CC: kernel: update 3.18 to 3.18.17
[15.05/openwrt.git] / target / linux / brcm2708 / patches-3.18 / 0004-Add-dwc_otg-driver.patch
1 From 9964a43723df02a84b7f132695193cd452d45b58 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Wed, 1 May 2013 19:46:17 +0100
4 Subject: [PATCH 004/114] Add dwc_otg driver
5
6 Signed-off-by: popcornmix <popcornmix@gmail.com>
7
8 usb: dwc: fix lockdep false positive
9
10 Signed-off-by: Kari Suvanto <karis79@gmail.com>
11
12 usb: dwc: fix inconsistent lock state
13
14 Signed-off-by: Kari Suvanto <karis79@gmail.com>
15 ---
16  drivers/usb/Makefile                               |    1 +
17  drivers/usb/core/generic.c                         |    1 +
18  drivers/usb/core/message.c                         |   79 +
19  drivers/usb/core/otg_whitelist.h                   |  114 +-
20  drivers/usb/gadget/file_storage.c                  | 3676 ++++++++++
21  drivers/usb/host/Kconfig                           |   13 +
22  drivers/usb/host/Makefile                          |    2 +
23  drivers/usb/host/dwc_common_port/Makefile          |   58 +
24  drivers/usb/host/dwc_common_port/Makefile.fbsd     |   17 +
25  drivers/usb/host/dwc_common_port/Makefile.linux    |   49 +
26  drivers/usb/host/dwc_common_port/changes.txt       |  174 +
27  drivers/usb/host/dwc_common_port/doc/doxygen.cfg   |  270 +
28  drivers/usb/host/dwc_common_port/dwc_cc.c          |  532 ++
29  drivers/usb/host/dwc_common_port/dwc_cc.h          |  224 +
30  drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++
31  .../usb/host/dwc_common_port/dwc_common_linux.c    | 1429 ++++
32  drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++
33  drivers/usb/host/dwc_common_port/dwc_crypto.c      |  308 +
34  drivers/usb/host/dwc_common_port/dwc_crypto.h      |  111 +
35  drivers/usb/host/dwc_common_port/dwc_dh.c          |  291 +
36  drivers/usb/host/dwc_common_port/dwc_dh.h          |  106 +
37  drivers/usb/host/dwc_common_port/dwc_list.h        |  594 ++
38  drivers/usb/host/dwc_common_port/dwc_mem.c         |  245 +
39  drivers/usb/host/dwc_common_port/dwc_modpow.c      |  636 ++
40  drivers/usb/host/dwc_common_port/dwc_modpow.h      |   34 +
41  drivers/usb/host/dwc_common_port/dwc_notifier.c    |  319 +
42  drivers/usb/host/dwc_common_port/dwc_notifier.h    |  122 +
43  drivers/usb/host/dwc_common_port/dwc_os.h          | 1274 ++++
44  drivers/usb/host/dwc_common_port/usb.h             |  946 +++
45  drivers/usb/host/dwc_otg/Makefile                  |   80 +
46  drivers/usb/host/dwc_otg/doc/doxygen.cfg           |  224 +
47  drivers/usb/host/dwc_otg/dummy_audio.c             | 1575 +++++
48  drivers/usb/host/dwc_otg/dwc_cfi_common.h          |  142 +
49  drivers/usb/host/dwc_otg/dwc_otg_adp.c             |  854 +++
50  drivers/usb/host/dwc_otg/dwc_otg_adp.h             |   80 +
51  drivers/usb/host/dwc_otg/dwc_otg_attr.c            | 1210 ++++
52  drivers/usb/host/dwc_otg/dwc_otg_attr.h            |   89 +
53  drivers/usb/host/dwc_otg/dwc_otg_cfi.c             | 1876 +++++
54  drivers/usb/host/dwc_otg/dwc_otg_cfi.h             |  320 +
55  drivers/usb/host/dwc_otg/dwc_otg_cil.c             | 7151 ++++++++++++++++++++
56  drivers/usb/host/dwc_otg/dwc_otg_cil.h             | 1464 ++++
57  drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c        | 1563 +++++
58  drivers/usb/host/dwc_otg/dwc_otg_core_if.h         |  705 ++
59  drivers/usb/host/dwc_otg/dwc_otg_dbg.h             |  116 +
60  drivers/usb/host/dwc_otg/dwc_otg_driver.c          | 1700 +++++
61  drivers/usb/host/dwc_otg/dwc_otg_driver.h          |   86 +
62  drivers/usb/host/dwc_otg/dwc_otg_hcd.c             | 3479 ++++++++++
63  drivers/usb/host/dwc_otg/dwc_otg_hcd.h             |  824 +++
64  drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c        | 1133 ++++
65  drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h          |  412 ++
66  drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c        | 2106 ++++++
67  drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c       |  893 +++
68  drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c       |  923 +++
69  drivers/usb/host/dwc_otg/dwc_otg_os_dep.h          |  185 +
70  drivers/usb/host/dwc_otg/dwc_otg_pcd.c             | 2712 ++++++++
71  drivers/usb/host/dwc_otg/dwc_otg_pcd.h             |  266 +
72  drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h          |  360 +
73  drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c        | 5147 ++++++++++++++
74  drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c       | 1358 ++++
75  drivers/usb/host/dwc_otg/dwc_otg_regs.h            | 2550 +++++++
76  drivers/usb/host/dwc_otg/test/Makefile             |   16 +
77  drivers/usb/host/dwc_otg/test/dwc_otg_test.pm      |  337 +
78  drivers/usb/host/dwc_otg/test/test_mod_param.pl    |  133 +
79  drivers/usb/host/dwc_otg/test/test_sysfs.pl        |  193 +
80  64 files changed, 56458 insertions(+), 12 deletions(-)
81  create mode 100644 drivers/usb/gadget/file_storage.c
82  create mode 100644 drivers/usb/host/dwc_common_port/Makefile
83  create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd
84  create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux
85  create mode 100644 drivers/usb/host/dwc_common_port/changes.txt
86  create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg
87  create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c
88  create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h
89  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
90  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c
91  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
92  create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c
93  create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h
94  create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c
95  create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h
96  create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h
97  create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c
98  create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c
99  create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h
100  create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c
101  create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h
102  create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h
103  create mode 100644 drivers/usb/host/dwc_common_port/usb.h
104  create mode 100644 drivers/usb/host/dwc_otg/Makefile
105  create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg
106  create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c
107  create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h
108  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.c
109  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.h
110  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c
111  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h
112  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c
113  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h
114  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c
115  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h
116  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
117  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h
118  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
119  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c
120  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h
121  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
122  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h
123  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
124  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
125  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
126  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
127  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
128  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
129  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c
130  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h
131  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
132  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
133  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
134  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h
135  create mode 100644 drivers/usb/host/dwc_otg/test/Makefile
136  create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
137  create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl
138  create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl
139
140 --- a/drivers/usb/Makefile
141 +++ b/drivers/usb/Makefile
142 @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_U132_HCD)    += host/
143  obj-$(CONFIG_USB_R8A66597_HCD) += host/
144  obj-$(CONFIG_USB_HWA_HCD)      += host/
145  obj-$(CONFIG_USB_ISP1760_HCD)  += host/
146 +obj-$(CONFIG_USB_DWCOTG)       += host/
147  obj-$(CONFIG_USB_IMX21_HCD)    += host/
148  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += host/
149  obj-$(CONFIG_USB_FUSBH200_HCD) += host/
150 --- a/drivers/usb/core/generic.c
151 +++ b/drivers/usb/core/generic.c
152 @@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_
153                 dev_warn(&udev->dev,
154                         "no configuration chosen from %d choice%s\n",
155                         num_configs, plural(num_configs));
156 +               dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
157         }
158         return i;
159  }
160 --- a/drivers/usb/core/message.c
161 +++ b/drivers/usb/core/message.c
162 @@ -1872,6 +1872,85 @@ free_interfaces:
163         if (cp->string == NULL &&
164                         !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
165                 cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
166 +/* Uncomment this define to enable the HS Electrical Test support */
167 +#define DWC_HS_ELECT_TST 1
168 +#ifdef DWC_HS_ELECT_TST
169 +               /* Here we implement the HS Electrical Test support. The
170 +                * tester uses a vendor ID of 0x1A0A to indicate we should
171 +                * run a special test sequence. The product ID tells us
172 +                * which sequence to run. We invoke the test sequence by
173 +                * sending a non-standard SetFeature command to our root
174 +                * hub port. Our dwc_otg_hcd_hub_control() routine will
175 +                * recognize the command and perform the desired test
176 +                * sequence.
177 +                */
178 +               if (dev->descriptor.idVendor == 0x1A0A) {
179 +                       /* HSOTG Electrical Test */
180 +                       dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
181 +
182 +                       if (dev->bus && dev->bus->root_hub) {
183 +                               struct usb_device *hdev = dev->bus->root_hub;
184 +                               dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
185 +
186 +                               switch (dev->descriptor.idProduct) {
187 +                               case 0x0101:    /* TEST_SE0_NAK */
188 +                                       dev_warn(&dev->dev, "TEST_SE0_NAK\n");
189 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
190 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
191 +                                                       USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
192 +                                       break;
193 +
194 +                               case 0x0102:    /* TEST_J */
195 +                                       dev_warn(&dev->dev, "TEST_J\n");
196 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
197 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
198 +                                                       USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
199 +                                       break;
200 +
201 +                               case 0x0103:    /* TEST_K */
202 +                                       dev_warn(&dev->dev, "TEST_K\n");
203 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
204 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
205 +                                                       USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
206 +                                       break;
207 +
208 +                               case 0x0104:    /* TEST_PACKET */
209 +                                       dev_warn(&dev->dev, "TEST_PACKET\n");
210 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
211 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
212 +                                                       USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
213 +                                       break;
214 +
215 +                               case 0x0105:    /* TEST_FORCE_ENABLE */
216 +                                       dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
217 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
218 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
219 +                                                       USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
220 +                                       break;
221 +
222 +                               case 0x0106:    /* HS_HOST_PORT_SUSPEND_RESUME */
223 +                                       dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
224 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
225 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
226 +                                                       USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
227 +                                       break;
228 +
229 +                               case 0x0107:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
230 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
231 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
232 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
233 +                                                       USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
234 +                                       break;
235 +
236 +                               case 0x0108:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
237 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
238 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
239 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
240 +                                                       USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
241 +                               }
242 +                       }
243 +               }
244 +#endif /* DWC_HS_ELECT_TST */
245  
246         /* Now that the interfaces are installed, re-enable LPM. */
247         usb_unlocked_enable_lpm(dev);
248 --- a/drivers/usb/core/otg_whitelist.h
249 +++ b/drivers/usb/core/otg_whitelist.h
250 @@ -19,33 +19,82 @@
251  static struct usb_device_id whitelist_table [] = {
252  
253  /* hubs are optional in OTG, but very handy ... */
254 +#define CERT_WITHOUT_HUBS
255 +#if defined(CERT_WITHOUT_HUBS)
256 +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
257 +#else
258  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
259  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
260 +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
261 +#endif
262  
263  #ifdef CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
264  /* FIXME actually, printers are NOT supposed to use device classes;
265   * they're supposed to use interface classes...
266   */
267 -{ USB_DEVICE_INFO(7, 1, 1) },
268 -{ USB_DEVICE_INFO(7, 1, 2) },
269 -{ USB_DEVICE_INFO(7, 1, 3) },
270 +//{ USB_DEVICE_INFO(7, 1, 1) },
271 +//{ USB_DEVICE_INFO(7, 1, 2) },
272 +//{ USB_DEVICE_INFO(7, 1, 3) },
273  #endif
274  
275  #ifdef CONFIG_USB_NET_CDCETHER
276  /* Linux-USB CDC Ethernet gadget */
277 -{ USB_DEVICE(0x0525, 0xa4a1), },
278 +//{ USB_DEVICE(0x0525, 0xa4a1), },
279  /* Linux-USB CDC Ethernet + RNDIS gadget */
280 -{ USB_DEVICE(0x0525, 0xa4a2), },
281 +//{ USB_DEVICE(0x0525, 0xa4a2), },
282  #endif
283  
284  #if    defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
285  /* gadget zero, for testing */
286 -{ USB_DEVICE(0x0525, 0xa4a0), },
287 +//{ USB_DEVICE(0x0525, 0xa4a0), },
288  #endif
289  
290 +/* OPT Tester */
291 +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
292 +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
293 +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
294 +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
295 +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
296 +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */
297 +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
298 +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
299 +
300 +/* Sony cameras */
301 +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
302 +
303 +/* Memory Devices */
304 +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
305 +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
306 +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
307 +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */
308 +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
309 +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
310 +
311 +/* HP Printers */
312 +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
313 +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
314 +
315 +/* Speakers */
316 +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
317 +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
318 +
319  { }    /* Terminating entry */
320  };
321  
322 +static inline void report_errors(struct usb_device *dev)
323 +{
324 +       /* OTG MESSAGE: report errors here, customize to match your product */
325 +       dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
326 +                le16_to_cpu(dev->descriptor.idVendor),
327 +                le16_to_cpu(dev->descriptor.idProduct));
328 +        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
329 +                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
330 +        } else {
331 +                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
332 +        }
333 +}
334 +
335 +
336  static int is_targeted(struct usb_device *dev)
337  {
338         struct usb_device_id    *id = whitelist_table;
339 @@ -95,16 +144,57 @@ static int is_targeted(struct usb_device
340                         continue;
341  
342                 return 1;
343 -       }
344 +               /* NOTE: can't use usb_match_id() since interface caches
345 +                * aren't set up yet. this is cut/paste from that code.
346 +                */
347 +               for (id = whitelist_table; id->match_flags; id++) {
348 +#ifdef DEBUG
349 +                       dev_dbg(&dev->dev,
350 +                               "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
351 +                               id->idVendor,
352 +                               id->idProduct,
353 +                               id->bDeviceClass,
354 +                               id->bDeviceSubClass,
355 +                               id->bDeviceProtocol);
356 +#endif
357  
358 -       /* add other match criteria here ... */
359 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
360 +                           id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
361 +                               continue;
362 +
363 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
364 +                           id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
365 +                               continue;
366 +
367 +                       /* No need to test id->bcdDevice_lo != 0, since 0 is never
368 +                          greater than any unsigned number. */
369 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
370 +                           (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
371 +                               continue;
372 +
373 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
374 +                           (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
375 +                               continue;
376 +
377 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
378 +                           (id->bDeviceClass != dev->descriptor.bDeviceClass))
379 +                               continue;
380 +
381 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
382 +                           (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
383 +                               continue;
384 +
385 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
386 +                           (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
387 +                               continue;
388  
389 +                       return 1;
390 +               }
391 +       }
392  
393 -       /* OTG MESSAGE: report errors here, customize to match your product */
394 -       dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
395 -               le16_to_cpu(dev->descriptor.idVendor),
396 -               le16_to_cpu(dev->descriptor.idProduct));
397 +       /* add other match criteria here ... */
398  
399 +       report_errors(dev);
400         return 0;
401  }
402  
403 --- /dev/null
404 +++ b/drivers/usb/gadget/file_storage.c
405 @@ -0,0 +1,3676 @@
406 +/*
407 + * file_storage.c -- File-backed USB Storage Gadget, for USB development
408 + *
409 + * Copyright (C) 2003-2008 Alan Stern
410 + * All rights reserved.
411 + *
412 + * Redistribution and use in source and binary forms, with or without
413 + * modification, are permitted provided that the following conditions
414 + * are met:
415 + * 1. Redistributions of source code must retain the above copyright
416 + *    notice, this list of conditions, and the following disclaimer,
417 + *    without modification.
418 + * 2. Redistributions in binary form must reproduce the above copyright
419 + *    notice, this list of conditions and the following disclaimer in the
420 + *    documentation and/or other materials provided with the distribution.
421 + * 3. The names of the above-listed copyright holders may not be used
422 + *    to endorse or promote products derived from this software without
423 + *    specific prior written permission.
424 + *
425 + * ALTERNATIVELY, this software may be distributed under the terms of the
426 + * GNU General Public License ("GPL") as published by the Free Software
427 + * Foundation, either version 2 of that License or (at your option) any
428 + * later version.
429 + *
430 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
431 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
432 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
433 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
434 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
435 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
436 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
437 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
438 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
439 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
440 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
441 + */
442 +
443 +
444 +/*
445 + * The File-backed Storage Gadget acts as a USB Mass Storage device,
446 + * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
447 + * to providing an example of a genuinely useful gadget driver for a USB
448 + * device, it also illustrates a technique of double-buffering for increased
449 + * throughput.  Last but not least, it gives an easy way to probe the
450 + * behavior of the Mass Storage drivers in a USB host.
451 + *
452 + * Backing storage is provided by a regular file or a block device, specified
453 + * by the "file" module parameter.  Access can be limited to read-only by
454 + * setting the optional "ro" module parameter.  (For CD-ROM emulation,
455 + * access is always read-only.)  The gadget will indicate that it has
456 + * removable media if the optional "removable" module parameter is set.
457 + *
458 + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
459 + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
460 + * by the optional "transport" module parameter.  It also supports the
461 + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
462 + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
463 + * the optional "protocol" module parameter.  In addition, the default
464 + * Vendor ID, Product ID, release number and serial number can be overridden.
465 + *
466 + * There is support for multiple logical units (LUNs), each of which has
467 + * its own backing file.  The number of LUNs can be set using the optional
468 + * "luns" module parameter (anywhere from 1 to 8), and the corresponding
469 + * files are specified using comma-separated lists for "file" and "ro".
470 + * The default number of LUNs is taken from the number of "file" elements;
471 + * it is 1 if "file" is not given.  If "removable" is not set then a backing
472 + * file must be specified for each LUN.  If it is set, then an unspecified
473 + * or empty backing filename means the LUN's medium is not loaded.  Ideally
474 + * each LUN would be settable independently as a disk drive or a CD-ROM
475 + * drive, but currently all LUNs have to be the same type.  The CD-ROM
476 + * emulation includes a single data track and no audio tracks; hence there
477 + * need be only one backing file per LUN.
478 + *
479 + * Requirements are modest; only a bulk-in and a bulk-out endpoint are
480 + * needed (an interrupt-out endpoint is also needed for CBI).  The memory
481 + * requirement amounts to two 16K buffers, size configurable by a parameter.
482 + * Support is included for both full-speed and high-speed operation.
483 + *
484 + * Note that the driver is slightly non-portable in that it assumes a
485 + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
486 + * interrupt-in endpoints.  With most device controllers this isn't an
487 + * issue, but there may be some with hardware restrictions that prevent
488 + * a buffer from being used by more than one endpoint.
489 + *
490 + * Module options:
491 + *
492 + *     file=filename[,filename...]
493 + *                             Required if "removable" is not set, names of
494 + *                                     the files or block devices used for
495 + *                                     backing storage
496 + *     serial=HHHH...          Required serial number (string of hex chars)
497 + *     ro=b[,b...]             Default false, booleans for read-only access
498 + *     removable               Default false, boolean for removable media
499 + *     luns=N                  Default N = number of filenames, number of
500 + *                                     LUNs to support
501 + *     nofua=b[,b...]          Default false, booleans for ignore FUA flag
502 + *                                     in SCSI WRITE(10,12) commands
503 + *     stall                   Default determined according to the type of
504 + *                                     USB device controller (usually true),
505 + *                                     boolean to permit the driver to halt
506 + *                                     bulk endpoints
507 + *     cdrom                   Default false, boolean for whether to emulate
508 + *                                     a CD-ROM drive
509 + *     transport=XXX           Default BBB, transport name (CB, CBI, or BBB)
510 + *     protocol=YYY            Default SCSI, protocol name (RBC, 8020 or
511 + *                                     ATAPI, QIC, UFI, 8070, or SCSI;
512 + *                                     also 1 - 6)
513 + *     vendor=0xVVVV           Default 0x0525 (NetChip), USB Vendor ID
514 + *     product=0xPPPP          Default 0xa4a5 (FSG), USB Product ID
515 + *     release=0xRRRR          Override the USB release number (bcdDevice)
516 + *     buflen=N                Default N=16384, buffer size used (will be
517 + *                                     rounded down to a multiple of
518 + *                                     PAGE_CACHE_SIZE)
519 + *
520 + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
521 + * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
522 + * default values are used for everything else.
523 + *
524 + * The pathnames of the backing files and the ro settings are available in
525 + * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
526 + * the gadget's sysfs directory.  If the "removable" option is set, writing to
527 + * these files will simulate ejecting/loading the medium (writing an empty
528 + * line means eject) and adjusting a write-enable tab.  Changes to the ro
529 + * setting are not allowed when the medium is loaded or if CD-ROM emulation
530 + * is being used.
531 + *
532 + * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
533 + * The driver's SCSI command interface was based on the "Information
534 + * technology - Small Computer System Interface - 2" document from
535 + * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
536 + * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
537 + * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
538 + * "Universal Serial Bus Mass Storage Class UFI Command Specification"
539 + * document, Revision 1.0, December 14, 1998, available at
540 + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
541 + */
542 +
543 +
544 +/*
545 + *                             Driver Design
546 + *
547 + * The FSG driver is fairly straightforward.  There is a main kernel
548 + * thread that handles most of the work.  Interrupt routines field
549 + * callbacks from the controller driver: bulk- and interrupt-request
550 + * completion notifications, endpoint-0 events, and disconnect events.
551 + * Completion events are passed to the main thread by wakeup calls.  Many
552 + * ep0 requests are handled at interrupt time, but SetInterface,
553 + * SetConfiguration, and device reset requests are forwarded to the
554 + * thread in the form of "exceptions" using SIGUSR1 signals (since they
555 + * should interrupt any ongoing file I/O operations).
556 + *
557 + * The thread's main routine implements the standard command/data/status
558 + * parts of a SCSI interaction.  It and its subroutines are full of tests
559 + * for pending signals/exceptions -- all this polling is necessary since
560 + * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
561 + * indication that the driver really wants to be running in userspace.)
562 + * An important point is that so long as the thread is alive it keeps an
563 + * open reference to the backing file.  This will prevent unmounting
564 + * the backing file's underlying filesystem and could cause problems
565 + * during system shutdown, for example.  To prevent such problems, the
566 + * thread catches INT, TERM, and KILL signals and converts them into
567 + * an EXIT exception.
568 + *
569 + * In normal operation the main thread is started during the gadget's
570 + * fsg_bind() callback and stopped during fsg_unbind().  But it can also
571 + * exit when it receives a signal, and there's no point leaving the
572 + * gadget running when the thread is dead.  So just before the thread
573 + * exits, it deregisters the gadget driver.  This makes things a little
574 + * tricky: The driver is deregistered at two places, and the exiting
575 + * thread can indirectly call fsg_unbind() which in turn can tell the
576 + * thread to exit.  The first problem is resolved through the use of the
577 + * REGISTERED atomic bitflag; the driver will only be deregistered once.
578 + * The second problem is resolved by having fsg_unbind() check
579 + * fsg->state; it won't try to stop the thread if the state is already
580 + * FSG_STATE_TERMINATED.
581 + *
582 + * To provide maximum throughput, the driver uses a circular pipeline of
583 + * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
584 + * arbitrarily long; in practice the benefits don't justify having more
585 + * than 2 stages (i.e., double buffering).  But it helps to think of the
586 + * pipeline as being a long one.  Each buffer head contains a bulk-in and
587 + * a bulk-out request pointer (since the buffer can be used for both
588 + * output and input -- directions always are given from the host's
589 + * point of view) as well as a pointer to the buffer and various state
590 + * variables.
591 + *
592 + * Use of the pipeline follows a simple protocol.  There is a variable
593 + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
594 + * At any time that buffer head may still be in use from an earlier
595 + * request, so each buffer head has a state variable indicating whether
596 + * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
597 + * buffer head to be EMPTY, filling the buffer either by file I/O or by
598 + * USB I/O (during which the buffer head is BUSY), and marking the buffer
599 + * head FULL when the I/O is complete.  Then the buffer will be emptied
600 + * (again possibly by USB I/O, during which it is marked BUSY) and
601 + * finally marked EMPTY again (possibly by a completion routine).
602 + *
603 + * A module parameter tells the driver to avoid stalling the bulk
604 + * endpoints wherever the transport specification allows.  This is
605 + * necessary for some UDCs like the SuperH, which cannot reliably clear a
606 + * halt on a bulk endpoint.  However, under certain circumstances the
607 + * Bulk-only specification requires a stall.  In such cases the driver
608 + * will halt the endpoint and set a flag indicating that it should clear
609 + * the halt in software during the next device reset.  Hopefully this
610 + * will permit everything to work correctly.  Furthermore, although the
611 + * specification allows the bulk-out endpoint to halt when the host sends
612 + * too much data, implementing this would cause an unavoidable race.
613 + * The driver will always use the "no-stall" approach for OUT transfers.
614 + *
615 + * One subtle point concerns sending status-stage responses for ep0
616 + * requests.  Some of these requests, such as device reset, can involve
617 + * interrupting an ongoing file I/O operation, which might take an
618 + * arbitrarily long time.  During that delay the host might give up on
619 + * the original ep0 request and issue a new one.  When that happens the
620 + * driver should not notify the host about completion of the original
621 + * request, as the host will no longer be waiting for it.  So the driver
622 + * assigns to each ep0 request a unique tag, and it keeps track of the
623 + * tag value of the request associated with a long-running exception
624 + * (device-reset, interface-change, or configuration-change).  When the
625 + * exception handler is finished, the status-stage response is submitted
626 + * only if the current ep0 request tag is equal to the exception request
627 + * tag.  Thus only the most recently received ep0 request will get a
628 + * status-stage response.
629 + *
630 + * Warning: This driver source file is too long.  It ought to be split up
631 + * into a header file plus about 3 separate .c files, to handle the details
632 + * of the Gadget, USB Mass Storage, and SCSI protocols.
633 + */
634 +
635 +
636 +/* #define VERBOSE_DEBUG */
637 +/* #define DUMP_MSGS */
638 +
639 +
640 +#include <linux/blkdev.h>
641 +#include <linux/completion.h>
642 +#include <linux/dcache.h>
643 +#include <linux/delay.h>
644 +#include <linux/device.h>
645 +#include <linux/fcntl.h>
646 +#include <linux/file.h>
647 +#include <linux/fs.h>
648 +#include <linux/kref.h>
649 +#include <linux/kthread.h>
650 +#include <linux/limits.h>
651 +#include <linux/module.h>
652 +#include <linux/rwsem.h>
653 +#include <linux/slab.h>
654 +#include <linux/spinlock.h>
655 +#include <linux/string.h>
656 +#include <linux/freezer.h>
657 +#include <linux/utsname.h>
658 +
659 +#include <linux/usb/ch9.h>
660 +#include <linux/usb/gadget.h>
661 +
662 +#include "gadget_chips.h"
663 +
664 +
665 +
666 +/*
667 + * Kbuild is not very cooperative with respect to linking separately
668 + * compiled library objects into one module.  So for now we won't use
669 + * separate compilation ... ensuring init/exit sections work to shrink
670 + * the runtime footprint, and giving us at least some parts of what
671 + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
672 + */
673 +#include "usbstring.c"
674 +#include "config.c"
675 +#include "epautoconf.c"
676 +
677 +/*-------------------------------------------------------------------------*/
678 +
679 +#define DRIVER_DESC            "File-backed Storage Gadget"
680 +#define DRIVER_NAME            "g_file_storage"
681 +#define DRIVER_VERSION         "1 September 2010"
682 +
683 +static       char fsg_string_manufacturer[64];
684 +static const char fsg_string_product[] = DRIVER_DESC;
685 +static const char fsg_string_config[] = "Self-powered";
686 +static const char fsg_string_interface[] = "Mass Storage";
687 +
688 +
689 +#include "storage_common.c"
690 +
691 +
692 +MODULE_DESCRIPTION(DRIVER_DESC);
693 +MODULE_AUTHOR("Alan Stern");
694 +MODULE_LICENSE("Dual BSD/GPL");
695 +
696 +/*
697 + * This driver assumes self-powered hardware and has no way for users to
698 + * trigger remote wakeup.  It uses autoconfiguration to select endpoints
699 + * and endpoint addresses.
700 + */
701 +
702 +
703 +/*-------------------------------------------------------------------------*/
704 +
705 +
706 +/* Encapsulate the module parameter settings */
707 +
708 +static struct {
709 +       char            *file[FSG_MAX_LUNS];
710 +       char            *serial;
711 +       bool            ro[FSG_MAX_LUNS];
712 +       bool            nofua[FSG_MAX_LUNS];
713 +       unsigned int    num_filenames;
714 +       unsigned int    num_ros;
715 +       unsigned int    num_nofuas;
716 +       unsigned int    nluns;
717 +
718 +       bool            removable;
719 +       bool            can_stall;
720 +       bool            cdrom;
721 +
722 +       char            *transport_parm;
723 +       char            *protocol_parm;
724 +       unsigned short  vendor;
725 +       unsigned short  product;
726 +       unsigned short  release;
727 +       unsigned int    buflen;
728 +
729 +       int             transport_type;
730 +       char            *transport_name;
731 +       int             protocol_type;
732 +       char            *protocol_name;
733 +
734 +} mod_data = {                                 // Default values
735 +       .transport_parm         = "BBB",
736 +       .protocol_parm          = "SCSI",
737 +       .removable              = 0,
738 +       .can_stall              = 1,
739 +       .cdrom                  = 0,
740 +       .vendor                 = FSG_VENDOR_ID,
741 +       .product                = FSG_PRODUCT_ID,
742 +       .release                = 0xffff,       // Use controller chip type
743 +       .buflen                 = 16384,
744 +       };
745 +
746 +
747 +module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
748 +               S_IRUGO);
749 +MODULE_PARM_DESC(file, "names of backing files or devices");
750 +
751 +module_param_named(serial, mod_data.serial, charp, S_IRUGO);
752 +MODULE_PARM_DESC(serial, "USB serial number");
753 +
754 +module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
755 +MODULE_PARM_DESC(ro, "true to force read-only");
756 +
757 +module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
758 +               S_IRUGO);
759 +MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
760 +
761 +module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
762 +MODULE_PARM_DESC(luns, "number of LUNs");
763 +
764 +module_param_named(removable, mod_data.removable, bool, S_IRUGO);
765 +MODULE_PARM_DESC(removable, "true to simulate removable media");
766 +
767 +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
768 +MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
769 +
770 +module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
771 +MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
772 +
773 +/* In the non-TEST version, only the module parameters listed above
774 + * are available. */
775 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
776 +
777 +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
778 +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
779 +
780 +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
781 +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
782 +               "8070, or SCSI)");
783 +
784 +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
785 +MODULE_PARM_DESC(vendor, "USB Vendor ID");
786 +
787 +module_param_named(product, mod_data.product, ushort, S_IRUGO);
788 +MODULE_PARM_DESC(product, "USB Product ID");
789 +
790 +module_param_named(release, mod_data.release, ushort, S_IRUGO);
791 +MODULE_PARM_DESC(release, "USB release number");
792 +
793 +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
794 +MODULE_PARM_DESC(buflen, "I/O buffer size");
795 +
796 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
797 +
798 +
799 +/*
800 + * These definitions will permit the compiler to avoid generating code for
801 + * parts of the driver that aren't used in the non-TEST version.  Even gcc
802 + * can recognize when a test of a constant expression yields a dead code
803 + * path.
804 + */
805 +
806 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
807 +
808 +#define transport_is_bbb()     (mod_data.transport_type == USB_PR_BULK)
809 +#define transport_is_cbi()     (mod_data.transport_type == USB_PR_CBI)
810 +#define protocol_is_scsi()     (mod_data.protocol_type == USB_SC_SCSI)
811 +
812 +#else
813 +
814 +#define transport_is_bbb()     1
815 +#define transport_is_cbi()     0
816 +#define protocol_is_scsi()     1
817 +
818 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
819 +
820 +
821 +/*-------------------------------------------------------------------------*/
822 +
823 +
824 +struct fsg_dev {
825 +       /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
826 +       spinlock_t              lock;
827 +       struct usb_gadget       *gadget;
828 +
829 +       /* filesem protects: backing files in use */
830 +       struct rw_semaphore     filesem;
831 +
832 +       /* reference counting: wait until all LUNs are released */
833 +       struct kref             ref;
834 +
835 +       struct usb_ep           *ep0;           // Handy copy of gadget->ep0
836 +       struct usb_request      *ep0req;        // For control responses
837 +       unsigned int            ep0_req_tag;
838 +       const char              *ep0req_name;
839 +
840 +       struct usb_request      *intreq;        // For interrupt responses
841 +       int                     intreq_busy;
842 +       struct fsg_buffhd       *intr_buffhd;
843 +
844 +       unsigned int            bulk_out_maxpacket;
845 +       enum fsg_state          state;          // For exception handling
846 +       unsigned int            exception_req_tag;
847 +
848 +       u8                      config, new_config;
849 +
850 +       unsigned int            running : 1;
851 +       unsigned int            bulk_in_enabled : 1;
852 +       unsigned int            bulk_out_enabled : 1;
853 +       unsigned int            intr_in_enabled : 1;
854 +       unsigned int            phase_error : 1;
855 +       unsigned int            short_packet_received : 1;
856 +       unsigned int            bad_lun_okay : 1;
857 +
858 +       unsigned long           atomic_bitflags;
859 +#define REGISTERED             0
860 +#define IGNORE_BULK_OUT                1
861 +#define SUSPENDED              2
862 +
863 +       struct usb_ep           *bulk_in;
864 +       struct usb_ep           *bulk_out;
865 +       struct usb_ep           *intr_in;
866 +
867 +       struct fsg_buffhd       *next_buffhd_to_fill;
868 +       struct fsg_buffhd       *next_buffhd_to_drain;
869 +
870 +       int                     thread_wakeup_needed;
871 +       struct completion       thread_notifier;
872 +       struct task_struct      *thread_task;
873 +
874 +       int                     cmnd_size;
875 +       u8                      cmnd[MAX_COMMAND_SIZE];
876 +       enum data_direction     data_dir;
877 +       u32                     data_size;
878 +       u32                     data_size_from_cmnd;
879 +       u32                     tag;
880 +       unsigned int            lun;
881 +       u32                     residue;
882 +       u32                     usb_amount_left;
883 +
884 +       /* The CB protocol offers no way for a host to know when a command
885 +        * has completed.  As a result the next command may arrive early,
886 +        * and we will still have to handle it.  For that reason we need
887 +        * a buffer to store new commands when using CB (or CBI, which
888 +        * does not oblige a host to wait for command completion either). */
889 +       int                     cbbuf_cmnd_size;
890 +       u8                      cbbuf_cmnd[MAX_COMMAND_SIZE];
891 +
892 +       unsigned int            nluns;
893 +       struct fsg_lun          *luns;
894 +       struct fsg_lun          *curlun;
895 +       /* Must be the last entry */
896 +       struct fsg_buffhd       buffhds[];
897 +};
898 +
899 +typedef void (*fsg_routine_t)(struct fsg_dev *);
900 +
901 +static int exception_in_progress(struct fsg_dev *fsg)
902 +{
903 +       return (fsg->state > FSG_STATE_IDLE);
904 +}
905 +
906 +/* Make bulk-out requests be divisible by the maxpacket size */
907 +static void set_bulk_out_req_length(struct fsg_dev *fsg,
908 +               struct fsg_buffhd *bh, unsigned int length)
909 +{
910 +       unsigned int    rem;
911 +
912 +       bh->bulk_out_intended_length = length;
913 +       rem = length % fsg->bulk_out_maxpacket;
914 +       if (rem > 0)
915 +               length += fsg->bulk_out_maxpacket - rem;
916 +       bh->outreq->length = length;
917 +}
918 +
919 +static struct fsg_dev                  *the_fsg;
920 +static struct usb_gadget_driver                fsg_driver;
921 +
922 +
923 +/*-------------------------------------------------------------------------*/
924 +
925 +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
926 +{
927 +       const char      *name;
928 +
929 +       if (ep == fsg->bulk_in)
930 +               name = "bulk-in";
931 +       else if (ep == fsg->bulk_out)
932 +               name = "bulk-out";
933 +       else
934 +               name = ep->name;
935 +       DBG(fsg, "%s set halt\n", name);
936 +       return usb_ep_set_halt(ep);
937 +}
938 +
939 +
940 +/*-------------------------------------------------------------------------*/
941 +
942 +/*
943 + * DESCRIPTORS ... most are static, but strings and (full) configuration
944 + * descriptors are built on demand.  Also the (static) config and interface
945 + * descriptors are adjusted during fsg_bind().
946 + */
947 +
948 +/* There is only one configuration. */
949 +#define        CONFIG_VALUE            1
950 +
951 +static struct usb_device_descriptor
952 +device_desc = {
953 +       .bLength =              sizeof device_desc,
954 +       .bDescriptorType =      USB_DT_DEVICE,
955 +
956 +       .bcdUSB =               cpu_to_le16(0x0200),
957 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
958 +
959 +       /* The next three values can be overridden by module parameters */
960 +       .idVendor =             cpu_to_le16(FSG_VENDOR_ID),
961 +       .idProduct =            cpu_to_le16(FSG_PRODUCT_ID),
962 +       .bcdDevice =            cpu_to_le16(0xffff),
963 +
964 +       .iManufacturer =        FSG_STRING_MANUFACTURER,
965 +       .iProduct =             FSG_STRING_PRODUCT,
966 +       .iSerialNumber =        FSG_STRING_SERIAL,
967 +       .bNumConfigurations =   1,
968 +};
969 +
970 +static struct usb_config_descriptor
971 +config_desc = {
972 +       .bLength =              sizeof config_desc,
973 +       .bDescriptorType =      USB_DT_CONFIG,
974 +
975 +       /* wTotalLength computed by usb_gadget_config_buf() */
976 +       .bNumInterfaces =       1,
977 +       .bConfigurationValue =  CONFIG_VALUE,
978 +       .iConfiguration =       FSG_STRING_CONFIG,
979 +       .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
980 +       .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
981 +};
982 +
983 +
984 +static struct usb_qualifier_descriptor
985 +dev_qualifier = {
986 +       .bLength =              sizeof dev_qualifier,
987 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
988 +
989 +       .bcdUSB =               cpu_to_le16(0x0200),
990 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
991 +
992 +       .bNumConfigurations =   1,
993 +};
994 +
995 +static int populate_bos(struct fsg_dev *fsg, u8 *buf)
996 +{
997 +       memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
998 +       buf += USB_DT_BOS_SIZE;
999 +
1000 +       memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
1001 +       buf += USB_DT_USB_EXT_CAP_SIZE;
1002 +
1003 +       memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
1004 +
1005 +       return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
1006 +               + USB_DT_USB_EXT_CAP_SIZE;
1007 +}
1008 +
1009 +/*
1010 + * Config descriptors must agree with the code that sets configurations
1011 + * and with code managing interfaces and their altsettings.  They must
1012 + * also handle different speeds and other-speed requests.
1013 + */
1014 +static int populate_config_buf(struct usb_gadget *gadget,
1015 +               u8 *buf, u8 type, unsigned index)
1016 +{
1017 +       enum usb_device_speed                   speed = gadget->speed;
1018 +       int                                     len;
1019 +       const struct usb_descriptor_header      **function;
1020 +
1021 +       if (index > 0)
1022 +               return -EINVAL;
1023 +
1024 +       if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
1025 +               speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
1026 +       function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
1027 +               ? (const struct usb_descriptor_header **)fsg_hs_function
1028 +               : (const struct usb_descriptor_header **)fsg_fs_function;
1029 +
1030 +       /* for now, don't advertise srp-only devices */
1031 +       if (!gadget_is_otg(gadget))
1032 +               function++;
1033 +
1034 +       len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
1035 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
1036 +       return len;
1037 +}
1038 +
1039 +
1040 +/*-------------------------------------------------------------------------*/
1041 +
1042 +/* These routines may be called in process context or in_irq */
1043 +
1044 +/* Caller must hold fsg->lock */
1045 +static void wakeup_thread(struct fsg_dev *fsg)
1046 +{
1047 +       /* Tell the main thread that something has happened */
1048 +       fsg->thread_wakeup_needed = 1;
1049 +       if (fsg->thread_task)
1050 +               wake_up_process(fsg->thread_task);
1051 +}
1052 +
1053 +
1054 +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
1055 +{
1056 +       unsigned long           flags;
1057 +
1058 +       /* Do nothing if a higher-priority exception is already in progress.
1059 +        * If a lower-or-equal priority exception is in progress, preempt it
1060 +        * and notify the main thread by sending it a signal. */
1061 +       spin_lock_irqsave(&fsg->lock, flags);
1062 +       if (fsg->state <= new_state) {
1063 +               fsg->exception_req_tag = fsg->ep0_req_tag;
1064 +               fsg->state = new_state;
1065 +               if (fsg->thread_task)
1066 +                       send_sig_info(SIGUSR1, SEND_SIG_FORCED,
1067 +                                       fsg->thread_task);
1068 +       }
1069 +       spin_unlock_irqrestore(&fsg->lock, flags);
1070 +}
1071 +
1072 +
1073 +/*-------------------------------------------------------------------------*/
1074 +
1075 +/* The disconnect callback and ep0 routines.  These always run in_irq,
1076 + * except that ep0_queue() is called in the main thread to acknowledge
1077 + * completion of various requests: set config, set interface, and
1078 + * Bulk-only device reset. */
1079 +
1080 +static void fsg_disconnect(struct usb_gadget *gadget)
1081 +{
1082 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1083 +
1084 +       DBG(fsg, "disconnect or port reset\n");
1085 +       raise_exception(fsg, FSG_STATE_DISCONNECT);
1086 +}
1087 +
1088 +
1089 +static int ep0_queue(struct fsg_dev *fsg)
1090 +{
1091 +       int     rc;
1092 +
1093 +       rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
1094 +       if (rc != 0 && rc != -ESHUTDOWN) {
1095 +
1096 +               /* We can't do much more than wait for a reset */
1097 +               WARNING(fsg, "error in submission: %s --> %d\n",
1098 +                               fsg->ep0->name, rc);
1099 +       }
1100 +       return rc;
1101 +}
1102 +
1103 +static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
1104 +{
1105 +       struct fsg_dev          *fsg = ep->driver_data;
1106 +
1107 +       if (req->actual > 0)
1108 +               dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
1109 +       if (req->status || req->actual != req->length)
1110 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1111 +                               req->status, req->actual, req->length);
1112 +       if (req->status == -ECONNRESET)         // Request was cancelled
1113 +               usb_ep_fifo_flush(ep);
1114 +
1115 +       if (req->status == 0 && req->context)
1116 +               ((fsg_routine_t) (req->context))(fsg);
1117 +}
1118 +
1119 +
1120 +/*-------------------------------------------------------------------------*/
1121 +
1122 +/* Bulk and interrupt endpoint completion handlers.
1123 + * These always run in_irq. */
1124 +
1125 +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
1126 +{
1127 +       struct fsg_dev          *fsg = ep->driver_data;
1128 +       struct fsg_buffhd       *bh = req->context;
1129 +
1130 +       if (req->status || req->actual != req->length)
1131 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1132 +                               req->status, req->actual, req->length);
1133 +       if (req->status == -ECONNRESET)         // Request was cancelled
1134 +               usb_ep_fifo_flush(ep);
1135 +
1136 +       /* Hold the lock while we update the request and buffer states */
1137 +       smp_wmb();
1138 +       spin_lock(&fsg->lock);
1139 +       bh->inreq_busy = 0;
1140 +       bh->state = BUF_STATE_EMPTY;
1141 +       wakeup_thread(fsg);
1142 +       spin_unlock(&fsg->lock);
1143 +}
1144 +
1145 +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
1146 +{
1147 +       struct fsg_dev          *fsg = ep->driver_data;
1148 +       struct fsg_buffhd       *bh = req->context;
1149 +
1150 +       dump_msg(fsg, "bulk-out", req->buf, req->actual);
1151 +       if (req->status || req->actual != bh->bulk_out_intended_length)
1152 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1153 +                               req->status, req->actual,
1154 +                               bh->bulk_out_intended_length);
1155 +       if (req->status == -ECONNRESET)         // Request was cancelled
1156 +               usb_ep_fifo_flush(ep);
1157 +
1158 +       /* Hold the lock while we update the request and buffer states */
1159 +       smp_wmb();
1160 +       spin_lock(&fsg->lock);
1161 +       bh->outreq_busy = 0;
1162 +       bh->state = BUF_STATE_FULL;
1163 +       wakeup_thread(fsg);
1164 +       spin_unlock(&fsg->lock);
1165 +}
1166 +
1167 +
1168 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1169 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1170 +{
1171 +       struct fsg_dev          *fsg = ep->driver_data;
1172 +       struct fsg_buffhd       *bh = req->context;
1173 +
1174 +       if (req->status || req->actual != req->length)
1175 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1176 +                               req->status, req->actual, req->length);
1177 +       if (req->status == -ECONNRESET)         // Request was cancelled
1178 +               usb_ep_fifo_flush(ep);
1179 +
1180 +       /* Hold the lock while we update the request and buffer states */
1181 +       smp_wmb();
1182 +       spin_lock(&fsg->lock);
1183 +       fsg->intreq_busy = 0;
1184 +       bh->state = BUF_STATE_EMPTY;
1185 +       wakeup_thread(fsg);
1186 +       spin_unlock(&fsg->lock);
1187 +}
1188 +
1189 +#else
1190 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1191 +{}
1192 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1193 +
1194 +
1195 +/*-------------------------------------------------------------------------*/
1196 +
1197 +/* Ep0 class-specific handlers.  These always run in_irq. */
1198 +
1199 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1200 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1201 +{
1202 +       struct usb_request      *req = fsg->ep0req;
1203 +       static u8               cbi_reset_cmnd[6] = {
1204 +                       SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
1205 +
1206 +       /* Error in command transfer? */
1207 +       if (req->status || req->length != req->actual ||
1208 +                       req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
1209 +
1210 +               /* Not all controllers allow a protocol stall after
1211 +                * receiving control-out data, but we'll try anyway. */
1212 +               fsg_set_halt(fsg, fsg->ep0);
1213 +               return;                 // Wait for reset
1214 +       }
1215 +
1216 +       /* Is it the special reset command? */
1217 +       if (req->actual >= sizeof cbi_reset_cmnd &&
1218 +                       memcmp(req->buf, cbi_reset_cmnd,
1219 +                               sizeof cbi_reset_cmnd) == 0) {
1220 +
1221 +               /* Raise an exception to stop the current operation
1222 +                * and reinitialize our state. */
1223 +               DBG(fsg, "cbi reset request\n");
1224 +               raise_exception(fsg, FSG_STATE_RESET);
1225 +               return;
1226 +       }
1227 +
1228 +       VDBG(fsg, "CB[I] accept device-specific command\n");
1229 +       spin_lock(&fsg->lock);
1230 +
1231 +       /* Save the command for later */
1232 +       if (fsg->cbbuf_cmnd_size)
1233 +               WARNING(fsg, "CB[I] overwriting previous command\n");
1234 +       fsg->cbbuf_cmnd_size = req->actual;
1235 +       memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
1236 +
1237 +       wakeup_thread(fsg);
1238 +       spin_unlock(&fsg->lock);
1239 +}
1240 +
1241 +#else
1242 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1243 +{}
1244 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1245 +
1246 +
1247 +static int class_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 +       u16                     w_length = le16_to_cpu(ctrl->wLength);
1255 +
1256 +       if (!fsg->config)
1257 +               return value;
1258 +
1259 +       /* Handle Bulk-only class-specific requests */
1260 +       if (transport_is_bbb()) {
1261 +               switch (ctrl->bRequest) {
1262 +
1263 +               case US_BULK_RESET_REQUEST:
1264 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1265 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1266 +                               break;
1267 +                       if (w_index != 0 || w_value != 0 || w_length != 0) {
1268 +                               value = -EDOM;
1269 +                               break;
1270 +                       }
1271 +
1272 +                       /* Raise an exception to stop the current operation
1273 +                        * and reinitialize our state. */
1274 +                       DBG(fsg, "bulk reset request\n");
1275 +                       raise_exception(fsg, FSG_STATE_RESET);
1276 +                       value = DELAYED_STATUS;
1277 +                       break;
1278 +
1279 +               case US_BULK_GET_MAX_LUN:
1280 +                       if (ctrl->bRequestType != (USB_DIR_IN |
1281 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1282 +                               break;
1283 +                       if (w_index != 0 || w_value != 0 || w_length != 1) {
1284 +                               value = -EDOM;
1285 +                               break;
1286 +                       }
1287 +                       VDBG(fsg, "get max LUN\n");
1288 +                       *(u8 *) req->buf = fsg->nluns - 1;
1289 +                       value = 1;
1290 +                       break;
1291 +               }
1292 +       }
1293 +
1294 +       /* Handle CBI class-specific requests */
1295 +       else {
1296 +               switch (ctrl->bRequest) {
1297 +
1298 +               case USB_CBI_ADSC_REQUEST:
1299 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1300 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1301 +                               break;
1302 +                       if (w_index != 0 || w_value != 0) {
1303 +                               value = -EDOM;
1304 +                               break;
1305 +                       }
1306 +                       if (w_length > MAX_COMMAND_SIZE) {
1307 +                               value = -EOVERFLOW;
1308 +                               break;
1309 +                       }
1310 +                       value = w_length;
1311 +                       fsg->ep0req->context = received_cbi_adsc;
1312 +                       break;
1313 +               }
1314 +       }
1315 +
1316 +       if (value == -EOPNOTSUPP)
1317 +               VDBG(fsg,
1318 +                       "unknown class-specific control req "
1319 +                       "%02x.%02x v%04x i%04x l%u\n",
1320 +                       ctrl->bRequestType, ctrl->bRequest,
1321 +                       le16_to_cpu(ctrl->wValue), w_index, w_length);
1322 +       return value;
1323 +}
1324 +
1325 +
1326 +/*-------------------------------------------------------------------------*/
1327 +
1328 +/* Ep0 standard request handlers.  These always run in_irq. */
1329 +
1330 +static int standard_setup_req(struct fsg_dev *fsg,
1331 +               const struct usb_ctrlrequest *ctrl)
1332 +{
1333 +       struct usb_request      *req = fsg->ep0req;
1334 +       int                     value = -EOPNOTSUPP;
1335 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1336 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1337 +
1338 +       /* Usually this just stores reply data in the pre-allocated ep0 buffer,
1339 +        * but config change events will also reconfigure hardware. */
1340 +       switch (ctrl->bRequest) {
1341 +
1342 +       case USB_REQ_GET_DESCRIPTOR:
1343 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1344 +                               USB_RECIP_DEVICE))
1345 +                       break;
1346 +               switch (w_value >> 8) {
1347 +
1348 +               case USB_DT_DEVICE:
1349 +                       VDBG(fsg, "get device descriptor\n");
1350 +                       device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
1351 +                       value = sizeof device_desc;
1352 +                       memcpy(req->buf, &device_desc, value);
1353 +                       break;
1354 +               case USB_DT_DEVICE_QUALIFIER:
1355 +                       VDBG(fsg, "get device qualifier\n");
1356 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1357 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1358 +                               break;
1359 +                       /*
1360 +                        * Assume ep0 uses the same maxpacket value for both
1361 +                        * speeds
1362 +                        */
1363 +                       dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
1364 +                       value = sizeof dev_qualifier;
1365 +                       memcpy(req->buf, &dev_qualifier, value);
1366 +                       break;
1367 +
1368 +               case USB_DT_OTHER_SPEED_CONFIG:
1369 +                       VDBG(fsg, "get other-speed config descriptor\n");
1370 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1371 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1372 +                               break;
1373 +                       goto get_config;
1374 +               case USB_DT_CONFIG:
1375 +                       VDBG(fsg, "get configuration descriptor\n");
1376 +get_config:
1377 +                       value = populate_config_buf(fsg->gadget,
1378 +                                       req->buf,
1379 +                                       w_value >> 8,
1380 +                                       w_value & 0xff);
1381 +                       break;
1382 +
1383 +               case USB_DT_STRING:
1384 +                       VDBG(fsg, "get string descriptor\n");
1385 +
1386 +                       /* wIndex == language code */
1387 +                       value = usb_gadget_get_string(&fsg_stringtab,
1388 +                                       w_value & 0xff, req->buf);
1389 +                       break;
1390 +
1391 +               case USB_DT_BOS:
1392 +                       VDBG(fsg, "get bos descriptor\n");
1393 +
1394 +                       if (gadget_is_superspeed(fsg->gadget))
1395 +                               value = populate_bos(fsg, req->buf);
1396 +                       break;
1397 +               }
1398 +
1399 +               break;
1400 +
1401 +       /* One config, two speeds */
1402 +       case USB_REQ_SET_CONFIGURATION:
1403 +               if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
1404 +                               USB_RECIP_DEVICE))
1405 +                       break;
1406 +               VDBG(fsg, "set configuration\n");
1407 +               if (w_value == CONFIG_VALUE || w_value == 0) {
1408 +                       fsg->new_config = w_value;
1409 +
1410 +                       /* Raise an exception to wipe out previous transaction
1411 +                        * state (queued bufs, etc) and set the new config. */
1412 +                       raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
1413 +                       value = DELAYED_STATUS;
1414 +               }
1415 +               break;
1416 +       case USB_REQ_GET_CONFIGURATION:
1417 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1418 +                               USB_RECIP_DEVICE))
1419 +                       break;
1420 +               VDBG(fsg, "get configuration\n");
1421 +               *(u8 *) req->buf = fsg->config;
1422 +               value = 1;
1423 +               break;
1424 +
1425 +       case USB_REQ_SET_INTERFACE:
1426 +               if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
1427 +                               USB_RECIP_INTERFACE))
1428 +                       break;
1429 +               if (fsg->config && w_index == 0) {
1430 +
1431 +                       /* Raise an exception to wipe out previous transaction
1432 +                        * state (queued bufs, etc) and install the new
1433 +                        * interface altsetting. */
1434 +                       raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
1435 +                       value = DELAYED_STATUS;
1436 +               }
1437 +               break;
1438 +       case USB_REQ_GET_INTERFACE:
1439 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1440 +                               USB_RECIP_INTERFACE))
1441 +                       break;
1442 +               if (!fsg->config)
1443 +                       break;
1444 +               if (w_index != 0) {
1445 +                       value = -EDOM;
1446 +                       break;
1447 +               }
1448 +               VDBG(fsg, "get interface\n");
1449 +               *(u8 *) req->buf = 0;
1450 +               value = 1;
1451 +               break;
1452 +
1453 +       default:
1454 +               VDBG(fsg,
1455 +                       "unknown control req %02x.%02x v%04x i%04x l%u\n",
1456 +                       ctrl->bRequestType, ctrl->bRequest,
1457 +                       w_value, w_index, le16_to_cpu(ctrl->wLength));
1458 +       }
1459 +
1460 +       return value;
1461 +}
1462 +
1463 +
1464 +static int fsg_setup(struct usb_gadget *gadget,
1465 +               const struct usb_ctrlrequest *ctrl)
1466 +{
1467 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1468 +       int                     rc;
1469 +       int                     w_length = le16_to_cpu(ctrl->wLength);
1470 +
1471 +       ++fsg->ep0_req_tag;             // Record arrival of a new request
1472 +       fsg->ep0req->context = NULL;
1473 +       fsg->ep0req->length = 0;
1474 +       dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
1475 +
1476 +       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
1477 +               rc = class_setup_req(fsg, ctrl);
1478 +       else
1479 +               rc = standard_setup_req(fsg, ctrl);
1480 +
1481 +       /* Respond with data/status or defer until later? */
1482 +       if (rc >= 0 && rc != DELAYED_STATUS) {
1483 +               rc = min(rc, w_length);
1484 +               fsg->ep0req->length = rc;
1485 +               fsg->ep0req->zero = rc < w_length;
1486 +               fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
1487 +                               "ep0-in" : "ep0-out");
1488 +               rc = ep0_queue(fsg);
1489 +       }
1490 +
1491 +       /* Device either stalls (rc < 0) or reports success */
1492 +       return rc;
1493 +}
1494 +
1495 +
1496 +/*-------------------------------------------------------------------------*/
1497 +
1498 +/* All the following routines run in process context */
1499 +
1500 +
1501 +/* Use this for bulk or interrupt transfers, not ep0 */
1502 +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
1503 +               struct usb_request *req, int *pbusy,
1504 +               enum fsg_buffer_state *state)
1505 +{
1506 +       int     rc;
1507 +
1508 +       if (ep == fsg->bulk_in)
1509 +               dump_msg(fsg, "bulk-in", req->buf, req->length);
1510 +       else if (ep == fsg->intr_in)
1511 +               dump_msg(fsg, "intr-in", req->buf, req->length);
1512 +
1513 +       spin_lock_irq(&fsg->lock);
1514 +       *pbusy = 1;
1515 +       *state = BUF_STATE_BUSY;
1516 +       spin_unlock_irq(&fsg->lock);
1517 +       rc = usb_ep_queue(ep, req, GFP_KERNEL);
1518 +       if (rc != 0) {
1519 +               *pbusy = 0;
1520 +               *state = BUF_STATE_EMPTY;
1521 +
1522 +               /* We can't do much more than wait for a reset */
1523 +
1524 +               /* Note: currently the net2280 driver fails zero-length
1525 +                * submissions if DMA is enabled. */
1526 +               if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
1527 +                                               req->length == 0))
1528 +                       WARNING(fsg, "error in submission: %s --> %d\n",
1529 +                                       ep->name, rc);
1530 +       }
1531 +}
1532 +
1533 +
1534 +static int sleep_thread(struct fsg_dev *fsg)
1535 +{
1536 +       int     rc = 0;
1537 +
1538 +       /* Wait until a signal arrives or we are woken up */
1539 +       for (;;) {
1540 +               try_to_freeze();
1541 +               set_current_state(TASK_INTERRUPTIBLE);
1542 +               if (signal_pending(current)) {
1543 +                       rc = -EINTR;
1544 +                       break;
1545 +               }
1546 +               if (fsg->thread_wakeup_needed)
1547 +                       break;
1548 +               schedule();
1549 +       }
1550 +       __set_current_state(TASK_RUNNING);
1551 +       fsg->thread_wakeup_needed = 0;
1552 +       return rc;
1553 +}
1554 +
1555 +
1556 +/*-------------------------------------------------------------------------*/
1557 +
1558 +static int do_read(struct fsg_dev *fsg)
1559 +{
1560 +       struct fsg_lun          *curlun = fsg->curlun;
1561 +       u32                     lba;
1562 +       struct fsg_buffhd       *bh;
1563 +       int                     rc;
1564 +       u32                     amount_left;
1565 +       loff_t                  file_offset, file_offset_tmp;
1566 +       unsigned int            amount;
1567 +       ssize_t                 nread;
1568 +
1569 +       /* Get the starting Logical Block Address and check that it's
1570 +        * not too big */
1571 +       if (fsg->cmnd[0] == READ_6)
1572 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1573 +       else {
1574 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1575 +
1576 +               /* We allow DPO (Disable Page Out = don't save data in the
1577 +                * cache) and FUA (Force Unit Access = don't read from the
1578 +                * cache), but we don't implement them. */
1579 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1580 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1581 +                       return -EINVAL;
1582 +               }
1583 +       }
1584 +       if (lba >= curlun->num_sectors) {
1585 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1586 +               return -EINVAL;
1587 +       }
1588 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1589 +
1590 +       /* Carry out the file reads */
1591 +       amount_left = fsg->data_size_from_cmnd;
1592 +       if (unlikely(amount_left == 0))
1593 +               return -EIO;            // No default reply
1594 +
1595 +       for (;;) {
1596 +
1597 +               /* Figure out how much we need to read:
1598 +                * Try to read the remaining amount.
1599 +                * But don't read more than the buffer size.
1600 +                * And don't try to read past the end of the file.
1601 +                */
1602 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1603 +               amount = min((loff_t) amount,
1604 +                               curlun->file_length - file_offset);
1605 +
1606 +               /* Wait for the next buffer to become available */
1607 +               bh = fsg->next_buffhd_to_fill;
1608 +               while (bh->state != BUF_STATE_EMPTY) {
1609 +                       rc = sleep_thread(fsg);
1610 +                       if (rc)
1611 +                               return rc;
1612 +               }
1613 +
1614 +               /* If we were asked to read past the end of file,
1615 +                * end with an empty buffer. */
1616 +               if (amount == 0) {
1617 +                       curlun->sense_data =
1618 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1619 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1620 +                       curlun->info_valid = 1;
1621 +                       bh->inreq->length = 0;
1622 +                       bh->state = BUF_STATE_FULL;
1623 +                       break;
1624 +               }
1625 +
1626 +               /* Perform the read */
1627 +               file_offset_tmp = file_offset;
1628 +               nread = vfs_read(curlun->filp,
1629 +                               (char __user *) bh->buf,
1630 +                               amount, &file_offset_tmp);
1631 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1632 +                               (unsigned long long) file_offset,
1633 +                               (int) nread);
1634 +               if (signal_pending(current))
1635 +                       return -EINTR;
1636 +
1637 +               if (nread < 0) {
1638 +                       LDBG(curlun, "error in file read: %d\n",
1639 +                                       (int) nread);
1640 +                       nread = 0;
1641 +               } else if (nread < amount) {
1642 +                       LDBG(curlun, "partial file read: %d/%u\n",
1643 +                                       (int) nread, amount);
1644 +                       nread = round_down(nread, curlun->blksize);
1645 +               }
1646 +               file_offset  += nread;
1647 +               amount_left  -= nread;
1648 +               fsg->residue -= nread;
1649 +
1650 +               /* Except at the end of the transfer, nread will be
1651 +                * equal to the buffer size, which is divisible by the
1652 +                * bulk-in maxpacket size.
1653 +                */
1654 +               bh->inreq->length = nread;
1655 +               bh->state = BUF_STATE_FULL;
1656 +
1657 +               /* If an error occurred, report it and its position */
1658 +               if (nread < amount) {
1659 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1660 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1661 +                       curlun->info_valid = 1;
1662 +                       break;
1663 +               }
1664 +
1665 +               if (amount_left == 0)
1666 +                       break;          // No more left to read
1667 +
1668 +               /* Send this buffer and go read some more */
1669 +               bh->inreq->zero = 0;
1670 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
1671 +                               &bh->inreq_busy, &bh->state);
1672 +               fsg->next_buffhd_to_fill = bh->next;
1673 +       }
1674 +
1675 +       return -EIO;            // No default reply
1676 +}
1677 +
1678 +
1679 +/*-------------------------------------------------------------------------*/
1680 +
1681 +static int do_write(struct fsg_dev *fsg)
1682 +{
1683 +       struct fsg_lun          *curlun = fsg->curlun;
1684 +       u32                     lba;
1685 +       struct fsg_buffhd       *bh;
1686 +       int                     get_some_more;
1687 +       u32                     amount_left_to_req, amount_left_to_write;
1688 +       loff_t                  usb_offset, file_offset, file_offset_tmp;
1689 +       unsigned int            amount;
1690 +       ssize_t                 nwritten;
1691 +       int                     rc;
1692 +
1693 +       if (curlun->ro) {
1694 +               curlun->sense_data = SS_WRITE_PROTECTED;
1695 +               return -EINVAL;
1696 +       }
1697 +       spin_lock(&curlun->filp->f_lock);
1698 +       curlun->filp->f_flags &= ~O_SYNC;       // Default is not to wait
1699 +       spin_unlock(&curlun->filp->f_lock);
1700 +
1701 +       /* Get the starting Logical Block Address and check that it's
1702 +        * not too big */
1703 +       if (fsg->cmnd[0] == WRITE_6)
1704 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1705 +       else {
1706 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1707 +
1708 +               /* We allow DPO (Disable Page Out = don't save data in the
1709 +                * cache) and FUA (Force Unit Access = write directly to the
1710 +                * medium).  We don't implement DPO; we implement FUA by
1711 +                * performing synchronous output. */
1712 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1713 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1714 +                       return -EINVAL;
1715 +               }
1716 +               /* FUA */
1717 +               if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
1718 +                       spin_lock(&curlun->filp->f_lock);
1719 +                       curlun->filp->f_flags |= O_DSYNC;
1720 +                       spin_unlock(&curlun->filp->f_lock);
1721 +               }
1722 +       }
1723 +       if (lba >= curlun->num_sectors) {
1724 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1725 +               return -EINVAL;
1726 +       }
1727 +
1728 +       /* Carry out the file writes */
1729 +       get_some_more = 1;
1730 +       file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
1731 +       amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
1732 +
1733 +       while (amount_left_to_write > 0) {
1734 +
1735 +               /* Queue a request for more data from the host */
1736 +               bh = fsg->next_buffhd_to_fill;
1737 +               if (bh->state == BUF_STATE_EMPTY && get_some_more) {
1738 +
1739 +                       /* Figure out how much we want to get:
1740 +                        * Try to get the remaining amount,
1741 +                        * but not more than the buffer size.
1742 +                        */
1743 +                       amount = min(amount_left_to_req, mod_data.buflen);
1744 +
1745 +                       /* Beyond the end of the backing file? */
1746 +                       if (usb_offset >= curlun->file_length) {
1747 +                               get_some_more = 0;
1748 +                               curlun->sense_data =
1749 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1750 +                               curlun->sense_data_info = usb_offset >> curlun->blkbits;
1751 +                               curlun->info_valid = 1;
1752 +                               continue;
1753 +                       }
1754 +
1755 +                       /* Get the next buffer */
1756 +                       usb_offset += amount;
1757 +                       fsg->usb_amount_left -= amount;
1758 +                       amount_left_to_req -= amount;
1759 +                       if (amount_left_to_req == 0)
1760 +                               get_some_more = 0;
1761 +
1762 +                       /* Except at the end of the transfer, amount will be
1763 +                        * equal to the buffer size, which is divisible by
1764 +                        * the bulk-out maxpacket size.
1765 +                        */
1766 +                       set_bulk_out_req_length(fsg, bh, amount);
1767 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
1768 +                                       &bh->outreq_busy, &bh->state);
1769 +                       fsg->next_buffhd_to_fill = bh->next;
1770 +                       continue;
1771 +               }
1772 +
1773 +               /* Write the received data to the backing file */
1774 +               bh = fsg->next_buffhd_to_drain;
1775 +               if (bh->state == BUF_STATE_EMPTY && !get_some_more)
1776 +                       break;                  // We stopped early
1777 +               if (bh->state == BUF_STATE_FULL) {
1778 +                       smp_rmb();
1779 +                       fsg->next_buffhd_to_drain = bh->next;
1780 +                       bh->state = BUF_STATE_EMPTY;
1781 +
1782 +                       /* Did something go wrong with the transfer? */
1783 +                       if (bh->outreq->status != 0) {
1784 +                               curlun->sense_data = SS_COMMUNICATION_FAILURE;
1785 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1786 +                               curlun->info_valid = 1;
1787 +                               break;
1788 +                       }
1789 +
1790 +                       amount = bh->outreq->actual;
1791 +                       if (curlun->file_length - file_offset < amount) {
1792 +                               LERROR(curlun,
1793 +       "write %u @ %llu beyond end %llu\n",
1794 +       amount, (unsigned long long) file_offset,
1795 +       (unsigned long long) curlun->file_length);
1796 +                               amount = curlun->file_length - file_offset;
1797 +                       }
1798 +
1799 +                       /* Don't accept excess data.  The spec doesn't say
1800 +                        * what to do in this case.  We'll ignore the error.
1801 +                        */
1802 +                       amount = min(amount, bh->bulk_out_intended_length);
1803 +
1804 +                       /* Don't write a partial block */
1805 +                       amount = round_down(amount, curlun->blksize);
1806 +                       if (amount == 0)
1807 +                               goto empty_write;
1808 +
1809 +                       /* Perform the write */
1810 +                       file_offset_tmp = file_offset;
1811 +                       nwritten = vfs_write(curlun->filp,
1812 +                                       (char __user *) bh->buf,
1813 +                                       amount, &file_offset_tmp);
1814 +                       VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
1815 +                                       (unsigned long long) file_offset,
1816 +                                       (int) nwritten);
1817 +                       if (signal_pending(current))
1818 +                               return -EINTR;          // Interrupted!
1819 +
1820 +                       if (nwritten < 0) {
1821 +                               LDBG(curlun, "error in file write: %d\n",
1822 +                                               (int) nwritten);
1823 +                               nwritten = 0;
1824 +                       } else if (nwritten < amount) {
1825 +                               LDBG(curlun, "partial file write: %d/%u\n",
1826 +                                               (int) nwritten, amount);
1827 +                               nwritten = round_down(nwritten, curlun->blksize);
1828 +                       }
1829 +                       file_offset += nwritten;
1830 +                       amount_left_to_write -= nwritten;
1831 +                       fsg->residue -= nwritten;
1832 +
1833 +                       /* If an error occurred, report it and its position */
1834 +                       if (nwritten < amount) {
1835 +                               curlun->sense_data = SS_WRITE_ERROR;
1836 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1837 +                               curlun->info_valid = 1;
1838 +                               break;
1839 +                       }
1840 +
1841 + empty_write:
1842 +                       /* Did the host decide to stop early? */
1843 +                       if (bh->outreq->actual < bh->bulk_out_intended_length) {
1844 +                               fsg->short_packet_received = 1;
1845 +                               break;
1846 +                       }
1847 +                       continue;
1848 +               }
1849 +
1850 +               /* Wait for something to happen */
1851 +               rc = sleep_thread(fsg);
1852 +               if (rc)
1853 +                       return rc;
1854 +       }
1855 +
1856 +       return -EIO;            // No default reply
1857 +}
1858 +
1859 +
1860 +/*-------------------------------------------------------------------------*/
1861 +
1862 +static int do_synchronize_cache(struct fsg_dev *fsg)
1863 +{
1864 +       struct fsg_lun  *curlun = fsg->curlun;
1865 +       int             rc;
1866 +
1867 +       /* We ignore the requested LBA and write out all file's
1868 +        * dirty data buffers. */
1869 +       rc = fsg_lun_fsync_sub(curlun);
1870 +       if (rc)
1871 +               curlun->sense_data = SS_WRITE_ERROR;
1872 +       return 0;
1873 +}
1874 +
1875 +
1876 +/*-------------------------------------------------------------------------*/
1877 +
1878 +static void invalidate_sub(struct fsg_lun *curlun)
1879 +{
1880 +       struct file     *filp = curlun->filp;
1881 +       struct inode    *inode = filp->f_path.dentry->d_inode;
1882 +       unsigned long   rc;
1883 +
1884 +       rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
1885 +       VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
1886 +}
1887 +
1888 +static int do_verify(struct fsg_dev *fsg)
1889 +{
1890 +       struct fsg_lun          *curlun = fsg->curlun;
1891 +       u32                     lba;
1892 +       u32                     verification_length;
1893 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
1894 +       loff_t                  file_offset, file_offset_tmp;
1895 +       u32                     amount_left;
1896 +       unsigned int            amount;
1897 +       ssize_t                 nread;
1898 +
1899 +       /* Get the starting Logical Block Address and check that it's
1900 +        * not too big */
1901 +       lba = get_unaligned_be32(&fsg->cmnd[2]);
1902 +       if (lba >= curlun->num_sectors) {
1903 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1904 +               return -EINVAL;
1905 +       }
1906 +
1907 +       /* We allow DPO (Disable Page Out = don't save data in the
1908 +        * cache) but we don't implement it. */
1909 +       if ((fsg->cmnd[1] & ~0x10) != 0) {
1910 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1911 +               return -EINVAL;
1912 +       }
1913 +
1914 +       verification_length = get_unaligned_be16(&fsg->cmnd[7]);
1915 +       if (unlikely(verification_length == 0))
1916 +               return -EIO;            // No default reply
1917 +
1918 +       /* Prepare to carry out the file verify */
1919 +       amount_left = verification_length << curlun->blkbits;
1920 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1921 +
1922 +       /* Write out all the dirty buffers before invalidating them */
1923 +       fsg_lun_fsync_sub(curlun);
1924 +       if (signal_pending(current))
1925 +               return -EINTR;
1926 +
1927 +       invalidate_sub(curlun);
1928 +       if (signal_pending(current))
1929 +               return -EINTR;
1930 +
1931 +       /* Just try to read the requested blocks */
1932 +       while (amount_left > 0) {
1933 +
1934 +               /* Figure out how much we need to read:
1935 +                * Try to read the remaining amount, but not more than
1936 +                * the buffer size.
1937 +                * And don't try to read past the end of the file.
1938 +                */
1939 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1940 +               amount = min((loff_t) amount,
1941 +                               curlun->file_length - file_offset);
1942 +               if (amount == 0) {
1943 +                       curlun->sense_data =
1944 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1945 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1946 +                       curlun->info_valid = 1;
1947 +                       break;
1948 +               }
1949 +
1950 +               /* Perform the read */
1951 +               file_offset_tmp = file_offset;
1952 +               nread = vfs_read(curlun->filp,
1953 +                               (char __user *) bh->buf,
1954 +                               amount, &file_offset_tmp);
1955 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1956 +                               (unsigned long long) file_offset,
1957 +                               (int) nread);
1958 +               if (signal_pending(current))
1959 +                       return -EINTR;
1960 +
1961 +               if (nread < 0) {
1962 +                       LDBG(curlun, "error in file verify: %d\n",
1963 +                                       (int) nread);
1964 +                       nread = 0;
1965 +               } else if (nread < amount) {
1966 +                       LDBG(curlun, "partial file verify: %d/%u\n",
1967 +                                       (int) nread, amount);
1968 +                       nread = round_down(nread, curlun->blksize);
1969 +               }
1970 +               if (nread == 0) {
1971 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1972 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1973 +                       curlun->info_valid = 1;
1974 +                       break;
1975 +               }
1976 +               file_offset += nread;
1977 +               amount_left -= nread;
1978 +       }
1979 +       return 0;
1980 +}
1981 +
1982 +
1983 +/*-------------------------------------------------------------------------*/
1984 +
1985 +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1986 +{
1987 +       u8      *buf = (u8 *) bh->buf;
1988 +
1989 +       static char vendor_id[] = "Linux   ";
1990 +       static char product_disk_id[] = "File-Stor Gadget";
1991 +       static char product_cdrom_id[] = "File-CD Gadget  ";
1992 +
1993 +       if (!fsg->curlun) {             // Unsupported LUNs are okay
1994 +               fsg->bad_lun_okay = 1;
1995 +               memset(buf, 0, 36);
1996 +               buf[0] = 0x7f;          // Unsupported, no device-type
1997 +               buf[4] = 31;            // Additional length
1998 +               return 36;
1999 +       }
2000 +
2001 +       memset(buf, 0, 8);
2002 +       buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
2003 +       if (mod_data.removable)
2004 +               buf[1] = 0x80;
2005 +       buf[2] = 2;             // ANSI SCSI level 2
2006 +       buf[3] = 2;             // SCSI-2 INQUIRY data format
2007 +       buf[4] = 31;            // Additional length
2008 +                               // No special options
2009 +       sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
2010 +                       (mod_data.cdrom ? product_cdrom_id :
2011 +                               product_disk_id),
2012 +                       mod_data.release);
2013 +       return 36;
2014 +}
2015 +
2016 +
2017 +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2018 +{
2019 +       struct fsg_lun  *curlun = fsg->curlun;
2020 +       u8              *buf = (u8 *) bh->buf;
2021 +       u32             sd, sdinfo;
2022 +       int             valid;
2023 +
2024 +       /*
2025 +        * From the SCSI-2 spec., section 7.9 (Unit attention condition):
2026 +        *
2027 +        * If a REQUEST SENSE command is received from an initiator
2028 +        * with a pending unit attention condition (before the target
2029 +        * generates the contingent allegiance condition), then the
2030 +        * target shall either:
2031 +        *   a) report any pending sense data and preserve the unit
2032 +        *      attention condition on the logical unit, or,
2033 +        *   b) report the unit attention condition, may discard any
2034 +        *      pending sense data, and clear the unit attention
2035 +        *      condition on the logical unit for that initiator.
2036 +        *
2037 +        * FSG normally uses option a); enable this code to use option b).
2038 +        */
2039 +#if 0
2040 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
2041 +               curlun->sense_data = curlun->unit_attention_data;
2042 +               curlun->unit_attention_data = SS_NO_SENSE;
2043 +       }
2044 +#endif
2045 +
2046 +       if (!curlun) {          // Unsupported LUNs are okay
2047 +               fsg->bad_lun_okay = 1;
2048 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2049 +               sdinfo = 0;
2050 +               valid = 0;
2051 +       } else {
2052 +               sd = curlun->sense_data;
2053 +               sdinfo = curlun->sense_data_info;
2054 +               valid = curlun->info_valid << 7;
2055 +               curlun->sense_data = SS_NO_SENSE;
2056 +               curlun->sense_data_info = 0;
2057 +               curlun->info_valid = 0;
2058 +       }
2059 +
2060 +       memset(buf, 0, 18);
2061 +       buf[0] = valid | 0x70;                  // Valid, current error
2062 +       buf[2] = SK(sd);
2063 +       put_unaligned_be32(sdinfo, &buf[3]);    /* Sense information */
2064 +       buf[7] = 18 - 8;                        // Additional sense length
2065 +       buf[12] = ASC(sd);
2066 +       buf[13] = ASCQ(sd);
2067 +       return 18;
2068 +}
2069 +
2070 +
2071 +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2072 +{
2073 +       struct fsg_lun  *curlun = fsg->curlun;
2074 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2075 +       int             pmi = fsg->cmnd[8];
2076 +       u8              *buf = (u8 *) bh->buf;
2077 +
2078 +       /* Check the PMI and LBA fields */
2079 +       if (pmi > 1 || (pmi == 0 && lba != 0)) {
2080 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2081 +               return -EINVAL;
2082 +       }
2083 +
2084 +       put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
2085 +                                               /* Max logical block */
2086 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2087 +       return 8;
2088 +}
2089 +
2090 +
2091 +static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2092 +{
2093 +       struct fsg_lun  *curlun = fsg->curlun;
2094 +       int             msf = fsg->cmnd[1] & 0x02;
2095 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2096 +       u8              *buf = (u8 *) bh->buf;
2097 +
2098 +       if ((fsg->cmnd[1] & ~0x02) != 0) {              /* Mask away MSF */
2099 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2100 +               return -EINVAL;
2101 +       }
2102 +       if (lba >= curlun->num_sectors) {
2103 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
2104 +               return -EINVAL;
2105 +       }
2106 +
2107 +       memset(buf, 0, 8);
2108 +       buf[0] = 0x01;          /* 2048 bytes of user data, rest is EC */
2109 +       store_cdrom_address(&buf[4], msf, lba);
2110 +       return 8;
2111 +}
2112 +
2113 +
2114 +static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2115 +{
2116 +       struct fsg_lun  *curlun = fsg->curlun;
2117 +       int             msf = fsg->cmnd[1] & 0x02;
2118 +       int             start_track = fsg->cmnd[6];
2119 +       u8              *buf = (u8 *) bh->buf;
2120 +
2121 +       if ((fsg->cmnd[1] & ~0x02) != 0 ||              /* Mask away MSF */
2122 +                       start_track > 1) {
2123 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2124 +               return -EINVAL;
2125 +       }
2126 +
2127 +       memset(buf, 0, 20);
2128 +       buf[1] = (20-2);                /* TOC data length */
2129 +       buf[2] = 1;                     /* First track number */
2130 +       buf[3] = 1;                     /* Last track number */
2131 +       buf[5] = 0x16;                  /* Data track, copying allowed */
2132 +       buf[6] = 0x01;                  /* Only track is number 1 */
2133 +       store_cdrom_address(&buf[8], msf, 0);
2134 +
2135 +       buf[13] = 0x16;                 /* Lead-out track is data */
2136 +       buf[14] = 0xAA;                 /* Lead-out track number */
2137 +       store_cdrom_address(&buf[16], msf, curlun->num_sectors);
2138 +       return 20;
2139 +}
2140 +
2141 +
2142 +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2143 +{
2144 +       struct fsg_lun  *curlun = fsg->curlun;
2145 +       int             mscmnd = fsg->cmnd[0];
2146 +       u8              *buf = (u8 *) bh->buf;
2147 +       u8              *buf0 = buf;
2148 +       int             pc, page_code;
2149 +       int             changeable_values, all_pages;
2150 +       int             valid_page = 0;
2151 +       int             len, limit;
2152 +
2153 +       if ((fsg->cmnd[1] & ~0x08) != 0) {              // Mask away DBD
2154 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2155 +               return -EINVAL;
2156 +       }
2157 +       pc = fsg->cmnd[2] >> 6;
2158 +       page_code = fsg->cmnd[2] & 0x3f;
2159 +       if (pc == 3) {
2160 +               curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
2161 +               return -EINVAL;
2162 +       }
2163 +       changeable_values = (pc == 1);
2164 +       all_pages = (page_code == 0x3f);
2165 +
2166 +       /* Write the mode parameter header.  Fixed values are: default
2167 +        * medium type, no cache control (DPOFUA), and no block descriptors.
2168 +        * The only variable value is the WriteProtect bit.  We will fill in
2169 +        * the mode data length later. */
2170 +       memset(buf, 0, 8);
2171 +       if (mscmnd == MODE_SENSE) {
2172 +               buf[2] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2173 +               buf += 4;
2174 +               limit = 255;
2175 +       } else {                        // MODE_SENSE_10
2176 +               buf[3] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2177 +               buf += 8;
2178 +               limit = 65535;          // Should really be mod_data.buflen
2179 +       }
2180 +
2181 +       /* No block descriptors */
2182 +
2183 +       /* The mode pages, in numerical order.  The only page we support
2184 +        * is the Caching page. */
2185 +       if (page_code == 0x08 || all_pages) {
2186 +               valid_page = 1;
2187 +               buf[0] = 0x08;          // Page code
2188 +               buf[1] = 10;            // Page length
2189 +               memset(buf+2, 0, 10);   // None of the fields are changeable
2190 +
2191 +               if (!changeable_values) {
2192 +                       buf[2] = 0x04;  // Write cache enable,
2193 +                                       // Read cache not disabled
2194 +                                       // No cache retention priorities
2195 +                       put_unaligned_be16(0xffff, &buf[4]);
2196 +                                       /* Don't disable prefetch */
2197 +                                       /* Minimum prefetch = 0 */
2198 +                       put_unaligned_be16(0xffff, &buf[8]);
2199 +                                       /* Maximum prefetch */
2200 +                       put_unaligned_be16(0xffff, &buf[10]);
2201 +                                       /* Maximum prefetch ceiling */
2202 +               }
2203 +               buf += 12;
2204 +       }
2205 +
2206 +       /* Check that a valid page was requested and the mode data length
2207 +        * isn't too long. */
2208 +       len = buf - buf0;
2209 +       if (!valid_page || len > limit) {
2210 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2211 +               return -EINVAL;
2212 +       }
2213 +
2214 +       /*  Store the mode data length */
2215 +       if (mscmnd == MODE_SENSE)
2216 +               buf0[0] = len - 1;
2217 +       else
2218 +               put_unaligned_be16(len - 2, buf0);
2219 +       return len;
2220 +}
2221 +
2222 +
2223 +static int do_start_stop(struct fsg_dev *fsg)
2224 +{
2225 +       struct fsg_lun  *curlun = fsg->curlun;
2226 +       int             loej, start;
2227 +
2228 +       if (!mod_data.removable) {
2229 +               curlun->sense_data = SS_INVALID_COMMAND;
2230 +               return -EINVAL;
2231 +       }
2232 +
2233 +       // int immed = fsg->cmnd[1] & 0x01;
2234 +       loej = fsg->cmnd[4] & 0x02;
2235 +       start = fsg->cmnd[4] & 0x01;
2236 +
2237 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
2238 +       if ((fsg->cmnd[1] & ~0x01) != 0 ||              // Mask away Immed
2239 +                       (fsg->cmnd[4] & ~0x03) != 0) {  // Mask LoEj, Start
2240 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2241 +               return -EINVAL;
2242 +       }
2243 +
2244 +       if (!start) {
2245 +
2246 +               /* Are we allowed to unload the media? */
2247 +               if (curlun->prevent_medium_removal) {
2248 +                       LDBG(curlun, "unload attempt prevented\n");
2249 +                       curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
2250 +                       return -EINVAL;
2251 +               }
2252 +               if (loej) {             // Simulate an unload/eject
2253 +                       up_read(&fsg->filesem);
2254 +                       down_write(&fsg->filesem);
2255 +                       fsg_lun_close(curlun);
2256 +                       up_write(&fsg->filesem);
2257 +                       down_read(&fsg->filesem);
2258 +               }
2259 +       } else {
2260 +
2261 +               /* Our emulation doesn't support mounting; the medium is
2262 +                * available for use as soon as it is loaded. */
2263 +               if (!fsg_lun_is_open(curlun)) {
2264 +                       curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2265 +                       return -EINVAL;
2266 +               }
2267 +       }
2268 +#endif
2269 +       return 0;
2270 +}
2271 +
2272 +
2273 +static int do_prevent_allow(struct fsg_dev *fsg)
2274 +{
2275 +       struct fsg_lun  *curlun = fsg->curlun;
2276 +       int             prevent;
2277 +
2278 +       if (!mod_data.removable) {
2279 +               curlun->sense_data = SS_INVALID_COMMAND;
2280 +               return -EINVAL;
2281 +       }
2282 +
2283 +       prevent = fsg->cmnd[4] & 0x01;
2284 +       if ((fsg->cmnd[4] & ~0x01) != 0) {              // Mask away Prevent
2285 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2286 +               return -EINVAL;
2287 +       }
2288 +
2289 +       if (curlun->prevent_medium_removal && !prevent)
2290 +               fsg_lun_fsync_sub(curlun);
2291 +       curlun->prevent_medium_removal = prevent;
2292 +       return 0;
2293 +}
2294 +
2295 +
2296 +static int do_read_format_capacities(struct fsg_dev *fsg,
2297 +                       struct fsg_buffhd *bh)
2298 +{
2299 +       struct fsg_lun  *curlun = fsg->curlun;
2300 +       u8              *buf = (u8 *) bh->buf;
2301 +
2302 +       buf[0] = buf[1] = buf[2] = 0;
2303 +       buf[3] = 8;             // Only the Current/Maximum Capacity Descriptor
2304 +       buf += 4;
2305 +
2306 +       put_unaligned_be32(curlun->num_sectors, &buf[0]);
2307 +                                               /* Number of blocks */
2308 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2309 +       buf[4] = 0x02;                          /* Current capacity */
2310 +       return 12;
2311 +}
2312 +
2313 +
2314 +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2315 +{
2316 +       struct fsg_lun  *curlun = fsg->curlun;
2317 +
2318 +       /* We don't support MODE SELECT */
2319 +       curlun->sense_data = SS_INVALID_COMMAND;
2320 +       return -EINVAL;
2321 +}
2322 +
2323 +
2324 +/*-------------------------------------------------------------------------*/
2325 +
2326 +static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
2327 +{
2328 +       int     rc;
2329 +
2330 +       rc = fsg_set_halt(fsg, fsg->bulk_in);
2331 +       if (rc == -EAGAIN)
2332 +               VDBG(fsg, "delayed bulk-in endpoint halt\n");
2333 +       while (rc != 0) {
2334 +               if (rc != -EAGAIN) {
2335 +                       WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
2336 +                       rc = 0;
2337 +                       break;
2338 +               }
2339 +
2340 +               /* Wait for a short time and then try again */
2341 +               if (msleep_interruptible(100) != 0)
2342 +                       return -EINTR;
2343 +               rc = usb_ep_set_halt(fsg->bulk_in);
2344 +       }
2345 +       return rc;
2346 +}
2347 +
2348 +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
2349 +{
2350 +       int     rc;
2351 +
2352 +       DBG(fsg, "bulk-in set wedge\n");
2353 +       rc = usb_ep_set_wedge(fsg->bulk_in);
2354 +       if (rc == -EAGAIN)
2355 +               VDBG(fsg, "delayed bulk-in endpoint wedge\n");
2356 +       while (rc != 0) {
2357 +               if (rc != -EAGAIN) {
2358 +                       WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
2359 +                       rc = 0;
2360 +                       break;
2361 +               }
2362 +
2363 +               /* Wait for a short time and then try again */
2364 +               if (msleep_interruptible(100) != 0)
2365 +                       return -EINTR;
2366 +               rc = usb_ep_set_wedge(fsg->bulk_in);
2367 +       }
2368 +       return rc;
2369 +}
2370 +
2371 +static int throw_away_data(struct fsg_dev *fsg)
2372 +{
2373 +       struct fsg_buffhd       *bh;
2374 +       u32                     amount;
2375 +       int                     rc;
2376 +
2377 +       while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
2378 +                       fsg->usb_amount_left > 0) {
2379 +
2380 +               /* Throw away the data in a filled buffer */
2381 +               if (bh->state == BUF_STATE_FULL) {
2382 +                       smp_rmb();
2383 +                       bh->state = BUF_STATE_EMPTY;
2384 +                       fsg->next_buffhd_to_drain = bh->next;
2385 +
2386 +                       /* A short packet or an error ends everything */
2387 +                       if (bh->outreq->actual < bh->bulk_out_intended_length ||
2388 +                                       bh->outreq->status != 0) {
2389 +                               raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2390 +                               return -EINTR;
2391 +                       }
2392 +                       continue;
2393 +               }
2394 +
2395 +               /* Try to submit another request if we need one */
2396 +               bh = fsg->next_buffhd_to_fill;
2397 +               if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
2398 +                       amount = min(fsg->usb_amount_left,
2399 +                                       (u32) mod_data.buflen);
2400 +
2401 +                       /* Except at the end of the transfer, amount will be
2402 +                        * equal to the buffer size, which is divisible by
2403 +                        * the bulk-out maxpacket size.
2404 +                        */
2405 +                       set_bulk_out_req_length(fsg, bh, amount);
2406 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
2407 +                                       &bh->outreq_busy, &bh->state);
2408 +                       fsg->next_buffhd_to_fill = bh->next;
2409 +                       fsg->usb_amount_left -= amount;
2410 +                       continue;
2411 +               }
2412 +
2413 +               /* Otherwise wait for something to happen */
2414 +               rc = sleep_thread(fsg);
2415 +               if (rc)
2416 +                       return rc;
2417 +       }
2418 +       return 0;
2419 +}
2420 +
2421 +
2422 +static int finish_reply(struct fsg_dev *fsg)
2423 +{
2424 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
2425 +       int                     rc = 0;
2426 +
2427 +       switch (fsg->data_dir) {
2428 +       case DATA_DIR_NONE:
2429 +               break;                  // Nothing to send
2430 +
2431 +       /* If we don't know whether the host wants to read or write,
2432 +        * this must be CB or CBI with an unknown command.  We mustn't
2433 +        * try to send or receive any data.  So stall both bulk pipes
2434 +        * if we can and wait for a reset. */
2435 +       case DATA_DIR_UNKNOWN:
2436 +               if (mod_data.can_stall) {
2437 +                       fsg_set_halt(fsg, fsg->bulk_out);
2438 +                       rc = halt_bulk_in_endpoint(fsg);
2439 +               }
2440 +               break;
2441 +
2442 +       /* All but the last buffer of data must have already been sent */
2443 +       case DATA_DIR_TO_HOST:
2444 +               if (fsg->data_size == 0)
2445 +                       ;               // Nothing to send
2446 +
2447 +               /* If there's no residue, simply send the last buffer */
2448 +               else if (fsg->residue == 0) {
2449 +                       bh->inreq->zero = 0;
2450 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2451 +                                       &bh->inreq_busy, &bh->state);
2452 +                       fsg->next_buffhd_to_fill = bh->next;
2453 +               }
2454 +
2455 +               /* There is a residue.  For CB and CBI, simply mark the end
2456 +                * of the data with a short packet.  However, if we are
2457 +                * allowed to stall, there was no data at all (residue ==
2458 +                * data_size), and the command failed (invalid LUN or
2459 +                * sense data is set), then halt the bulk-in endpoint
2460 +                * instead. */
2461 +               else if (!transport_is_bbb()) {
2462 +                       if (mod_data.can_stall &&
2463 +                                       fsg->residue == fsg->data_size &&
2464 +       (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
2465 +                               bh->state = BUF_STATE_EMPTY;
2466 +                               rc = halt_bulk_in_endpoint(fsg);
2467 +                       } else {
2468 +                               bh->inreq->zero = 1;
2469 +                               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2470 +                                               &bh->inreq_busy, &bh->state);
2471 +                               fsg->next_buffhd_to_fill = bh->next;
2472 +                       }
2473 +               }
2474 +
2475 +               /*
2476 +                * For Bulk-only, mark the end of the data with a short
2477 +                * packet.  If we are allowed to stall, halt the bulk-in
2478 +                * endpoint.  (Note: This violates the Bulk-Only Transport
2479 +                * specification, which requires us to pad the data if we
2480 +                * don't halt the endpoint.  Presumably nobody will mind.)
2481 +                */
2482 +               else {
2483 +                       bh->inreq->zero = 1;
2484 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2485 +                                       &bh->inreq_busy, &bh->state);
2486 +                       fsg->next_buffhd_to_fill = bh->next;
2487 +                       if (mod_data.can_stall)
2488 +                               rc = halt_bulk_in_endpoint(fsg);
2489 +               }
2490 +               break;
2491 +
2492 +       /* We have processed all we want from the data the host has sent.
2493 +        * There may still be outstanding bulk-out requests. */
2494 +       case DATA_DIR_FROM_HOST:
2495 +               if (fsg->residue == 0)
2496 +                       ;               // Nothing to receive
2497 +
2498 +               /* Did the host stop sending unexpectedly early? */
2499 +               else if (fsg->short_packet_received) {
2500 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2501 +                       rc = -EINTR;
2502 +               }
2503 +
2504 +               /* We haven't processed all the incoming data.  Even though
2505 +                * we may be allowed to stall, doing so would cause a race.
2506 +                * The controller may already have ACK'ed all the remaining
2507 +                * bulk-out packets, in which case the host wouldn't see a
2508 +                * STALL.  Not realizing the endpoint was halted, it wouldn't
2509 +                * clear the halt -- leading to problems later on. */
2510 +#if 0
2511 +               else if (mod_data.can_stall) {
2512 +                       fsg_set_halt(fsg, fsg->bulk_out);
2513 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2514 +                       rc = -EINTR;
2515 +               }
2516 +#endif
2517 +
2518 +               /* We can't stall.  Read in the excess data and throw it
2519 +                * all away. */
2520 +               else
2521 +                       rc = throw_away_data(fsg);
2522 +               break;
2523 +       }
2524 +       return rc;
2525 +}
2526 +
2527 +
2528 +static int send_status(struct fsg_dev *fsg)
2529 +{
2530 +       struct fsg_lun          *curlun = fsg->curlun;
2531 +       struct fsg_buffhd       *bh;
2532 +       int                     rc;
2533 +       u8                      status = US_BULK_STAT_OK;
2534 +       u32                     sd, sdinfo = 0;
2535 +
2536 +       /* Wait for the next buffer to become available */
2537 +       bh = fsg->next_buffhd_to_fill;
2538 +       while (bh->state != BUF_STATE_EMPTY) {
2539 +               rc = sleep_thread(fsg);
2540 +               if (rc)
2541 +                       return rc;
2542 +       }
2543 +
2544 +       if (curlun) {
2545 +               sd = curlun->sense_data;
2546 +               sdinfo = curlun->sense_data_info;
2547 +       } else if (fsg->bad_lun_okay)
2548 +               sd = SS_NO_SENSE;
2549 +       else
2550 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2551 +
2552 +       if (fsg->phase_error) {
2553 +               DBG(fsg, "sending phase-error status\n");
2554 +               status = US_BULK_STAT_PHASE;
2555 +               sd = SS_INVALID_COMMAND;
2556 +       } else if (sd != SS_NO_SENSE) {
2557 +               DBG(fsg, "sending command-failure status\n");
2558 +               status = US_BULK_STAT_FAIL;
2559 +               VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
2560 +                               "  info x%x\n",
2561 +                               SK(sd), ASC(sd), ASCQ(sd), sdinfo);
2562 +       }
2563 +
2564 +       if (transport_is_bbb()) {
2565 +               struct bulk_cs_wrap     *csw = bh->buf;
2566 +
2567 +               /* Store and send the Bulk-only CSW */
2568 +               csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
2569 +               csw->Tag = fsg->tag;
2570 +               csw->Residue = cpu_to_le32(fsg->residue);
2571 +               csw->Status = status;
2572 +
2573 +               bh->inreq->length = US_BULK_CS_WRAP_LEN;
2574 +               bh->inreq->zero = 0;
2575 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2576 +                               &bh->inreq_busy, &bh->state);
2577 +
2578 +       } else if (mod_data.transport_type == USB_PR_CB) {
2579 +
2580 +               /* Control-Bulk transport has no status phase! */
2581 +               return 0;
2582 +
2583 +       } else {                        // USB_PR_CBI
2584 +               struct interrupt_data   *buf = bh->buf;
2585 +
2586 +               /* Store and send the Interrupt data.  UFI sends the ASC
2587 +                * and ASCQ bytes.  Everything else sends a Type (which
2588 +                * is always 0) and the status Value. */
2589 +               if (mod_data.protocol_type == USB_SC_UFI) {
2590 +                       buf->bType = ASC(sd);
2591 +                       buf->bValue = ASCQ(sd);
2592 +               } else {
2593 +                       buf->bType = 0;
2594 +                       buf->bValue = status;
2595 +               }
2596 +               fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
2597 +
2598 +               fsg->intr_buffhd = bh;          // Point to the right buffhd
2599 +               fsg->intreq->buf = bh->inreq->buf;
2600 +               fsg->intreq->context = bh;
2601 +               start_transfer(fsg, fsg->intr_in, fsg->intreq,
2602 +                               &fsg->intreq_busy, &bh->state);
2603 +       }
2604 +
2605 +       fsg->next_buffhd_to_fill = bh->next;
2606 +       return 0;
2607 +}
2608 +
2609 +
2610 +/*-------------------------------------------------------------------------*/
2611 +
2612 +/* Check whether the command is properly formed and whether its data size
2613 + * and direction agree with the values we already have. */
2614 +static int check_command(struct fsg_dev *fsg, int cmnd_size,
2615 +               enum data_direction data_dir, unsigned int mask,
2616 +               int needs_medium, const char *name)
2617 +{
2618 +       int                     i;
2619 +       int                     lun = fsg->cmnd[1] >> 5;
2620 +       static const char       dirletter[4] = {'u', 'o', 'i', 'n'};
2621 +       char                    hdlen[20];
2622 +       struct fsg_lun          *curlun;
2623 +
2624 +       /* Adjust the expected cmnd_size for protocol encapsulation padding.
2625 +        * Transparent SCSI doesn't pad. */
2626 +       if (protocol_is_scsi())
2627 +               ;
2628 +
2629 +       /* There's some disagreement as to whether RBC pads commands or not.
2630 +        * We'll play it safe and accept either form. */
2631 +       else if (mod_data.protocol_type == USB_SC_RBC) {
2632 +               if (fsg->cmnd_size == 12)
2633 +                       cmnd_size = 12;
2634 +
2635 +       /* All the other protocols pad to 12 bytes */
2636 +       } else
2637 +               cmnd_size = 12;
2638 +
2639 +       hdlen[0] = 0;
2640 +       if (fsg->data_dir != DATA_DIR_UNKNOWN)
2641 +               sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
2642 +                               fsg->data_size);
2643 +       VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
2644 +                       name, cmnd_size, dirletter[(int) data_dir],
2645 +                       fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
2646 +
2647 +       /* We can't reply at all until we know the correct data direction
2648 +        * and size. */
2649 +       if (fsg->data_size_from_cmnd == 0)
2650 +               data_dir = DATA_DIR_NONE;
2651 +       if (fsg->data_dir == DATA_DIR_UNKNOWN) {        // CB or CBI
2652 +               fsg->data_dir = data_dir;
2653 +               fsg->data_size = fsg->data_size_from_cmnd;
2654 +
2655 +       } else {                                        // Bulk-only
2656 +               if (fsg->data_size < fsg->data_size_from_cmnd) {
2657 +
2658 +                       /* Host data size < Device data size is a phase error.
2659 +                        * Carry out the command, but only transfer as much
2660 +                        * as we are allowed. */
2661 +                       fsg->data_size_from_cmnd = fsg->data_size;
2662 +                       fsg->phase_error = 1;
2663 +               }
2664 +       }
2665 +       fsg->residue = fsg->usb_amount_left = fsg->data_size;
2666 +
2667 +       /* Conflicting data directions is a phase error */
2668 +       if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
2669 +               fsg->phase_error = 1;
2670 +               return -EINVAL;
2671 +       }
2672 +
2673 +       /* Verify the length of the command itself */
2674 +       if (cmnd_size != fsg->cmnd_size) {
2675 +
2676 +               /* Special case workaround: There are plenty of buggy SCSI
2677 +                * implementations. Many have issues with cbw->Length
2678 +                * field passing a wrong command size. For those cases we
2679 +                * always try to work around the problem by using the length
2680 +                * sent by the host side provided it is at least as large
2681 +                * as the correct command length.
2682 +                * Examples of such cases would be MS-Windows, which issues
2683 +                * REQUEST SENSE with cbw->Length == 12 where it should
2684 +                * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
2685 +                * REQUEST SENSE with cbw->Length == 10 where it should
2686 +                * be 6 as well.
2687 +                */
2688 +               if (cmnd_size <= fsg->cmnd_size) {
2689 +                       DBG(fsg, "%s is buggy! Expected length %d "
2690 +                                       "but we got %d\n", name,
2691 +                                       cmnd_size, fsg->cmnd_size);
2692 +                       cmnd_size = fsg->cmnd_size;
2693 +               } else {
2694 +                       fsg->phase_error = 1;
2695 +                       return -EINVAL;
2696 +               }
2697 +       }
2698 +
2699 +       /* Check that the LUN values are consistent */
2700 +       if (transport_is_bbb()) {
2701 +               if (fsg->lun != lun)
2702 +                       DBG(fsg, "using LUN %d from CBW, "
2703 +                                       "not LUN %d from CDB\n",
2704 +                                       fsg->lun, lun);
2705 +       }
2706 +
2707 +       /* Check the LUN */
2708 +       curlun = fsg->curlun;
2709 +       if (curlun) {
2710 +               if (fsg->cmnd[0] != REQUEST_SENSE) {
2711 +                       curlun->sense_data = SS_NO_SENSE;
2712 +                       curlun->sense_data_info = 0;
2713 +                       curlun->info_valid = 0;
2714 +               }
2715 +       } else {
2716 +               fsg->bad_lun_okay = 0;
2717 +
2718 +               /* INQUIRY and REQUEST SENSE commands are explicitly allowed
2719 +                * to use unsupported LUNs; all others may not. */
2720 +               if (fsg->cmnd[0] != INQUIRY &&
2721 +                               fsg->cmnd[0] != REQUEST_SENSE) {
2722 +                       DBG(fsg, "unsupported LUN %d\n", fsg->lun);
2723 +                       return -EINVAL;
2724 +               }
2725 +       }
2726 +
2727 +       /* If a unit attention condition exists, only INQUIRY and
2728 +        * REQUEST SENSE commands are allowed; anything else must fail. */
2729 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
2730 +                       fsg->cmnd[0] != INQUIRY &&
2731 +                       fsg->cmnd[0] != REQUEST_SENSE) {
2732 +               curlun->sense_data = curlun->unit_attention_data;
2733 +               curlun->unit_attention_data = SS_NO_SENSE;
2734 +               return -EINVAL;
2735 +       }
2736 +
2737 +       /* Check that only command bytes listed in the mask are non-zero */
2738 +       fsg->cmnd[1] &= 0x1f;                   // Mask away the LUN
2739 +       for (i = 1; i < cmnd_size; ++i) {
2740 +               if (fsg->cmnd[i] && !(mask & (1 << i))) {
2741 +                       if (curlun)
2742 +                               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2743 +                       return -EINVAL;
2744 +               }
2745 +       }
2746 +
2747 +       /* If the medium isn't mounted and the command needs to access
2748 +        * it, return an error. */
2749 +       if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
2750 +               curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2751 +               return -EINVAL;
2752 +       }
2753 +
2754 +       return 0;
2755 +}
2756 +
2757 +/* wrapper of check_command for data size in blocks handling */
2758 +static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
2759 +               enum data_direction data_dir, unsigned int mask,
2760 +               int needs_medium, const char *name)
2761 +{
2762 +       if (fsg->curlun)
2763 +               fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
2764 +       return check_command(fsg, cmnd_size, data_dir,
2765 +                       mask, needs_medium, name);
2766 +}
2767 +
2768 +static int do_scsi_command(struct fsg_dev *fsg)
2769 +{
2770 +       struct fsg_buffhd       *bh;
2771 +       int                     rc;
2772 +       int                     reply = -EINVAL;
2773 +       int                     i;
2774 +       static char             unknown[16];
2775 +
2776 +       dump_cdb(fsg);
2777 +
2778 +       /* Wait for the next buffer to become available for data or status */
2779 +       bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
2780 +       while (bh->state != BUF_STATE_EMPTY) {
2781 +               rc = sleep_thread(fsg);
2782 +               if (rc)
2783 +                       return rc;
2784 +       }
2785 +       fsg->phase_error = 0;
2786 +       fsg->short_packet_received = 0;
2787 +
2788 +       down_read(&fsg->filesem);       // We're using the backing file
2789 +       switch (fsg->cmnd[0]) {
2790 +
2791 +       case INQUIRY:
2792 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2793 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2794 +                               (1<<4), 0,
2795 +                               "INQUIRY")) == 0)
2796 +                       reply = do_inquiry(fsg, bh);
2797 +               break;
2798 +
2799 +       case MODE_SELECT:
2800 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2801 +               if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
2802 +                               (1<<1) | (1<<4), 0,
2803 +                               "MODE SELECT(6)")) == 0)
2804 +                       reply = do_mode_select(fsg, bh);
2805 +               break;
2806 +
2807 +       case MODE_SELECT_10:
2808 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2809 +               if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
2810 +                               (1<<1) | (3<<7), 0,
2811 +                               "MODE SELECT(10)")) == 0)
2812 +                       reply = do_mode_select(fsg, bh);
2813 +               break;
2814 +
2815 +       case MODE_SENSE:
2816 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2817 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2818 +                               (1<<1) | (1<<2) | (1<<4), 0,
2819 +                               "MODE SENSE(6)")) == 0)
2820 +                       reply = do_mode_sense(fsg, bh);
2821 +               break;
2822 +
2823 +       case MODE_SENSE_10:
2824 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2825 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2826 +                               (1<<1) | (1<<2) | (3<<7), 0,
2827 +                               "MODE SENSE(10)")) == 0)
2828 +                       reply = do_mode_sense(fsg, bh);
2829 +               break;
2830 +
2831 +       case ALLOW_MEDIUM_REMOVAL:
2832 +               fsg->data_size_from_cmnd = 0;
2833 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2834 +                               (1<<4), 0,
2835 +                               "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
2836 +                       reply = do_prevent_allow(fsg);
2837 +               break;
2838 +
2839 +       case READ_6:
2840 +               i = fsg->cmnd[4];
2841 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2842 +               if ((reply = check_command_size_in_blocks(fsg, 6,
2843 +                               DATA_DIR_TO_HOST,
2844 +                               (7<<1) | (1<<4), 1,
2845 +                               "READ(6)")) == 0)
2846 +                       reply = do_read(fsg);
2847 +               break;
2848 +
2849 +       case READ_10:
2850 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2851 +               if ((reply = check_command_size_in_blocks(fsg, 10,
2852 +                               DATA_DIR_TO_HOST,
2853 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2854 +                               "READ(10)")) == 0)
2855 +                       reply = do_read(fsg);
2856 +               break;
2857 +
2858 +       case READ_12:
2859 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2860 +               if ((reply = check_command_size_in_blocks(fsg, 12,
2861 +                               DATA_DIR_TO_HOST,
2862 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
2863 +                               "READ(12)")) == 0)
2864 +                       reply = do_read(fsg);
2865 +               break;
2866 +
2867 +       case READ_CAPACITY:
2868 +               fsg->data_size_from_cmnd = 8;
2869 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2870 +                               (0xf<<2) | (1<<8), 1,
2871 +                               "READ CAPACITY")) == 0)
2872 +                       reply = do_read_capacity(fsg, bh);
2873 +               break;
2874 +
2875 +       case READ_HEADER:
2876 +               if (!mod_data.cdrom)
2877 +                       goto unknown_cmnd;
2878 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2879 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2880 +                               (3<<7) | (0x1f<<1), 1,
2881 +                               "READ HEADER")) == 0)
2882 +                       reply = do_read_header(fsg, bh);
2883 +               break;
2884 +
2885 +       case READ_TOC:
2886 +               if (!mod_data.cdrom)
2887 +                       goto unknown_cmnd;
2888 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2889 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2890 +                               (7<<6) | (1<<1), 1,
2891 +                               "READ TOC")) == 0)
2892 +                       reply = do_read_toc(fsg, bh);
2893 +               break;
2894 +
2895 +       case READ_FORMAT_CAPACITIES:
2896 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2897 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2898 +                               (3<<7), 1,
2899 +                               "READ FORMAT CAPACITIES")) == 0)
2900 +                       reply = do_read_format_capacities(fsg, bh);
2901 +               break;
2902 +
2903 +       case REQUEST_SENSE:
2904 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2905 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2906 +                               (1<<4), 0,
2907 +                               "REQUEST SENSE")) == 0)
2908 +                       reply = do_request_sense(fsg, bh);
2909 +               break;
2910 +
2911 +       case START_STOP:
2912 +               fsg->data_size_from_cmnd = 0;
2913 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2914 +                               (1<<1) | (1<<4), 0,
2915 +                               "START-STOP UNIT")) == 0)
2916 +                       reply = do_start_stop(fsg);
2917 +               break;
2918 +
2919 +       case SYNCHRONIZE_CACHE:
2920 +               fsg->data_size_from_cmnd = 0;
2921 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2922 +                               (0xf<<2) | (3<<7), 1,
2923 +                               "SYNCHRONIZE CACHE")) == 0)
2924 +                       reply = do_synchronize_cache(fsg);
2925 +               break;
2926 +
2927 +       case TEST_UNIT_READY:
2928 +               fsg->data_size_from_cmnd = 0;
2929 +               reply = check_command(fsg, 6, DATA_DIR_NONE,
2930 +                               0, 1,
2931 +                               "TEST UNIT READY");
2932 +               break;
2933 +
2934 +       /* Although optional, this command is used by MS-Windows.  We
2935 +        * support a minimal version: BytChk must be 0. */
2936 +       case VERIFY:
2937 +               fsg->data_size_from_cmnd = 0;
2938 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2939 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2940 +                               "VERIFY")) == 0)
2941 +                       reply = do_verify(fsg);
2942 +               break;
2943 +
2944 +       case WRITE_6:
2945 +               i = fsg->cmnd[4];
2946 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2947 +               if ((reply = check_command_size_in_blocks(fsg, 6,
2948 +                               DATA_DIR_FROM_HOST,
2949 +                               (7<<1) | (1<<4), 1,
2950 +                               "WRITE(6)")) == 0)
2951 +                       reply = do_write(fsg);
2952 +               break;
2953 +
2954 +       case WRITE_10:
2955 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2956 +               if ((reply = check_command_size_in_blocks(fsg, 10,
2957 +                               DATA_DIR_FROM_HOST,
2958 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2959 +                               "WRITE(10)")) == 0)
2960 +                       reply = do_write(fsg);
2961 +               break;
2962 +
2963 +       case WRITE_12:
2964 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2965 +               if ((reply = check_command_size_in_blocks(fsg, 12,
2966 +                               DATA_DIR_FROM_HOST,
2967 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
2968 +                               "WRITE(12)")) == 0)
2969 +                       reply = do_write(fsg);
2970 +               break;
2971 +
2972 +       /* Some mandatory commands that we recognize but don't implement.
2973 +        * They don't mean much in this setting.  It's left as an exercise
2974 +        * for anyone interested to implement RESERVE and RELEASE in terms
2975 +        * of Posix locks. */
2976 +       case FORMAT_UNIT:
2977 +       case RELEASE:
2978 +       case RESERVE:
2979 +       case SEND_DIAGNOSTIC:
2980 +               // Fall through
2981 +
2982 +       default:
2983 + unknown_cmnd:
2984 +               fsg->data_size_from_cmnd = 0;
2985 +               sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
2986 +               if ((reply = check_command(fsg, fsg->cmnd_size,
2987 +                               DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
2988 +                       fsg->curlun->sense_data = SS_INVALID_COMMAND;
2989 +                       reply = -EINVAL;
2990 +               }
2991 +               break;
2992 +       }
2993 +       up_read(&fsg->filesem);
2994 +
2995 +       if (reply == -EINTR || signal_pending(current))
2996 +               return -EINTR;
2997 +
2998 +       /* Set up the single reply buffer for finish_reply() */
2999 +       if (reply == -EINVAL)
3000 +               reply = 0;              // Error reply length
3001 +       if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
3002 +               reply = min((u32) reply, fsg->data_size_from_cmnd);
3003 +               bh->inreq->length = reply;
3004 +               bh->state = BUF_STATE_FULL;
3005 +               fsg->residue -= reply;
3006 +       }                               // Otherwise it's already set
3007 +
3008 +       return 0;
3009 +}
3010 +
3011 +
3012 +/*-------------------------------------------------------------------------*/
3013 +
3014 +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
3015 +{
3016 +       struct usb_request              *req = bh->outreq;
3017 +       struct bulk_cb_wrap     *cbw = req->buf;
3018 +
3019 +       /* Was this a real packet?  Should it be ignored? */
3020 +       if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3021 +               return -EINVAL;
3022 +
3023 +       /* Is the CBW valid? */
3024 +       if (req->actual != US_BULK_CB_WRAP_LEN ||
3025 +                       cbw->Signature != cpu_to_le32(
3026 +                               US_BULK_CB_SIGN)) {
3027 +               DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
3028 +                               req->actual,
3029 +                               le32_to_cpu(cbw->Signature));
3030 +
3031 +               /* The Bulk-only spec says we MUST stall the IN endpoint
3032 +                * (6.6.1), so it's unavoidable.  It also says we must
3033 +                * retain this state until the next reset, but there's
3034 +                * no way to tell the controller driver it should ignore
3035 +                * Clear-Feature(HALT) requests.
3036 +                *
3037 +                * We aren't required to halt the OUT endpoint; instead
3038 +                * we can simply accept and discard any data received
3039 +                * until the next reset. */
3040 +               wedge_bulk_in_endpoint(fsg);
3041 +               set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3042 +               return -EINVAL;
3043 +       }
3044 +
3045 +       /* Is the CBW meaningful? */
3046 +       if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
3047 +                       cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
3048 +               DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
3049 +                               "cmdlen %u\n",
3050 +                               cbw->Lun, cbw->Flags, cbw->Length);
3051 +
3052 +               /* We can do anything we want here, so let's stall the
3053 +                * bulk pipes if we are allowed to. */
3054 +               if (mod_data.can_stall) {
3055 +                       fsg_set_halt(fsg, fsg->bulk_out);
3056 +                       halt_bulk_in_endpoint(fsg);
3057 +               }
3058 +               return -EINVAL;
3059 +       }
3060 +
3061 +       /* Save the command for later */
3062 +       fsg->cmnd_size = cbw->Length;
3063 +       memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
3064 +       if (cbw->Flags & US_BULK_FLAG_IN)
3065 +               fsg->data_dir = DATA_DIR_TO_HOST;
3066 +       else
3067 +               fsg->data_dir = DATA_DIR_FROM_HOST;
3068 +       fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
3069 +       if (fsg->data_size == 0)
3070 +               fsg->data_dir = DATA_DIR_NONE;
3071 +       fsg->lun = cbw->Lun;
3072 +       fsg->tag = cbw->Tag;
3073 +       return 0;
3074 +}
3075 +
3076 +
3077 +static int get_next_command(struct fsg_dev *fsg)
3078 +{
3079 +       struct fsg_buffhd       *bh;
3080 +       int                     rc = 0;
3081 +
3082 +       if (transport_is_bbb()) {
3083 +
3084 +               /* Wait for the next buffer to become available */
3085 +               bh = fsg->next_buffhd_to_fill;
3086 +               while (bh->state != BUF_STATE_EMPTY) {
3087 +                       rc = sleep_thread(fsg);
3088 +                       if (rc)
3089 +                               return rc;
3090 +               }
3091 +
3092 +               /* Queue a request to read a Bulk-only CBW */
3093 +               set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
3094 +               start_transfer(fsg, fsg->bulk_out, bh->outreq,
3095 +                               &bh->outreq_busy, &bh->state);
3096 +
3097 +               /* We will drain the buffer in software, which means we
3098 +                * can reuse it for the next filling.  No need to advance
3099 +                * next_buffhd_to_fill. */
3100 +
3101 +               /* Wait for the CBW to arrive */
3102 +               while (bh->state != BUF_STATE_FULL) {
3103 +                       rc = sleep_thread(fsg);
3104 +                       if (rc)
3105 +                               return rc;
3106 +               }
3107 +               smp_rmb();
3108 +               rc = received_cbw(fsg, bh);
3109 +               bh->state = BUF_STATE_EMPTY;
3110 +
3111 +       } else {                // USB_PR_CB or USB_PR_CBI
3112 +
3113 +               /* Wait for the next command to arrive */
3114 +               while (fsg->cbbuf_cmnd_size == 0) {
3115 +                       rc = sleep_thread(fsg);
3116 +                       if (rc)
3117 +                               return rc;
3118 +               }
3119 +
3120 +               /* Is the previous status interrupt request still busy?
3121 +                * The host is allowed to skip reading the status,
3122 +                * so we must cancel it. */
3123 +               if (fsg->intreq_busy)
3124 +                       usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3125 +
3126 +               /* Copy the command and mark the buffer empty */
3127 +               fsg->data_dir = DATA_DIR_UNKNOWN;
3128 +               spin_lock_irq(&fsg->lock);
3129 +               fsg->cmnd_size = fsg->cbbuf_cmnd_size;
3130 +               memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
3131 +               fsg->cbbuf_cmnd_size = 0;
3132 +               spin_unlock_irq(&fsg->lock);
3133 +
3134 +               /* Use LUN from the command */
3135 +               fsg->lun = fsg->cmnd[1] >> 5;
3136 +       }
3137 +
3138 +       /* Update current lun */
3139 +       if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
3140 +               fsg->curlun = &fsg->luns[fsg->lun];
3141 +       else
3142 +               fsg->curlun = NULL;
3143 +
3144 +       return rc;
3145 +}
3146 +
3147 +
3148 +/*-------------------------------------------------------------------------*/
3149 +
3150 +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
3151 +               const struct usb_endpoint_descriptor *d)
3152 +{
3153 +       int     rc;
3154 +
3155 +       ep->driver_data = fsg;
3156 +       ep->desc = d;
3157 +       rc = usb_ep_enable(ep);
3158 +       if (rc)
3159 +               ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
3160 +       return rc;
3161 +}
3162 +
3163 +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
3164 +               struct usb_request **preq)
3165 +{
3166 +       *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
3167 +       if (*preq)
3168 +               return 0;
3169 +       ERROR(fsg, "can't allocate request for %s\n", ep->name);
3170 +       return -ENOMEM;
3171 +}
3172 +
3173 +/*
3174 + * Reset interface setting and re-init endpoint state (toggle etc).
3175 + * Call with altsetting < 0 to disable the interface.  The only other
3176 + * available altsetting is 0, which enables the interface.
3177 + */
3178 +static int do_set_interface(struct fsg_dev *fsg, int altsetting)
3179 +{
3180 +       int     rc = 0;
3181 +       int     i;
3182 +       const struct usb_endpoint_descriptor    *d;
3183 +
3184 +       if (fsg->running)
3185 +               DBG(fsg, "reset interface\n");
3186 +
3187 +reset:
3188 +       /* Deallocate the requests */
3189 +       for (i = 0; i < fsg_num_buffers; ++i) {
3190 +               struct fsg_buffhd *bh = &fsg->buffhds[i];
3191 +
3192 +               if (bh->inreq) {
3193 +                       usb_ep_free_request(fsg->bulk_in, bh->inreq);
3194 +                       bh->inreq = NULL;
3195 +               }
3196 +               if (bh->outreq) {
3197 +                       usb_ep_free_request(fsg->bulk_out, bh->outreq);
3198 +                       bh->outreq = NULL;
3199 +               }
3200 +       }
3201 +       if (fsg->intreq) {
3202 +               usb_ep_free_request(fsg->intr_in, fsg->intreq);
3203 +               fsg->intreq = NULL;
3204 +       }
3205 +
3206 +       /* Disable the endpoints */
3207 +       if (fsg->bulk_in_enabled) {
3208 +               usb_ep_disable(fsg->bulk_in);
3209 +               fsg->bulk_in_enabled = 0;
3210 +       }
3211 +       if (fsg->bulk_out_enabled) {
3212 +               usb_ep_disable(fsg->bulk_out);
3213 +               fsg->bulk_out_enabled = 0;
3214 +       }
3215 +       if (fsg->intr_in_enabled) {
3216 +               usb_ep_disable(fsg->intr_in);
3217 +               fsg->intr_in_enabled = 0;
3218 +       }
3219 +
3220 +       fsg->running = 0;
3221 +       if (altsetting < 0 || rc != 0)
3222 +               return rc;
3223 +
3224 +       DBG(fsg, "set interface %d\n", altsetting);
3225 +
3226 +       /* Enable the endpoints */
3227 +       d = fsg_ep_desc(fsg->gadget,
3228 +                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
3229 +                       &fsg_ss_bulk_in_desc);
3230 +       if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
3231 +               goto reset;
3232 +       fsg->bulk_in_enabled = 1;
3233 +
3234 +       d = fsg_ep_desc(fsg->gadget,
3235 +                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
3236 +                       &fsg_ss_bulk_out_desc);
3237 +       if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
3238 +               goto reset;
3239 +       fsg->bulk_out_enabled = 1;
3240 +       fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
3241 +       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3242 +
3243 +       if (transport_is_cbi()) {
3244 +               d = fsg_ep_desc(fsg->gadget,
3245 +                               &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
3246 +                               &fsg_ss_intr_in_desc);
3247 +               if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
3248 +                       goto reset;
3249 +               fsg->intr_in_enabled = 1;
3250 +       }
3251 +
3252 +       /* Allocate the requests */
3253 +       for (i = 0; i < fsg_num_buffers; ++i) {
3254 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3255 +
3256 +               if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
3257 +                       goto reset;
3258 +               if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
3259 +                       goto reset;
3260 +               bh->inreq->buf = bh->outreq->buf = bh->buf;
3261 +               bh->inreq->context = bh->outreq->context = bh;
3262 +               bh->inreq->complete = bulk_in_complete;
3263 +               bh->outreq->complete = bulk_out_complete;
3264 +       }
3265 +       if (transport_is_cbi()) {
3266 +               if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
3267 +                       goto reset;
3268 +               fsg->intreq->complete = intr_in_complete;
3269 +       }
3270 +
3271 +       fsg->running = 1;
3272 +       for (i = 0; i < fsg->nluns; ++i)
3273 +               fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3274 +       return rc;
3275 +}
3276 +
3277 +
3278 +/*
3279 + * Change our operational configuration.  This code must agree with the code
3280 + * that returns config descriptors, and with interface altsetting code.
3281 + *
3282 + * It's also responsible for power management interactions.  Some
3283 + * configurations might not work with our current power sources.
3284 + * For now we just assume the gadget is always self-powered.
3285 + */
3286 +static int do_set_config(struct fsg_dev *fsg, u8 new_config)
3287 +{
3288 +       int     rc = 0;
3289 +
3290 +       /* Disable the single interface */
3291 +       if (fsg->config != 0) {
3292 +               DBG(fsg, "reset config\n");
3293 +               fsg->config = 0;
3294 +               rc = do_set_interface(fsg, -1);
3295 +       }
3296 +
3297 +       /* Enable the interface */
3298 +       if (new_config != 0) {
3299 +               fsg->config = new_config;
3300 +               if ((rc = do_set_interface(fsg, 0)) != 0)
3301 +                       fsg->config = 0;        // Reset on errors
3302 +               else
3303 +                       INFO(fsg, "%s config #%d\n",
3304 +                            usb_speed_string(fsg->gadget->speed),
3305 +                            fsg->config);
3306 +       }
3307 +       return rc;
3308 +}
3309 +
3310 +
3311 +/*-------------------------------------------------------------------------*/
3312 +
3313 +static void handle_exception(struct fsg_dev *fsg)
3314 +{
3315 +       siginfo_t               info;
3316 +       int                     sig;
3317 +       int                     i;
3318 +       int                     num_active;
3319 +       struct fsg_buffhd       *bh;
3320 +       enum fsg_state          old_state;
3321 +       u8                      new_config;
3322 +       struct fsg_lun          *curlun;
3323 +       unsigned int            exception_req_tag;
3324 +       int                     rc;
3325 +
3326 +       /* Clear the existing signals.  Anything but SIGUSR1 is converted
3327 +        * into a high-priority EXIT exception. */
3328 +       for (;;) {
3329 +               sig = dequeue_signal_lock(current, &current->blocked, &info);
3330 +               if (!sig)
3331 +                       break;
3332 +               if (sig != SIGUSR1) {
3333 +                       if (fsg->state < FSG_STATE_EXIT)
3334 +                               DBG(fsg, "Main thread exiting on signal\n");
3335 +                       raise_exception(fsg, FSG_STATE_EXIT);
3336 +               }
3337 +       }
3338 +
3339 +       /* Cancel all the pending transfers */
3340 +       if (fsg->intreq_busy)
3341 +               usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3342 +       for (i = 0; i < fsg_num_buffers; ++i) {
3343 +               bh = &fsg->buffhds[i];
3344 +               if (bh->inreq_busy)
3345 +                       usb_ep_dequeue(fsg->bulk_in, bh->inreq);
3346 +               if (bh->outreq_busy)
3347 +                       usb_ep_dequeue(fsg->bulk_out, bh->outreq);
3348 +       }
3349 +
3350 +       /* Wait until everything is idle */
3351 +       for (;;) {
3352 +               num_active = fsg->intreq_busy;
3353 +               for (i = 0; i < fsg_num_buffers; ++i) {
3354 +                       bh = &fsg->buffhds[i];
3355 +                       num_active += bh->inreq_busy + bh->outreq_busy;
3356 +               }
3357 +               if (num_active == 0)
3358 +                       break;
3359 +               if (sleep_thread(fsg))
3360 +                       return;
3361 +       }
3362 +
3363 +       /* Clear out the controller's fifos */
3364 +       if (fsg->bulk_in_enabled)
3365 +               usb_ep_fifo_flush(fsg->bulk_in);
3366 +       if (fsg->bulk_out_enabled)
3367 +               usb_ep_fifo_flush(fsg->bulk_out);
3368 +       if (fsg->intr_in_enabled)
3369 +               usb_ep_fifo_flush(fsg->intr_in);
3370 +
3371 +       /* Reset the I/O buffer states and pointers, the SCSI
3372 +        * state, and the exception.  Then invoke the handler. */
3373 +       spin_lock_irq(&fsg->lock);
3374 +
3375 +       for (i = 0; i < fsg_num_buffers; ++i) {
3376 +               bh = &fsg->buffhds[i];
3377 +               bh->state = BUF_STATE_EMPTY;
3378 +       }
3379 +       fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
3380 +                       &fsg->buffhds[0];
3381 +
3382 +       exception_req_tag = fsg->exception_req_tag;
3383 +       new_config = fsg->new_config;
3384 +       old_state = fsg->state;
3385 +
3386 +       if (old_state == FSG_STATE_ABORT_BULK_OUT)
3387 +               fsg->state = FSG_STATE_STATUS_PHASE;
3388 +       else {
3389 +               for (i = 0; i < fsg->nluns; ++i) {
3390 +                       curlun = &fsg->luns[i];
3391 +                       curlun->prevent_medium_removal = 0;
3392 +                       curlun->sense_data = curlun->unit_attention_data =
3393 +                                       SS_NO_SENSE;
3394 +                       curlun->sense_data_info = 0;
3395 +                       curlun->info_valid = 0;
3396 +               }
3397 +               fsg->state = FSG_STATE_IDLE;
3398 +       }
3399 +       spin_unlock_irq(&fsg->lock);
3400 +
3401 +       /* Carry out any extra actions required for the exception */
3402 +       switch (old_state) {
3403 +       default:
3404 +               break;
3405 +
3406 +       case FSG_STATE_ABORT_BULK_OUT:
3407 +               send_status(fsg);
3408 +               spin_lock_irq(&fsg->lock);
3409 +               if (fsg->state == FSG_STATE_STATUS_PHASE)
3410 +                       fsg->state = FSG_STATE_IDLE;
3411 +               spin_unlock_irq(&fsg->lock);
3412 +               break;
3413 +
3414 +       case FSG_STATE_RESET:
3415 +               /* In case we were forced against our will to halt a
3416 +                * bulk endpoint, clear the halt now.  (The SuperH UDC
3417 +                * requires this.) */
3418 +               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3419 +                       usb_ep_clear_halt(fsg->bulk_in);
3420 +
3421 +               if (transport_is_bbb()) {
3422 +                       if (fsg->ep0_req_tag == exception_req_tag)
3423 +                               ep0_queue(fsg); // Complete the status stage
3424 +
3425 +               } else if (transport_is_cbi())
3426 +                       send_status(fsg);       // Status by interrupt pipe
3427 +
3428 +               /* Technically this should go here, but it would only be
3429 +                * a waste of time.  Ditto for the INTERFACE_CHANGE and
3430 +                * CONFIG_CHANGE cases. */
3431 +               // for (i = 0; i < fsg->nluns; ++i)
3432 +               //      fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3433 +               break;
3434 +
3435 +       case FSG_STATE_INTERFACE_CHANGE:
3436 +               rc = do_set_interface(fsg, 0);
3437 +               if (fsg->ep0_req_tag != exception_req_tag)
3438 +                       break;
3439 +               if (rc != 0)                    // STALL on errors
3440 +                       fsg_set_halt(fsg, fsg->ep0);
3441 +               else                            // Complete the status stage
3442 +                       ep0_queue(fsg);
3443 +               break;
3444 +
3445 +       case FSG_STATE_CONFIG_CHANGE:
3446 +               rc = do_set_config(fsg, new_config);
3447 +               if (fsg->ep0_req_tag != exception_req_tag)
3448 +                       break;
3449 +               if (rc != 0)                    // STALL on errors
3450 +                       fsg_set_halt(fsg, fsg->ep0);
3451 +               else                            // Complete the status stage
3452 +                       ep0_queue(fsg);
3453 +               break;
3454 +
3455 +       case FSG_STATE_DISCONNECT:
3456 +               for (i = 0; i < fsg->nluns; ++i)
3457 +                       fsg_lun_fsync_sub(fsg->luns + i);
3458 +               do_set_config(fsg, 0);          // Unconfigured state
3459 +               break;
3460 +
3461 +       case FSG_STATE_EXIT:
3462 +       case FSG_STATE_TERMINATED:
3463 +               do_set_config(fsg, 0);                  // Free resources
3464 +               spin_lock_irq(&fsg->lock);
3465 +               fsg->state = FSG_STATE_TERMINATED;      // Stop the thread
3466 +               spin_unlock_irq(&fsg->lock);
3467 +               break;
3468 +       }
3469 +}
3470 +
3471 +
3472 +/*-------------------------------------------------------------------------*/
3473 +
3474 +static int fsg_main_thread(void *fsg_)
3475 +{
3476 +       struct fsg_dev          *fsg = fsg_;
3477 +
3478 +       /* Allow the thread to be killed by a signal, but set the signal mask
3479 +        * to block everything but INT, TERM, KILL, and USR1. */
3480 +       allow_signal(SIGINT);
3481 +       allow_signal(SIGTERM);
3482 +       allow_signal(SIGKILL);
3483 +       allow_signal(SIGUSR1);
3484 +
3485 +       /* Allow the thread to be frozen */
3486 +       set_freezable();
3487 +
3488 +       /* Arrange for userspace references to be interpreted as kernel
3489 +        * pointers.  That way we can pass a kernel pointer to a routine
3490 +        * that expects a __user pointer and it will work okay. */
3491 +       set_fs(get_ds());
3492 +
3493 +       /* The main loop */
3494 +       while (fsg->state != FSG_STATE_TERMINATED) {
3495 +               if (exception_in_progress(fsg) || signal_pending(current)) {
3496 +                       handle_exception(fsg);
3497 +                       continue;
3498 +               }
3499 +
3500 +               if (!fsg->running) {
3501 +                       sleep_thread(fsg);
3502 +                       continue;
3503 +               }
3504 +
3505 +               if (get_next_command(fsg))
3506 +                       continue;
3507 +
3508 +               spin_lock_irq(&fsg->lock);
3509 +               if (!exception_in_progress(fsg))
3510 +                       fsg->state = FSG_STATE_DATA_PHASE;
3511 +               spin_unlock_irq(&fsg->lock);
3512 +
3513 +               if (do_scsi_command(fsg) || finish_reply(fsg))
3514 +                       continue;
3515 +
3516 +               spin_lock_irq(&fsg->lock);
3517 +               if (!exception_in_progress(fsg))
3518 +                       fsg->state = FSG_STATE_STATUS_PHASE;
3519 +               spin_unlock_irq(&fsg->lock);
3520 +
3521 +               if (send_status(fsg))
3522 +                       continue;
3523 +
3524 +               spin_lock_irq(&fsg->lock);
3525 +               if (!exception_in_progress(fsg))
3526 +                       fsg->state = FSG_STATE_IDLE;
3527 +               spin_unlock_irq(&fsg->lock);
3528 +               }
3529 +
3530 +       spin_lock_irq(&fsg->lock);
3531 +       fsg->thread_task = NULL;
3532 +       spin_unlock_irq(&fsg->lock);
3533 +
3534 +       /* If we are exiting because of a signal, unregister the
3535 +        * gadget driver. */
3536 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
3537 +               usb_gadget_unregister_driver(&fsg_driver);
3538 +
3539 +       /* Let the unbind and cleanup routines know the thread has exited */
3540 +       complete_and_exit(&fsg->thread_notifier, 0);
3541 +}
3542 +
3543 +
3544 +/*-------------------------------------------------------------------------*/
3545 +
3546 +
3547 +/* The write permissions and store_xxx pointers are set in fsg_bind() */
3548 +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
3549 +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
3550 +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
3551 +
3552 +
3553 +/*-------------------------------------------------------------------------*/
3554 +
3555 +static void fsg_release(struct kref *ref)
3556 +{
3557 +       struct fsg_dev  *fsg = container_of(ref, struct fsg_dev, ref);
3558 +
3559 +       kfree(fsg->luns);
3560 +       kfree(fsg);
3561 +}
3562 +
3563 +static void lun_release(struct device *dev)
3564 +{
3565 +       struct rw_semaphore     *filesem = dev_get_drvdata(dev);
3566 +       struct fsg_dev          *fsg =
3567 +               container_of(filesem, struct fsg_dev, filesem);
3568 +
3569 +       kref_put(&fsg->ref, fsg_release);
3570 +}
3571 +
3572 +static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
3573 +{
3574 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
3575 +       int                     i;
3576 +       struct fsg_lun          *curlun;
3577 +       struct usb_request      *req = fsg->ep0req;
3578 +
3579 +       DBG(fsg, "unbind\n");
3580 +       clear_bit(REGISTERED, &fsg->atomic_bitflags);
3581 +
3582 +       /* If the thread isn't already dead, tell it to exit now */
3583 +       if (fsg->state != FSG_STATE_TERMINATED) {
3584 +               raise_exception(fsg, FSG_STATE_EXIT);
3585 +               wait_for_completion(&fsg->thread_notifier);
3586 +
3587 +               /* The cleanup routine waits for this completion also */
3588 +               complete(&fsg->thread_notifier);
3589 +       }
3590 +
3591 +       /* Unregister the sysfs attribute files and the LUNs */
3592 +       for (i = 0; i < fsg->nluns; ++i) {
3593 +               curlun = &fsg->luns[i];
3594 +               if (curlun->registered) {
3595 +                       device_remove_file(&curlun->dev, &dev_attr_nofua);
3596 +                       device_remove_file(&curlun->dev, &dev_attr_ro);
3597 +                       device_remove_file(&curlun->dev, &dev_attr_file);
3598 +                       fsg_lun_close(curlun);
3599 +                       device_unregister(&curlun->dev);
3600 +                       curlun->registered = 0;
3601 +               }
3602 +       }
3603 +
3604 +       /* Free the data buffers */
3605 +       for (i = 0; i < fsg_num_buffers; ++i)
3606 +               kfree(fsg->buffhds[i].buf);
3607 +
3608 +       /* Free the request and buffer for endpoint 0 */
3609 +       if (req) {
3610 +               kfree(req->buf);
3611 +               usb_ep_free_request(fsg->ep0, req);
3612 +       }
3613 +
3614 +       set_gadget_data(gadget, NULL);
3615 +}
3616 +
3617 +
3618 +static int __init check_parameters(struct fsg_dev *fsg)
3619 +{
3620 +       int     prot;
3621 +       int     gcnum;
3622 +
3623 +       /* Store the default values */
3624 +       mod_data.transport_type = USB_PR_BULK;
3625 +       mod_data.transport_name = "Bulk-only";
3626 +       mod_data.protocol_type = USB_SC_SCSI;
3627 +       mod_data.protocol_name = "Transparent SCSI";
3628 +
3629 +       /* Some peripheral controllers are known not to be able to
3630 +        * halt bulk endpoints correctly.  If one of them is present,
3631 +        * disable stalls.
3632 +        */
3633 +       if (gadget_is_at91(fsg->gadget))
3634 +               mod_data.can_stall = 0;
3635 +
3636 +       if (mod_data.release == 0xffff) {       // Parameter wasn't set
3637 +               gcnum = usb_gadget_controller_number(fsg->gadget);
3638 +               if (gcnum >= 0)
3639 +                       mod_data.release = 0x0300 + gcnum;
3640 +               else {
3641 +                       WARNING(fsg, "controller '%s' not recognized\n",
3642 +                               fsg->gadget->name);
3643 +                       mod_data.release = 0x0399;
3644 +               }
3645 +       }
3646 +
3647 +       prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
3648 +
3649 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
3650 +       if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
3651 +               ;               // Use default setting
3652 +       } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
3653 +               mod_data.transport_type = USB_PR_CB;
3654 +               mod_data.transport_name = "Control-Bulk";
3655 +       } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
3656 +               mod_data.transport_type = USB_PR_CBI;
3657 +               mod_data.transport_name = "Control-Bulk-Interrupt";
3658 +       } else {
3659 +               ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
3660 +               return -EINVAL;
3661 +       }
3662 +
3663 +       if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
3664 +                       prot == USB_SC_SCSI) {
3665 +               ;               // Use default setting
3666 +       } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
3667 +                       prot == USB_SC_RBC) {
3668 +               mod_data.protocol_type = USB_SC_RBC;
3669 +               mod_data.protocol_name = "RBC";
3670 +       } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
3671 +                       strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
3672 +                       prot == USB_SC_8020) {
3673 +               mod_data.protocol_type = USB_SC_8020;
3674 +               mod_data.protocol_name = "8020i (ATAPI)";
3675 +       } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
3676 +                       prot == USB_SC_QIC) {
3677 +               mod_data.protocol_type = USB_SC_QIC;
3678 +               mod_data.protocol_name = "QIC-157";
3679 +       } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
3680 +                       prot == USB_SC_UFI) {
3681 +               mod_data.protocol_type = USB_SC_UFI;
3682 +               mod_data.protocol_name = "UFI";
3683 +       } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
3684 +                       prot == USB_SC_8070) {
3685 +               mod_data.protocol_type = USB_SC_8070;
3686 +               mod_data.protocol_name = "8070i";
3687 +       } else {
3688 +               ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
3689 +               return -EINVAL;
3690 +       }
3691 +
3692 +       mod_data.buflen &= PAGE_CACHE_MASK;
3693 +       if (mod_data.buflen <= 0) {
3694 +               ERROR(fsg, "invalid buflen\n");
3695 +               return -ETOOSMALL;
3696 +       }
3697 +
3698 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
3699 +
3700 +       /* Serial string handling.
3701 +        * On a real device, the serial string would be loaded
3702 +        * from permanent storage. */
3703 +       if (mod_data.serial) {
3704 +               const char *ch;
3705 +               unsigned len = 0;
3706 +
3707 +               /* Sanity check :
3708 +                * The CB[I] specification limits the serial string to
3709 +                * 12 uppercase hexadecimal characters.
3710 +                * BBB need at least 12 uppercase hexadecimal characters,
3711 +                * with a maximum of 126. */
3712 +               for (ch = mod_data.serial; *ch; ++ch) {
3713 +                       ++len;
3714 +                       if ((*ch < '0' || *ch > '9') &&
3715 +                           (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
3716 +                               WARNING(fsg,
3717 +                                       "Invalid serial string character: %c\n",
3718 +                                       *ch);
3719 +                               goto no_serial;
3720 +                       }
3721 +               }
3722 +               if (len > 126 ||
3723 +                   (mod_data.transport_type == USB_PR_BULK && len < 12) ||
3724 +                   (mod_data.transport_type != USB_PR_BULK && len > 12)) {
3725 +                       WARNING(fsg, "Invalid serial string length!\n");
3726 +                       goto no_serial;
3727 +               }
3728 +               fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
3729 +       } else {
3730 +               WARNING(fsg, "No serial-number string provided!\n");
3731 + no_serial:
3732 +               device_desc.iSerialNumber = 0;
3733 +       }
3734 +
3735 +       return 0;
3736 +}
3737 +
3738 +
3739 +static int __init fsg_bind(struct usb_gadget *gadget)
3740 +{
3741 +       struct fsg_dev          *fsg = the_fsg;
3742 +       int                     rc;
3743 +       int                     i;
3744 +       struct fsg_lun          *curlun;
3745 +       struct usb_ep           *ep;
3746 +       struct usb_request      *req;
3747 +       char                    *pathbuf, *p;
3748 +
3749 +       fsg->gadget = gadget;
3750 +       set_gadget_data(gadget, fsg);
3751 +       fsg->ep0 = gadget->ep0;
3752 +       fsg->ep0->driver_data = fsg;
3753 +
3754 +       if ((rc = check_parameters(fsg)) != 0)
3755 +               goto out;
3756 +
3757 +       if (mod_data.removable) {       // Enable the store_xxx attributes
3758 +               dev_attr_file.attr.mode = 0644;
3759 +               dev_attr_file.store = fsg_store_file;
3760 +               if (!mod_data.cdrom) {
3761 +                       dev_attr_ro.attr.mode = 0644;
3762 +                       dev_attr_ro.store = fsg_store_ro;
3763 +               }
3764 +       }
3765 +
3766 +       /* Only for removable media? */
3767 +       dev_attr_nofua.attr.mode = 0644;
3768 +       dev_attr_nofua.store = fsg_store_nofua;
3769 +
3770 +       /* Find out how many LUNs there should be */
3771 +       i = mod_data.nluns;
3772 +       if (i == 0)
3773 +               i = max(mod_data.num_filenames, 1u);
3774 +       if (i > FSG_MAX_LUNS) {
3775 +               ERROR(fsg, "invalid number of LUNs: %d\n", i);
3776 +               rc = -EINVAL;
3777 +               goto out;
3778 +       }
3779 +
3780 +       /* Create the LUNs, open their backing files, and register the
3781 +        * LUN devices in sysfs. */
3782 +       fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
3783 +       if (!fsg->luns) {
3784 +               rc = -ENOMEM;
3785 +               goto out;
3786 +       }
3787 +       fsg->nluns = i;
3788 +
3789 +       for (i = 0; i < fsg->nluns; ++i) {
3790 +               curlun = &fsg->luns[i];
3791 +               curlun->cdrom = !!mod_data.cdrom;
3792 +               curlun->ro = mod_data.cdrom || mod_data.ro[i];
3793 +               curlun->initially_ro = curlun->ro;
3794 +               curlun->removable = mod_data.removable;
3795 +               curlun->nofua = mod_data.nofua[i];
3796 +               curlun->dev.release = lun_release;
3797 +               curlun->dev.parent = &gadget->dev;
3798 +               curlun->dev.driver = &fsg_driver.driver;
3799 +               dev_set_drvdata(&curlun->dev, &fsg->filesem);
3800 +               dev_set_name(&curlun->dev,"%s-lun%d",
3801 +                            dev_name(&gadget->dev), i);
3802 +
3803 +               kref_get(&fsg->ref);
3804 +               rc = device_register(&curlun->dev);
3805 +               if (rc) {
3806 +                       INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
3807 +                       put_device(&curlun->dev);
3808 +                       goto out;
3809 +               }
3810 +               curlun->registered = 1;
3811 +
3812 +               rc = device_create_file(&curlun->dev, &dev_attr_ro);
3813 +               if (rc)
3814 +                       goto out;
3815 +               rc = device_create_file(&curlun->dev, &dev_attr_nofua);
3816 +               if (rc)
3817 +                       goto out;
3818 +               rc = device_create_file(&curlun->dev, &dev_attr_file);
3819 +               if (rc)
3820 +                       goto out;
3821 +
3822 +               if (mod_data.file[i] && *mod_data.file[i]) {
3823 +                       rc = fsg_lun_open(curlun, mod_data.file[i]);
3824 +                       if (rc)
3825 +                               goto out;
3826 +               } else if (!mod_data.removable) {
3827 +                       ERROR(fsg, "no file given for LUN%d\n", i);
3828 +                       rc = -EINVAL;
3829 +                       goto out;
3830 +               }
3831 +       }
3832 +
3833 +       /* Find all the endpoints we will use */
3834 +       usb_ep_autoconfig_reset(gadget);
3835 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
3836 +       if (!ep)
3837 +               goto autoconf_fail;
3838 +       ep->driver_data = fsg;          // claim the endpoint
3839 +       fsg->bulk_in = ep;
3840 +
3841 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
3842 +       if (!ep)
3843 +               goto autoconf_fail;
3844 +       ep->driver_data = fsg;          // claim the endpoint
3845 +       fsg->bulk_out = ep;
3846 +
3847 +       if (transport_is_cbi()) {
3848 +               ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
3849 +               if (!ep)
3850 +                       goto autoconf_fail;
3851 +               ep->driver_data = fsg;          // claim the endpoint
3852 +               fsg->intr_in = ep;
3853 +       }
3854 +
3855 +       /* Fix up the descriptors */
3856 +       device_desc.idVendor = cpu_to_le16(mod_data.vendor);
3857 +       device_desc.idProduct = cpu_to_le16(mod_data.product);
3858 +       device_desc.bcdDevice = cpu_to_le16(mod_data.release);
3859 +
3860 +       i = (transport_is_cbi() ? 3 : 2);       // Number of endpoints
3861 +       fsg_intf_desc.bNumEndpoints = i;
3862 +       fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
3863 +       fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
3864 +       fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3865 +
3866 +       if (gadget_is_dualspeed(gadget)) {
3867 +               fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3868 +
3869 +               /* Assume endpoint addresses are the same for both speeds */
3870 +               fsg_hs_bulk_in_desc.bEndpointAddress =
3871 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3872 +               fsg_hs_bulk_out_desc.bEndpointAddress =
3873 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3874 +               fsg_hs_intr_in_desc.bEndpointAddress =
3875 +                       fsg_fs_intr_in_desc.bEndpointAddress;
3876 +       }
3877 +
3878 +       if (gadget_is_superspeed(gadget)) {
3879 +               unsigned                max_burst;
3880 +
3881 +               fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3882 +
3883 +               /* Calculate bMaxBurst, we know packet size is 1024 */
3884 +               max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
3885 +
3886 +               /* Assume endpoint addresses are the same for both speeds */
3887 +               fsg_ss_bulk_in_desc.bEndpointAddress =
3888 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3889 +               fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
3890 +
3891 +               fsg_ss_bulk_out_desc.bEndpointAddress =
3892 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3893 +               fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
3894 +       }
3895 +
3896 +       if (gadget_is_otg(gadget))
3897 +               fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
3898 +
3899 +       rc = -ENOMEM;
3900 +
3901 +       /* Allocate the request and buffer for endpoint 0 */
3902 +       fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
3903 +       if (!req)
3904 +               goto out;
3905 +       req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
3906 +       if (!req->buf)
3907 +               goto out;
3908 +       req->complete = ep0_complete;
3909 +
3910 +       /* Allocate the data buffers */
3911 +       for (i = 0; i < fsg_num_buffers; ++i) {
3912 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3913 +
3914 +               /* Allocate for the bulk-in endpoint.  We assume that
3915 +                * the buffer will also work with the bulk-out (and
3916 +                * interrupt-in) endpoint. */
3917 +               bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
3918 +               if (!bh->buf)
3919 +                       goto out;
3920 +               bh->next = bh + 1;
3921 +       }
3922 +       fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
3923 +
3924 +       /* This should reflect the actual gadget power source */
3925 +       usb_gadget_set_selfpowered(gadget);
3926 +
3927 +       snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
3928 +                       "%s %s with %s",
3929 +                       init_utsname()->sysname, init_utsname()->release,
3930 +                       gadget->name);
3931 +
3932 +       fsg->thread_task = kthread_create(fsg_main_thread, fsg,
3933 +                       "file-storage-gadget");
3934 +       if (IS_ERR(fsg->thread_task)) {
3935 +               rc = PTR_ERR(fsg->thread_task);
3936 +               goto out;
3937 +       }
3938 +
3939 +       INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
3940 +       INFO(fsg, "NOTE: This driver is deprecated.  "
3941 +                       "Consider using g_mass_storage instead.\n");
3942 +       INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
3943 +
3944 +       pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
3945 +       for (i = 0; i < fsg->nluns; ++i) {
3946 +               curlun = &fsg->luns[i];
3947 +               if (fsg_lun_is_open(curlun)) {
3948 +                       p = NULL;
3949 +                       if (pathbuf) {
3950 +                               p = d_path(&curlun->filp->f_path,
3951 +                                          pathbuf, PATH_MAX);
3952 +                               if (IS_ERR(p))
3953 +                                       p = NULL;
3954 +                       }
3955 +                       LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
3956 +                             curlun->ro, curlun->nofua, (p ? p : "(error)"));
3957 +               }
3958 +       }
3959 +       kfree(pathbuf);
3960 +
3961 +       DBG(fsg, "transport=%s (x%02x)\n",
3962 +                       mod_data.transport_name, mod_data.transport_type);
3963 +       DBG(fsg, "protocol=%s (x%02x)\n",
3964 +                       mod_data.protocol_name, mod_data.protocol_type);
3965 +       DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
3966 +                       mod_data.vendor, mod_data.product, mod_data.release);
3967 +       DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
3968 +                       mod_data.removable, mod_data.can_stall,
3969 +                       mod_data.cdrom, mod_data.buflen);
3970 +       DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
3971 +
3972 +       set_bit(REGISTERED, &fsg->atomic_bitflags);
3973 +
3974 +       /* Tell the thread to start working */
3975 +       wake_up_process(fsg->thread_task);
3976 +       return 0;
3977 +
3978 +autoconf_fail:
3979 +       ERROR(fsg, "unable to autoconfigure all endpoints\n");
3980 +       rc = -ENOTSUPP;
3981 +
3982 +out:
3983 +       fsg->state = FSG_STATE_TERMINATED;      // The thread is dead
3984 +       fsg_unbind(gadget);
3985 +       complete(&fsg->thread_notifier);
3986 +       return rc;
3987 +}
3988 +
3989 +
3990 +/*-------------------------------------------------------------------------*/
3991 +
3992 +static void fsg_suspend(struct usb_gadget *gadget)
3993 +{
3994 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
3995 +
3996 +       DBG(fsg, "suspend\n");
3997 +       set_bit(SUSPENDED, &fsg->atomic_bitflags);
3998 +}
3999 +
4000 +static void fsg_resume(struct usb_gadget *gadget)
4001 +{
4002 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4003 +
4004 +       DBG(fsg, "resume\n");
4005 +       clear_bit(SUSPENDED, &fsg->atomic_bitflags);
4006 +}
4007 +
4008 +
4009 +/*-------------------------------------------------------------------------*/
4010 +
4011 +static struct usb_gadget_driver                fsg_driver = {
4012 +       .max_speed      = USB_SPEED_SUPER,
4013 +       .function       = (char *) fsg_string_product,
4014 +       .unbind         = fsg_unbind,
4015 +       .disconnect     = fsg_disconnect,
4016 +       .setup          = fsg_setup,
4017 +       .suspend        = fsg_suspend,
4018 +       .resume         = fsg_resume,
4019 +
4020 +       .driver         = {
4021 +               .name           = DRIVER_NAME,
4022 +               .owner          = THIS_MODULE,
4023 +               // .release = ...
4024 +               // .suspend = ...
4025 +               // .resume = ...
4026 +       },
4027 +};
4028 +
4029 +
4030 +static int __init fsg_alloc(void)
4031 +{
4032 +       struct fsg_dev          *fsg;
4033 +
4034 +       fsg = kzalloc(sizeof *fsg +
4035 +                     fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
4036 +
4037 +       if (!fsg)
4038 +               return -ENOMEM;
4039 +       spin_lock_init(&fsg->lock);
4040 +       init_rwsem(&fsg->filesem);
4041 +       kref_init(&fsg->ref);
4042 +       init_completion(&fsg->thread_notifier);
4043 +
4044 +       the_fsg = fsg;
4045 +       return 0;
4046 +}
4047 +
4048 +
4049 +static int __init fsg_init(void)
4050 +{
4051 +       int             rc;
4052 +       struct fsg_dev  *fsg;
4053 +
4054 +       rc = fsg_num_buffers_validate();
4055 +       if (rc != 0)
4056 +               return rc;
4057 +
4058 +       if ((rc = fsg_alloc()) != 0)
4059 +               return rc;
4060 +       fsg = the_fsg;
4061 +       if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
4062 +               kref_put(&fsg->ref, fsg_release);
4063 +       return rc;
4064 +}
4065 +module_init(fsg_init);
4066 +
4067 +
4068 +static void __exit fsg_cleanup(void)
4069 +{
4070 +       struct fsg_dev  *fsg = the_fsg;
4071 +
4072 +       /* Unregister the driver iff the thread hasn't already done so */
4073 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
4074 +               usb_gadget_unregister_driver(&fsg_driver);
4075 +
4076 +       /* Wait for the thread to finish up */
4077 +       wait_for_completion(&fsg->thread_notifier);
4078 +
4079 +       kref_put(&fsg->ref, fsg_release);
4080 +}
4081 +module_exit(fsg_cleanup);
4082 --- a/drivers/usb/host/Kconfig
4083 +++ b/drivers/usb/host/Kconfig
4084 @@ -751,6 +751,19 @@ config USB_HWA_HCD
4085           To compile this driver a module, choose M here: the module
4086           will be called "hwa-hc".
4087  
4088 +config USB_DWCOTG
4089 +       tristate "Synopsis DWC host support"
4090 +       depends on USB
4091 +       help
4092 +         The Synopsis DWC controller is a dual-role
4093 +         host/peripheral/OTG ("On The Go") USB controllers.
4094 +
4095 +         Enable this option to support this IP in host controller mode.
4096 +         If unsure, say N.
4097 +
4098 +         To compile this driver as a module, choose M here: the
4099 +         modules built will be called dwc_otg and dwc_common_port.
4100 +
4101  config USB_IMX21_HCD
4102         tristate "i.MX21 HCD support"
4103         depends on ARM && ARCH_MXC
4104 --- a/drivers/usb/host/Makefile
4105 +++ b/drivers/usb/host/Makefile
4106 @@ -71,6 +71,8 @@ obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
4107  obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
4108  obj-$(CONFIG_USB_ISP1760_HCD)  += isp1760.o
4109  obj-$(CONFIG_USB_HWA_HCD)      += hwa-hc.o
4110 +
4111 +obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/
4112  obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
4113  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
4114  obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
4115 --- /dev/null
4116 +++ b/drivers/usb/host/dwc_common_port/Makefile
4117 @@ -0,0 +1,58 @@
4118 +#
4119 +# Makefile for DWC_common library
4120 +#
4121 +
4122 +ifneq ($(KERNELRELEASE),)
4123 +
4124 +ccflags-y      += -DDWC_LINUX
4125 +#ccflags-y     += -DDEBUG
4126 +#ccflags-y     += -DDWC_DEBUG_REGS
4127 +#ccflags-y     += -DDWC_DEBUG_MEMORY
4128 +
4129 +ccflags-y      += -DDWC_LIBMODULE
4130 +ccflags-y      += -DDWC_CCLIB
4131 +#ccflags-y     += -DDWC_CRYPTOLIB
4132 +ccflags-y      += -DDWC_NOTIFYLIB
4133 +ccflags-y      += -DDWC_UTFLIB
4134 +
4135 +obj-$(CONFIG_USB_DWCOTG)       += dwc_common_port_lib.o
4136 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4137 +                           dwc_crypto.o dwc_notifier.o \
4138 +                           dwc_common_linux.o dwc_mem.o
4139 +
4140 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
4141 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
4142 +
4143 +ifneq ($(kernrel3),2.6.20)
4144 +# grayg - I only know that we use ccflags-y in 2.6.31 actually
4145 +ccflags-y += $(CPPFLAGS)
4146 +endif
4147 +
4148 +else
4149 +
4150 +#ifeq ($(KDIR),)
4151 +#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4152 +#endif
4153 +
4154 +ifeq ($(ARCH),)
4155 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4156 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4157 +endif
4158 +
4159 +ifeq ($(DOXYGEN),)
4160 +DOXYGEN                := doxygen
4161 +endif
4162 +
4163 +default:
4164 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4165 +
4166 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4167 +       $(DOXYGEN) doc/doxygen.cfg
4168 +
4169 +tags:  $(wildcard *.[hc])
4170 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4171 +
4172 +endif
4173 +
4174 +clean:
4175 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4176 --- /dev/null
4177 +++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd
4178 @@ -0,0 +1,17 @@
4179 +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
4180 +CFLAGS += -DDWC_FREEBSD
4181 +CFLAGS += -DDEBUG
4182 +#CFLAGS        += -DDWC_DEBUG_REGS
4183 +#CFLAGS        += -DDWC_DEBUG_MEMORY
4184 +
4185 +#CFLAGS        += -DDWC_LIBMODULE
4186 +#CFLAGS        += -DDWC_CCLIB
4187 +#CFLAGS        += -DDWC_CRYPTOLIB
4188 +#CFLAGS        += -DDWC_NOTIFYLIB
4189 +#CFLAGS        += -DDWC_UTFLIB
4190 +
4191 +KMOD = dwc_common_port_lib
4192 +SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \
4193 +       dwc_common_fbsd.c dwc_mem.c
4194 +
4195 +.include <bsd.kmod.mk>
4196 --- /dev/null
4197 +++ b/drivers/usb/host/dwc_common_port/Makefile.linux
4198 @@ -0,0 +1,49 @@
4199 +#
4200 +# Makefile for DWC_common library
4201 +#
4202 +ifneq ($(KERNELRELEASE),)
4203 +
4204 +ccflags-y      += -DDWC_LINUX
4205 +#ccflags-y     += -DDEBUG
4206 +#ccflags-y     += -DDWC_DEBUG_REGS
4207 +#ccflags-y     += -DDWC_DEBUG_MEMORY
4208 +
4209 +ccflags-y      += -DDWC_LIBMODULE
4210 +ccflags-y      += -DDWC_CCLIB
4211 +ccflags-y      += -DDWC_CRYPTOLIB
4212 +ccflags-y      += -DDWC_NOTIFYLIB
4213 +ccflags-y      += -DDWC_UTFLIB
4214 +
4215 +obj-m                   := dwc_common_port_lib.o
4216 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4217 +                           dwc_crypto.o dwc_notifier.o \
4218 +                           dwc_common_linux.o dwc_mem.o
4219 +
4220 +else
4221 +
4222 +ifeq ($(KDIR),)
4223 +$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4224 +endif
4225 +
4226 +ifeq ($(ARCH),)
4227 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4228 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4229 +endif
4230 +
4231 +ifeq ($(DOXYGEN),)
4232 +DOXYGEN                := doxygen
4233 +endif
4234 +
4235 +default:
4236 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4237 +
4238 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4239 +       $(DOXYGEN) doc/doxygen.cfg
4240 +
4241 +tags:  $(wildcard *.[hc])
4242 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4243 +
4244 +endif
4245 +
4246 +clean:
4247 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4248 --- /dev/null
4249 +++ b/drivers/usb/host/dwc_common_port/changes.txt
4250 @@ -0,0 +1,174 @@
4251 +
4252 +dwc_read_reg32() and friends now take an additional parameter, a pointer to an
4253 +IO context struct. The IO context struct should live in an os-dependent struct
4254 +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct
4255 +named 'os_dep' embedded in the main device struct. So there these calls look
4256 +like this:
4257 +
4258 +       dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);
4259 +
4260 +       dwc_write_reg32(&usb3_dev->os_dep.ioctx,
4261 +                       &pcd->dev_global_regs->dcfg, 0);
4262 +
4263 +Note that for the existing Linux driver ports, it is not necessary to actually
4264 +define the 'ioctx' member in the os-dependent struct. Since Linux does not
4265 +require an IO context, its macros for dwc_read_reg32() and friends do not
4266 +use the context pointer, so it is optimized away by the compiler. But it is
4267 +necessary to add the pointer parameter to all of the call sites, to be ready
4268 +for any future ports (such as FreeBSD) which do require an IO context.
4269 +
4270 +
4271 +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now
4272 +take an additional parameter, a pointer to a memory context. Examples:
4273 +
4274 +       addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);
4275 +
4276 +       dwc_free(&usb3_dev->os_dep.memctx, addr);
4277 +
4278 +Again, for the Linux ports, it is not necessary to actually define the memctx
4279 +member, but it is necessary to add the pointer parameter to all of the call
4280 +sites.
4281 +
4282 +
4283 +Same for dwc_dma_alloc() and dwc_dma_free(). Examples:
4284 +
4285 +       virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);
4286 +
4287 +       dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);
4288 +
4289 +
4290 +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:
4291 +
4292 +       mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);
4293 +
4294 +       dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);
4295 +
4296 +
4297 +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:
4298 +
4299 +       lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);
4300 +
4301 +       dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);
4302 +
4303 +
4304 +Same for dwc_timer_alloc(). Example:
4305 +
4306 +       timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",
4307 +                               cb_func, cb_data);
4308 +
4309 +
4310 +Same for dwc_waitq_alloc(). Example:
4311 +
4312 +       waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);
4313 +
4314 +
4315 +Same for dwc_thread_run(). Example:
4316 +
4317 +       thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,
4318 +                               "dwc_usb3_thd1", data);
4319 +
4320 +
4321 +Same for dwc_workq_alloc(). Example:
4322 +
4323 +       workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");
4324 +
4325 +
4326 +Same for dwc_task_alloc(). Example:
4327 +
4328 +       task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",
4329 +                             cb_func, cb_data);
4330 +
4331 +
4332 +In addition to the context pointer additions, a few core functions have had
4333 +other changes made to their parameters:
4334 +
4335 +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()
4336 +has been changed from a uint64_t to a dwc_irqflags_t.
4337 +
4338 +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the
4339 +FreeBSD equivalent of that function requires it.
4340 +
4341 +And, in addition to the context pointer, dwc_task_alloc() also adds a
4342 +'char *name' parameter, to be consistent with dwc_thread_run() and
4343 +dwc_workq_alloc(), and because the FreeBSD equivalent of that function
4344 +requires a unique name.
4345 +
4346 +
4347 +Here is a complete list of the core functions that now take a pointer to a
4348 +context as their first parameter:
4349 +
4350 +       dwc_read_reg32
4351 +       dwc_read_reg64
4352 +       dwc_write_reg32
4353 +       dwc_write_reg64
4354 +       dwc_modify_reg32
4355 +       dwc_modify_reg64
4356 +       dwc_alloc
4357 +       dwc_alloc_atomic
4358 +       dwc_strdup
4359 +       dwc_free
4360 +       dwc_dma_alloc
4361 +       dwc_dma_free
4362 +       dwc_mutex_alloc
4363 +       dwc_mutex_free
4364 +       dwc_spinlock_alloc
4365 +       dwc_spinlock_free
4366 +       dwc_timer_alloc
4367 +       dwc_waitq_alloc
4368 +       dwc_thread_run
4369 +       dwc_workq_alloc
4370 +       dwc_task_alloc     Also adds a 'char *name' as its 2nd parameter
4371 +
4372 +And here are the core functions that have other changes to their parameters:
4373 +
4374 +       dwc_spinlock_irqsave      'flags' param is now a 'dwc_irqflags_t *'
4375 +       dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'
4376 +       dwc_thread_should_stop    Adds a 'dwc_thread_t *' parameter
4377 +
4378 +
4379 +
4380 +The changes to the core functions also require some of the other library
4381 +functions to change:
4382 +
4383 +       dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'
4384 +       (for memory allocation) as the 1st param and a 'void *mtxctx'
4385 +       (for mutex allocation) as the 2nd param.
4386 +
4387 +       dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),
4388 +       dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a
4389 +       'void *memctx' as the 1st param.
4390 +
4391 +       dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a
4392 +       'void *memctx' as the 1st param.
4393 +
4394 +       dwc_modpow() now takes a 'void *memctx' as the 1st param.
4395 +
4396 +       dwc_alloc_notification_manager() now takes a 'void *memctx' as the
4397 +       1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd
4398 +       param, and also now returns an integer value that is non-zero if
4399 +       allocation of its data structures or work queue fails.
4400 +
4401 +       dwc_register_notifier() now takes a 'void *memctx' as the 1st param.
4402 +
4403 +       dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first
4404 +       param, and also now returns an integer value that is non-zero if
4405 +       allocation of its data structures fails.
4406 +
4407 +
4408 +
4409 +Other miscellaneous changes:
4410 +
4411 +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to
4412 +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.
4413 +
4414 +The following #define's have been added to allow selectively compiling library
4415 +features:
4416 +
4417 +       DWC_CCLIB
4418 +       DWC_CRYPTOLIB
4419 +       DWC_NOTIFYLIB
4420 +       DWC_UTFLIB
4421 +
4422 +A DWC_LIBMODULE #define has also been added. If this is not defined, then the
4423 +module code in dwc_common_linux.c is not compiled in. This allows linking the
4424 +library code directly into a driver module, instead of as a standalone module.
4425 --- /dev/null
4426 +++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4427 @@ -0,0 +1,270 @@
4428 +# Doxyfile 1.4.5
4429 +
4430 +#---------------------------------------------------------------------------
4431 +# Project related configuration options
4432 +#---------------------------------------------------------------------------
4433 +PROJECT_NAME           = "Synopsys DWC Portability and Common Library for UWB"
4434 +PROJECT_NUMBER         =
4435 +OUTPUT_DIRECTORY       = doc
4436 +CREATE_SUBDIRS         = NO
4437 +OUTPUT_LANGUAGE        = English
4438 +BRIEF_MEMBER_DESC      = YES
4439 +REPEAT_BRIEF           = YES
4440 +ABBREVIATE_BRIEF       = "The $name class" \
4441 +                         "The $name widget" \
4442 +                         "The $name file" \
4443 +                         is \
4444 +                         provides \
4445 +                         specifies \
4446 +                         contains \
4447 +                         represents \
4448 +                         a \
4449 +                         an \
4450 +                         the
4451 +ALWAYS_DETAILED_SEC    = YES
4452 +INLINE_INHERITED_MEMB  = NO
4453 +FULL_PATH_NAMES        = NO
4454 +STRIP_FROM_PATH        = ..
4455 +STRIP_FROM_INC_PATH    =
4456 +SHORT_NAMES            = NO
4457 +JAVADOC_AUTOBRIEF      = YES
4458 +MULTILINE_CPP_IS_BRIEF = NO
4459 +DETAILS_AT_TOP         = YES
4460 +INHERIT_DOCS           = YES
4461 +SEPARATE_MEMBER_PAGES  = NO
4462 +TAB_SIZE               = 8
4463 +ALIASES                =
4464 +OPTIMIZE_OUTPUT_FOR_C  = YES
4465 +OPTIMIZE_OUTPUT_JAVA   = NO
4466 +BUILTIN_STL_SUPPORT    = NO
4467 +DISTRIBUTE_GROUP_DOC   = NO
4468 +SUBGROUPING            = NO
4469 +#---------------------------------------------------------------------------
4470 +# Build related configuration options
4471 +#---------------------------------------------------------------------------
4472 +EXTRACT_ALL            = NO
4473 +EXTRACT_PRIVATE        = NO
4474 +EXTRACT_STATIC         = YES
4475 +EXTRACT_LOCAL_CLASSES  = NO
4476 +EXTRACT_LOCAL_METHODS  = NO
4477 +HIDE_UNDOC_MEMBERS     = NO
4478 +HIDE_UNDOC_CLASSES     = NO
4479 +HIDE_FRIEND_COMPOUNDS  = NO
4480 +HIDE_IN_BODY_DOCS      = NO
4481 +INTERNAL_DOCS          = NO
4482 +CASE_SENSE_NAMES       = YES
4483 +HIDE_SCOPE_NAMES       = NO
4484 +SHOW_INCLUDE_FILES     = NO
4485 +INLINE_INFO            = YES
4486 +SORT_MEMBER_DOCS       = NO
4487 +SORT_BRIEF_DOCS        = NO
4488 +SORT_BY_SCOPE_NAME     = NO
4489 +GENERATE_TODOLIST      = YES
4490 +GENERATE_TESTLIST      = YES
4491 +GENERATE_BUGLIST       = YES
4492 +GENERATE_DEPRECATEDLIST= YES
4493 +ENABLED_SECTIONS       =
4494 +MAX_INITIALIZER_LINES  = 30
4495 +SHOW_USED_FILES        = YES
4496 +SHOW_DIRECTORIES       = YES
4497 +FILE_VERSION_FILTER    =
4498 +#---------------------------------------------------------------------------
4499 +# configuration options related to warning and progress messages
4500 +#---------------------------------------------------------------------------
4501 +QUIET                  = YES
4502 +WARNINGS               = YES
4503 +WARN_IF_UNDOCUMENTED   = NO
4504 +WARN_IF_DOC_ERROR      = YES
4505 +WARN_NO_PARAMDOC       = YES
4506 +WARN_FORMAT            = "$file:$line: $text"
4507 +WARN_LOGFILE           =
4508 +#---------------------------------------------------------------------------
4509 +# configuration options related to the input files
4510 +#---------------------------------------------------------------------------
4511 +INPUT                  = .
4512 +FILE_PATTERNS          = *.c \
4513 +                         *.cc \
4514 +                         *.cxx \
4515 +                         *.cpp \
4516 +                         *.c++ \
4517 +                         *.d \
4518 +                         *.java \
4519 +                         *.ii \
4520 +                         *.ixx \
4521 +                         *.ipp \
4522 +                         *.i++ \
4523 +                         *.inl \
4524 +                         *.h \
4525 +                         *.hh \
4526 +                         *.hxx \
4527 +                         *.hpp \
4528 +                         *.h++ \
4529 +                         *.idl \
4530 +                         *.odl \
4531 +                         *.cs \
4532 +                         *.php \
4533 +                         *.php3 \
4534 +                         *.inc \
4535 +                         *.m \
4536 +                         *.mm \
4537 +                         *.dox \
4538 +                         *.py \
4539 +                         *.C \
4540 +                         *.CC \
4541 +                         *.C++ \
4542 +                         *.II \
4543 +                         *.I++ \
4544 +                         *.H \
4545 +                         *.HH \
4546 +                         *.H++ \
4547 +                         *.CS \
4548 +                         *.PHP \
4549 +                         *.PHP3 \
4550 +                         *.M \
4551 +                         *.MM \
4552 +                         *.PY
4553 +RECURSIVE              = NO
4554 +EXCLUDE                =
4555 +EXCLUDE_SYMLINKS       = NO
4556 +EXCLUDE_PATTERNS       =
4557 +EXAMPLE_PATH           =
4558 +EXAMPLE_PATTERNS       = *
4559 +EXAMPLE_RECURSIVE      = NO
4560 +IMAGE_PATH             =
4561 +INPUT_FILTER           =
4562 +FILTER_PATTERNS        =
4563 +FILTER_SOURCE_FILES    = NO
4564 +#---------------------------------------------------------------------------
4565 +# configuration options related to source browsing
4566 +#---------------------------------------------------------------------------
4567 +SOURCE_BROWSER         = NO
4568 +INLINE_SOURCES         = NO
4569 +STRIP_CODE_COMMENTS    = YES
4570 +REFERENCED_BY_RELATION = YES
4571 +REFERENCES_RELATION    = YES
4572 +USE_HTAGS              = NO
4573 +VERBATIM_HEADERS       = NO
4574 +#---------------------------------------------------------------------------
4575 +# configuration options related to the alphabetical class index
4576 +#---------------------------------------------------------------------------
4577 +ALPHABETICAL_INDEX     = NO
4578 +COLS_IN_ALPHA_INDEX    = 5
4579 +IGNORE_PREFIX          =
4580 +#---------------------------------------------------------------------------
4581 +# configuration options related to the HTML output
4582 +#---------------------------------------------------------------------------
4583 +GENERATE_HTML          = YES
4584 +HTML_OUTPUT            = html
4585 +HTML_FILE_EXTENSION    = .html
4586 +HTML_HEADER            =
4587 +HTML_FOOTER            =
4588 +HTML_STYLESHEET        =
4589 +HTML_ALIGN_MEMBERS     = YES
4590 +GENERATE_HTMLHELP      = NO
4591 +CHM_FILE               =
4592 +HHC_LOCATION           =
4593 +GENERATE_CHI           = NO
4594 +BINARY_TOC             = NO
4595 +TOC_EXPAND             = NO
4596 +DISABLE_INDEX          = NO
4597 +ENUM_VALUES_PER_LINE   = 4
4598 +GENERATE_TREEVIEW      = YES
4599 +TREEVIEW_WIDTH         = 250
4600 +#---------------------------------------------------------------------------
4601 +# configuration options related to the LaTeX output
4602 +#---------------------------------------------------------------------------
4603 +GENERATE_LATEX         = NO
4604 +LATEX_OUTPUT           = latex
4605 +LATEX_CMD_NAME         = latex
4606 +MAKEINDEX_CMD_NAME     = makeindex
4607 +COMPACT_LATEX          = NO
4608 +PAPER_TYPE             = a4wide
4609 +EXTRA_PACKAGES         =
4610 +LATEX_HEADER           =
4611 +PDF_HYPERLINKS         = NO
4612 +USE_PDFLATEX           = NO
4613 +LATEX_BATCHMODE        = NO
4614 +LATEX_HIDE_INDICES     = NO
4615 +#---------------------------------------------------------------------------
4616 +# configuration options related to the RTF output
4617 +#---------------------------------------------------------------------------
4618 +GENERATE_RTF           = NO
4619 +RTF_OUTPUT             = rtf
4620 +COMPACT_RTF            = NO
4621 +RTF_HYPERLINKS         = NO
4622 +RTF_STYLESHEET_FILE    =
4623 +RTF_EXTENSIONS_FILE    =
4624 +#---------------------------------------------------------------------------
4625 +# configuration options related to the man page output
4626 +#---------------------------------------------------------------------------
4627 +GENERATE_MAN           = NO
4628 +MAN_OUTPUT             = man
4629 +MAN_EXTENSION          = .3
4630 +MAN_LINKS              = NO
4631 +#---------------------------------------------------------------------------
4632 +# configuration options related to the XML output
4633 +#---------------------------------------------------------------------------
4634 +GENERATE_XML           = NO
4635 +XML_OUTPUT             = xml
4636 +XML_SCHEMA             =
4637 +XML_DTD                =
4638 +XML_PROGRAMLISTING     = YES
4639 +#---------------------------------------------------------------------------
4640 +# configuration options for the AutoGen Definitions output
4641 +#---------------------------------------------------------------------------
4642 +GENERATE_AUTOGEN_DEF   = NO
4643 +#---------------------------------------------------------------------------
4644 +# configuration options related to the Perl module output
4645 +#---------------------------------------------------------------------------
4646 +GENERATE_PERLMOD       = NO
4647 +PERLMOD_LATEX          = NO
4648 +PERLMOD_PRETTY         = YES
4649 +PERLMOD_MAKEVAR_PREFIX =
4650 +#---------------------------------------------------------------------------
4651 +# Configuration options related to the preprocessor
4652 +#---------------------------------------------------------------------------
4653 +ENABLE_PREPROCESSING   = YES
4654 +MACRO_EXPANSION        = NO
4655 +EXPAND_ONLY_PREDEF     = NO
4656 +SEARCH_INCLUDES        = YES
4657 +INCLUDE_PATH           =
4658 +INCLUDE_FILE_PATTERNS  =
4659 +PREDEFINED             = DEBUG DEBUG_MEMORY
4660 +EXPAND_AS_DEFINED      =
4661 +SKIP_FUNCTION_MACROS   = YES
4662 +#---------------------------------------------------------------------------
4663 +# Configuration::additions related to external references
4664 +#---------------------------------------------------------------------------
4665 +TAGFILES               =
4666 +GENERATE_TAGFILE       =
4667 +ALLEXTERNALS           = NO
4668 +EXTERNAL_GROUPS        = YES
4669 +PERL_PATH              = /usr/bin/perl
4670 +#---------------------------------------------------------------------------
4671 +# Configuration options related to the dot tool
4672 +#---------------------------------------------------------------------------
4673 +CLASS_DIAGRAMS         = YES
4674 +HIDE_UNDOC_RELATIONS   = YES
4675 +HAVE_DOT               = NO
4676 +CLASS_GRAPH            = YES
4677 +COLLABORATION_GRAPH    = YES
4678 +GROUP_GRAPHS           = YES
4679 +UML_LOOK               = NO
4680 +TEMPLATE_RELATIONS     = NO
4681 +INCLUDE_GRAPH          = NO
4682 +INCLUDED_BY_GRAPH      = YES
4683 +CALL_GRAPH             = NO
4684 +GRAPHICAL_HIERARCHY    = YES
4685 +DIRECTORY_GRAPH        = YES
4686 +DOT_IMAGE_FORMAT       = png
4687 +DOT_PATH               =
4688 +DOTFILE_DIRS           =
4689 +MAX_DOT_GRAPH_DEPTH    = 1000
4690 +DOT_TRANSPARENT        = NO
4691 +DOT_MULTI_TARGETS      = NO
4692 +GENERATE_LEGEND        = YES
4693 +DOT_CLEANUP            = YES
4694 +#---------------------------------------------------------------------------
4695 +# Configuration::additions related to the search engine
4696 +#---------------------------------------------------------------------------
4697 +SEARCHENGINE           = NO
4698 --- /dev/null
4699 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
4700 @@ -0,0 +1,532 @@
4701 +/* =========================================================================
4702 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
4703 + * $Revision: #4 $
4704 + * $Date: 2010/11/04 $
4705 + * $Change: 1621692 $
4706 + *
4707 + * Synopsys Portability Library Software and documentation
4708 + * (hereinafter, "Software") is an Unsupported proprietary work of
4709 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
4710 + * between Synopsys and you.
4711 + *
4712 + * The Software IS NOT an item of Licensed Software or Licensed Product
4713 + * under any End User Software License Agreement or Agreement for
4714 + * Licensed Product with Synopsys or any supplement thereto. You are
4715 + * permitted to use and redistribute this Software in source and binary
4716 + * forms, with or without modification, provided that redistributions
4717 + * of source code must retain this notice. You may not view, use,
4718 + * disclose, copy or distribute this file or any information contained
4719 + * herein except pursuant to this license grant from Synopsys. If you
4720 + * do not agree with this notice, including the disclaimer below, then
4721 + * you are not authorized to use the Software.
4722 + *
4723 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4724 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4725 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
4726 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
4727 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4728 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4729 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4730 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
4731 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4732 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4733 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4734 + * DAMAGE.
4735 + * ========================================================================= */
4736 +#ifdef DWC_CCLIB
4737 +
4738 +#include "dwc_cc.h"
4739 +
4740 +typedef struct dwc_cc
4741 +{
4742 +       uint32_t uid;
4743 +       uint8_t chid[16];
4744 +       uint8_t cdid[16];
4745 +       uint8_t ck[16];
4746 +       uint8_t *name;
4747 +       uint8_t length;
4748 +        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
4749 +} dwc_cc_t;
4750 +
4751 +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
4752 +
4753 +/** The main structure for CC management.  */
4754 +struct dwc_cc_if
4755 +{
4756 +       dwc_mutex_t *mutex;
4757 +       char *filename;
4758 +
4759 +       unsigned is_host:1;
4760 +
4761 +       dwc_notifier_t *notifier;
4762 +
4763 +       struct context_list list;
4764 +};
4765 +
4766 +#ifdef DEBUG
4767 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
4768 +{
4769 +       int i;
4770 +       DWC_PRINTF("%s: ", name);
4771 +       for (i=0; i<len; i++) {
4772 +               DWC_PRINTF("%02x ", bytes[i]);
4773 +       }
4774 +       DWC_PRINTF("\n");
4775 +}
4776 +#else
4777 +#define dump_bytes(x...)
4778 +#endif
4779 +
4780 +static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
4781 +{
4782 +       dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
4783 +       if (!cc) {
4784 +               return NULL;
4785 +       }
4786 +       DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
4787 +
4788 +       if (name) {
4789 +               cc->length = length;
4790 +               cc->name = dwc_alloc(mem_ctx, length);
4791 +               if (!cc->name) {
4792 +                       dwc_free(mem_ctx, cc);
4793 +                       return NULL;
4794 +               }
4795 +
4796 +               DWC_MEMCPY(cc->name, name, length);
4797 +       }
4798 +
4799 +       return cc;
4800 +}
4801 +
4802 +static void free_cc(void *mem_ctx, dwc_cc_t *cc)
4803 +{
4804 +       if (cc->name) {
4805 +               dwc_free(mem_ctx, cc->name);
4806 +       }
4807 +       dwc_free(mem_ctx, cc);
4808 +}
4809 +
4810 +static uint32_t next_uid(dwc_cc_if_t *cc_if)
4811 +{
4812 +       uint32_t uid = 0;
4813 +       dwc_cc_t *cc;
4814 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4815 +               if (cc->uid > uid) {
4816 +                       uid = cc->uid;
4817 +               }
4818 +       }
4819 +
4820 +       if (uid == 0) {
4821 +               uid = 255;
4822 +       }
4823 +
4824 +       return uid + 1;
4825 +}
4826 +
4827 +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
4828 +{
4829 +       dwc_cc_t *cc;
4830 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4831 +               if (cc->uid == uid) {
4832 +                       return cc;
4833 +               }
4834 +       }
4835 +       return NULL;
4836 +}
4837 +
4838 +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
4839 +{
4840 +       unsigned int size = 0;
4841 +       dwc_cc_t *cc;
4842 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4843 +               size += (48 + 1);
4844 +               if (cc->name) {
4845 +                       size += cc->length;
4846 +               }
4847 +       }
4848 +       return size;
4849 +}
4850 +
4851 +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
4852 +{
4853 +       uint32_t uid = 0;
4854 +       dwc_cc_t *cc;
4855 +
4856 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4857 +               if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
4858 +                       uid = cc->uid;
4859 +                       break;
4860 +               }
4861 +       }
4862 +       return uid;
4863 +}
4864 +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
4865 +{
4866 +       uint32_t uid = 0;
4867 +       dwc_cc_t *cc;
4868 +
4869 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4870 +               if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
4871 +                       uid = cc->uid;
4872 +                       break;
4873 +               }
4874 +       }
4875 +       return uid;
4876 +}
4877 +
4878 +/* Internal cc_add */
4879 +static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4880 +                     uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4881 +{
4882 +       dwc_cc_t *cc;
4883 +       uint32_t uid;
4884 +
4885 +       if (cc_if->is_host) {
4886 +               uid = cc_match_cdid(cc_if, cdid);
4887 +       }
4888 +       else {
4889 +               uid = cc_match_chid(cc_if, chid);
4890 +       }
4891 +
4892 +       if (uid) {
4893 +               DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
4894 +               cc = cc_find(cc_if, uid);
4895 +       }
4896 +       else {
4897 +               cc = alloc_cc(mem_ctx, name, length);
4898 +               cc->uid = next_uid(cc_if);
4899 +               DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
4900 +       }
4901 +
4902 +       DWC_MEMCPY(&(cc->chid[0]), chid, 16);
4903 +       DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
4904 +       DWC_MEMCPY(&(cc->ck[0]), ck, 16);
4905 +
4906 +       DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
4907 +       dump_bytes("CHID", cc->chid, 16);
4908 +       dump_bytes("CDID", cc->cdid, 16);
4909 +       dump_bytes("CK", cc->ck, 16);
4910 +       return cc->uid;
4911 +}
4912 +
4913 +/* Internal cc_clear */
4914 +static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
4915 +{
4916 +       while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
4917 +               dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
4918 +               DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
4919 +               free_cc(mem_ctx, cc);
4920 +       }
4921 +}
4922 +
4923 +dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
4924 +                            dwc_notifier_t *notifier, unsigned is_host)
4925 +{
4926 +       dwc_cc_if_t *cc_if = NULL;
4927 +
4928 +       /* Allocate a common_cc_if structure */
4929 +       cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
4930 +
4931 +       if (!cc_if)
4932 +               return NULL;
4933 +
4934 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4935 +       DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
4936 +#else
4937 +       cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
4938 +#endif
4939 +       if (!cc_if->mutex) {
4940 +               dwc_free(mem_ctx, cc_if);
4941 +               return NULL;
4942 +       }
4943 +
4944 +       DWC_CIRCLEQ_INIT(&cc_if->list);
4945 +       cc_if->is_host = is_host;
4946 +       cc_if->notifier = notifier;
4947 +       return cc_if;
4948 +}
4949 +
4950 +void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
4951 +{
4952 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4953 +       DWC_MUTEX_FREE(cc_if->mutex);
4954 +#else
4955 +       dwc_mutex_free(mtx_ctx, cc_if->mutex);
4956 +#endif
4957 +       cc_clear(mem_ctx, cc_if);
4958 +       dwc_free(mem_ctx, cc_if);
4959 +}
4960 +
4961 +static void cc_changed(dwc_cc_if_t *cc_if)
4962 +{
4963 +       if (cc_if->notifier) {
4964 +               dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
4965 +       }
4966 +}
4967 +
4968 +void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
4969 +{
4970 +       DWC_MUTEX_LOCK(cc_if->mutex);
4971 +       cc_clear(mem_ctx, cc_if);
4972 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
4973 +       cc_changed(cc_if);
4974 +}
4975 +
4976 +int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4977 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4978 +{
4979 +       uint32_t uid;
4980 +
4981 +       DWC_MUTEX_LOCK(cc_if->mutex);
4982 +       uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
4983 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
4984 +       cc_changed(cc_if);
4985 +
4986 +       return uid;
4987 +}
4988 +
4989 +void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
4990 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4991 +{
4992 +       dwc_cc_t* cc;
4993 +
4994 +       DWC_DEBUGC("Change connection context %d", id);
4995 +
4996 +       DWC_MUTEX_LOCK(cc_if->mutex);
4997 +       cc = cc_find(cc_if, id);
4998 +       if (!cc) {
4999 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5000 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5001 +               return;
5002 +       }
5003 +
5004 +       if (chid) {
5005 +               DWC_MEMCPY(&(cc->chid[0]), chid, 16);
5006 +       }
5007 +       if (cdid) {
5008 +               DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
5009 +       }
5010 +       if (ck) {
5011 +               DWC_MEMCPY(&(cc->ck[0]), ck, 16);
5012 +       }
5013 +
5014 +       if (name) {
5015 +               if (cc->name) {
5016 +                       dwc_free(mem_ctx, cc->name);
5017 +               }
5018 +               cc->name = dwc_alloc(mem_ctx, length);
5019 +               if (!cc->name) {
5020 +                       DWC_ERROR("Out of memory in dwc_cc_change()\n");
5021 +                       DWC_MUTEX_UNLOCK(cc_if->mutex);
5022 +                       return;
5023 +               }
5024 +               cc->length = length;
5025 +               DWC_MEMCPY(cc->name, name, length);
5026 +       }
5027 +
5028 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5029 +
5030 +       cc_changed(cc_if);
5031 +
5032 +       DWC_DEBUGC("Changed connection context id=%d\n", id);
5033 +       dump_bytes("New CHID", cc->chid, 16);
5034 +       dump_bytes("New CDID", cc->cdid, 16);
5035 +       dump_bytes("New CK", cc->ck, 16);
5036 +}
5037 +
5038 +void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
5039 +{
5040 +       dwc_cc_t *cc;
5041 +
5042 +       DWC_DEBUGC("Removing connection context %d", id);
5043 +
5044 +       DWC_MUTEX_LOCK(cc_if->mutex);
5045 +       cc = cc_find(cc_if, id);
5046 +       if (!cc) {
5047 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5048 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5049 +               return;
5050 +       }
5051 +
5052 +       DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
5053 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5054 +       free_cc(mem_ctx, cc);
5055 +
5056 +       cc_changed(cc_if);
5057 +}
5058 +
5059 +uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
5060 +{
5061 +       uint8_t *buf, *x;
5062 +       uint8_t zero = 0;
5063 +       dwc_cc_t *cc;
5064 +
5065 +       DWC_MUTEX_LOCK(cc_if->mutex);
5066 +       *length = cc_data_size(cc_if);
5067 +       if (!(*length)) {
5068 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5069 +               return NULL;
5070 +       }
5071 +
5072 +       DWC_DEBUGC("Creating data for saving (length=%d)", *length);
5073 +
5074 +       buf = dwc_alloc(mem_ctx, *length);
5075 +       if (!buf) {
5076 +               *length = 0;
5077 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5078 +               return NULL;
5079 +       }
5080 +
5081 +       x = buf;
5082 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
5083 +               DWC_MEMCPY(x, cc->chid, 16);
5084 +               x += 16;
5085 +               DWC_MEMCPY(x, cc->cdid, 16);
5086 +               x += 16;
5087 +               DWC_MEMCPY(x, cc->ck, 16);
5088 +               x += 16;
5089 +               if (cc->name) {
5090 +                       DWC_MEMCPY(x, &cc->length, 1);
5091 +                       x += 1;
5092 +                       DWC_MEMCPY(x, cc->name, cc->length);
5093 +                       x += cc->length;
5094 +               }
5095 +               else {
5096 +                       DWC_MEMCPY(x, &zero, 1);
5097 +                       x += 1;
5098 +               }
5099 +       }
5100 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5101 +
5102 +       return buf;
5103 +}
5104 +
5105 +void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
5106 +{
5107 +       uint8_t name_length;
5108 +       uint8_t *name;
5109 +       uint8_t *chid;
5110 +       uint8_t *cdid;
5111 +       uint8_t *ck;
5112 +       uint32_t i = 0;
5113 +
5114 +       DWC_MUTEX_LOCK(cc_if->mutex);
5115 +       cc_clear(mem_ctx, cc_if);
5116 +
5117 +       while (i < length) {
5118 +               chid = &data[i];
5119 +               i += 16;
5120 +               cdid = &data[i];
5121 +               i += 16;
5122 +               ck = &data[i];
5123 +               i += 16;
5124 +
5125 +               name_length = data[i];
5126 +               i ++;
5127 +
5128 +               if (name_length) {
5129 +                       name = &data[i];
5130 +                       i += name_length;
5131 +               }
5132 +               else {
5133 +                       name = NULL;
5134 +               }
5135 +
5136 +               /* check to see if we haven't overflown the buffer */
5137 +               if (i > length) {
5138 +                       DWC_ERROR("Data format error while attempting to load CCs "
5139 +                                 "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
5140 +                       break;
5141 +               }
5142 +
5143 +               cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
5144 +       }
5145 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5146 +
5147 +       cc_changed(cc_if);
5148 +}
5149 +
5150 +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
5151 +{
5152 +       uint32_t uid = 0;
5153 +
5154 +       DWC_MUTEX_LOCK(cc_if->mutex);
5155 +       uid = cc_match_chid(cc_if, chid);
5156 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5157 +       return uid;
5158 +}
5159 +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
5160 +{
5161 +       uint32_t uid = 0;
5162 +
5163 +       DWC_MUTEX_LOCK(cc_if->mutex);
5164 +       uid = cc_match_cdid(cc_if, cdid);
5165 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5166 +       return uid;
5167 +}
5168 +
5169 +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
5170 +{
5171 +       uint8_t *ck = NULL;
5172 +       dwc_cc_t *cc;
5173 +
5174 +       DWC_MUTEX_LOCK(cc_if->mutex);
5175 +       cc = cc_find(cc_if, id);
5176 +       if (cc) {
5177 +               ck = cc->ck;
5178 +       }
5179 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5180 +
5181 +       return ck;
5182 +
5183 +}
5184 +
5185 +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
5186 +{
5187 +       uint8_t *retval = NULL;
5188 +       dwc_cc_t *cc;
5189 +
5190 +       DWC_MUTEX_LOCK(cc_if->mutex);
5191 +       cc = cc_find(cc_if, id);
5192 +       if (cc) {
5193 +               retval = cc->chid;
5194 +       }
5195 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5196 +
5197 +       return retval;
5198 +}
5199 +
5200 +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
5201 +{
5202 +       uint8_t *retval = NULL;
5203 +       dwc_cc_t *cc;
5204 +
5205 +       DWC_MUTEX_LOCK(cc_if->mutex);
5206 +       cc = cc_find(cc_if, id);
5207 +       if (cc) {
5208 +               retval = cc->cdid;
5209 +       }
5210 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5211 +
5212 +       return retval;
5213 +}
5214 +
5215 +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
5216 +{
5217 +       uint8_t *retval = NULL;
5218 +       dwc_cc_t *cc;
5219 +
5220 +       DWC_MUTEX_LOCK(cc_if->mutex);
5221 +       *length = 0;
5222 +       cc = cc_find(cc_if, id);
5223 +       if (cc) {
5224 +               *length = cc->length;
5225 +               retval = cc->name;
5226 +       }
5227 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5228 +
5229 +       return retval;
5230 +}
5231 +
5232 +#endif /* DWC_CCLIB */
5233 --- /dev/null
5234 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
5235 @@ -0,0 +1,224 @@
5236 +/* =========================================================================
5237 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
5238 + * $Revision: #4 $
5239 + * $Date: 2010/09/28 $
5240 + * $Change: 1596182 $
5241 + *
5242 + * Synopsys Portability Library Software and documentation
5243 + * (hereinafter, "Software") is an Unsupported proprietary work of
5244 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
5245 + * between Synopsys and you.
5246 + *
5247 + * The Software IS NOT an item of Licensed Software or Licensed Product
5248 + * under any End User Software License Agreement or Agreement for
5249 + * Licensed Product with Synopsys or any supplement thereto. You are
5250 + * permitted to use and redistribute this Software in source and binary
5251 + * forms, with or without modification, provided that redistributions
5252 + * of source code must retain this notice. You may not view, use,
5253 + * disclose, copy or distribute this file or any information contained
5254 + * herein except pursuant to this license grant from Synopsys. If you
5255 + * do not agree with this notice, including the disclaimer below, then
5256 + * you are not authorized to use the Software.
5257 + *
5258 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
5259 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5260 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
5261 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
5262 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5263 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5264 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5265 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
5266 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5267 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5268 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
5269 + * DAMAGE.
5270 + * ========================================================================= */
5271 +#ifndef _DWC_CC_H_
5272 +#define _DWC_CC_H_
5273 +
5274 +#ifdef __cplusplus
5275 +extern "C" {
5276 +#endif
5277 +
5278 +/** @file
5279 + *
5280 + * This file defines the Context Context library.
5281 + *
5282 + * The main data structure is dwc_cc_if_t which is returned by either the
5283 + * dwc_cc_if_alloc function or returned by the module to the user via a provided
5284 + * function. The data structure is opaque and should only be manipulated via the
5285 + * functions provied in this API.
5286 + *
5287 + * It manages a list of connection contexts and operations can be performed to
5288 + * add, remove, query, search, and change, those contexts.  Additionally,
5289 + * a dwc_notifier_t object can be requested from the manager so that
5290 + * the user can be notified whenever the context list has changed.
5291 + */
5292 +
5293 +#include "dwc_os.h"
5294 +#include "dwc_list.h"
5295 +#include "dwc_notifier.h"
5296 +
5297 +
5298 +/* Notifications */
5299 +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
5300 +
5301 +struct dwc_cc_if;
5302 +typedef struct dwc_cc_if dwc_cc_if_t;
5303 +
5304 +
5305 +/** @name Connection Context Operations */
5306 +/** @{ */
5307 +
5308 +/** This function allocates memory for a dwc_cc_if_t structure, initializes
5309 + * fields to default values, and returns a pointer to the structure or NULL on
5310 + * error. */
5311 +extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
5312 +                                   dwc_notifier_t *notifier, unsigned is_host);
5313 +
5314 +/** Frees the memory for the specified CC structure allocated from
5315 + * dwc_cc_if_alloc(). */
5316 +extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);
5317 +
5318 +/** Removes all contexts from the connection context list */
5319 +extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);
5320 +
5321 +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
5322 + * If a CHID already exists, the CK and name are overwritten.  Statistics are
5323 + * not overwritten.
5324 + *
5325 + * @param cc_if The cc_if structure.
5326 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.
5327 + * @param ck A pointer to the 16-byte CK.  This value will be copied.
5328 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.
5329 + * @param name An optional host friendly name as defined in the association model
5330 + * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.
5331 + * @param length The length othe unicode string.
5332 + * @return A unique identifier used to refer to this context that is valid for
5333 + * as long as this context is still in the list. */
5334 +extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5335 +                         uint8_t *cdid, uint8_t *ck, uint8_t *name,
5336 +                         uint8_t length);
5337 +
5338 +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
5339 + * list, preserving any accumulated statistics.  This would typically be called
5340 + * if the host decideds to change the context with a SET_CONNECTION request.
5341 + *
5342 + * @param cc_if The cc_if structure.
5343 + * @param id The identifier of the connection context.
5344 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL
5345 + * indicates no change.
5346 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL
5347 + * indicates no change.
5348 + * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL
5349 + * indicates no change.
5350 + * @param name Host friendly name UTF16-LE.  NULL indicates no change.
5351 + * @param length Length of name. */
5352 +extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,
5353 +                         uint8_t *chid, uint8_t *cdid, uint8_t *ck,
5354 +                         uint8_t *name, uint8_t length);
5355 +
5356 +/** Remove the specified connection context.
5357 + * @param cc_if The cc_if structure.
5358 + * @param id The identifier of the connection context to remove. */
5359 +extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);
5360 +
5361 +/** Get a binary block of data for the connection context list and attributes.
5362 + * This data can be used by the OS specific driver to save the connection
5363 + * context list into non-volatile memory.
5364 + *
5365 + * @param cc_if The cc_if structure.
5366 + * @param length Return the length of the data buffer.
5367 + * @return A pointer to the data buffer.  The memory for this buffer should be
5368 + * freed with DWC_FREE() after use. */
5369 +extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,
5370 +                                    unsigned int *length);
5371 +
5372 +/** Restore the connection context list from the binary data that was previously
5373 + * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific
5374 + * driver to load a connection context list from non-volatile memory.
5375 + *
5376 + * @param cc_if The cc_if structure.
5377 + * @param data The data bytes as returned from dwc_cc_data_for_save.
5378 + * @param length The length of the data. */
5379 +extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,
5380 +                                    uint8_t *data, unsigned int length);
5381 +
5382 +/** Find the connection context from the specified CHID.
5383 + *
5384 + * @param cc_if The cc_if structure.
5385 + * @param chid A pointer to the CHID data.
5386 + * @return A non-zero identifier of the connection context if the CHID matches.
5387 + * Otherwise returns 0. */
5388 +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
5389 +
5390 +/** Find the connection context from the specified CDID.
5391 + *
5392 + * @param cc_if The cc_if structure.
5393 + * @param cdid A pointer to the CDID data.
5394 + * @return A non-zero identifier of the connection context if the CHID matches.
5395 + * Otherwise returns 0. */
5396 +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
5397 +
5398 +/** Retrieve the CK from the specified connection context.
5399 + *
5400 + * @param cc_if The cc_if structure.
5401 + * @param id The identifier of the connection context.
5402 + * @return A pointer to the CK data.  The memory does not need to be freed. */
5403 +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
5404 +
5405 +/** Retrieve the CHID from the specified connection context.
5406 + *
5407 + * @param cc_if The cc_if structure.
5408 + * @param id The identifier of the connection context.
5409 + * @return A pointer to the CHID data.  The memory does not need to be freed. */
5410 +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
5411 +
5412 +/** Retrieve the CDID from the specified connection context.
5413 + *
5414 + * @param cc_if The cc_if structure.
5415 + * @param id The identifier of the connection context.
5416 + * @return A pointer to the CDID data.  The memory does not need to be freed. */
5417 +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
5418 +
5419 +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
5420 +
5421 +/** Checks a buffer for non-zero.
5422 + * @param id A pointer to a 16 byte buffer.
5423 + * @return true if the 16 byte value is non-zero. */
5424 +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
5425 +       int i;
5426 +       for (i=0; i<16; i++) {
5427 +               if (id[i]) return 1;
5428 +       }
5429 +       return 0;
5430 +}
5431 +
5432 +/** Checks a buffer for zero.
5433 + * @param id A pointer to a 16 byte buffer.
5434 + * @return true if the 16 byte value is zero. */
5435 +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
5436 +       return !dwc_assoc_is_not_zero_id(id);
5437 +}
5438 +
5439 +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
5440 + * buffer. */
5441 +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
5442 +       char *ptr = buffer;
5443 +       int i;
5444 +       for (i=0; i<16; i++) {
5445 +               ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
5446 +               if (i < 15) {
5447 +                       ptr += DWC_SPRINTF(ptr, " ");
5448 +               }
5449 +       }
5450 +       return ptr - buffer;
5451 +}
5452 +
5453 +/** @} */
5454 +
5455 +#ifdef __cplusplus
5456 +}
5457 +#endif
5458 +
5459 +#endif /* _DWC_CC_H_ */
5460 --- /dev/null
5461 +++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5462 @@ -0,0 +1,1308 @@
5463 +#include "dwc_os.h"
5464 +#include "dwc_list.h"
5465 +
5466 +#ifdef DWC_CCLIB
5467 +# include "dwc_cc.h"
5468 +#endif
5469 +
5470 +#ifdef DWC_CRYPTOLIB
5471 +# include "dwc_modpow.h"
5472 +# include "dwc_dh.h"
5473 +# include "dwc_crypto.h"
5474 +#endif
5475 +
5476 +#ifdef DWC_NOTIFYLIB
5477 +# include "dwc_notifier.h"
5478 +#endif
5479 +
5480 +/* OS-Level Implementations */
5481 +
5482 +/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */
5483 +
5484 +
5485 +/* MISC */
5486 +
5487 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
5488 +{
5489 +       return memset(dest, byte, size);
5490 +}
5491 +
5492 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
5493 +{
5494 +       return memcpy(dest, src, size);
5495 +}
5496 +
5497 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
5498 +{
5499 +       bcopy(src, dest, size);
5500 +       return dest;
5501 +}
5502 +
5503 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
5504 +{
5505 +       return memcmp(m1, m2, size);
5506 +}
5507 +
5508 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
5509 +{
5510 +       return strncmp(s1, s2, size);
5511 +}
5512 +
5513 +int DWC_STRCMP(void *s1, void *s2)
5514 +{
5515 +       return strcmp(s1, s2);
5516 +}
5517 +
5518 +int DWC_STRLEN(char const *str)
5519 +{
5520 +       return strlen(str);
5521 +}
5522 +
5523 +char *DWC_STRCPY(char *to, char const *from)
5524 +{
5525 +       return strcpy(to, from);
5526 +}
5527 +
5528 +char *DWC_STRDUP(char const *str)
5529 +{
5530 +       int len = DWC_STRLEN(str) + 1;
5531 +       char *new = DWC_ALLOC_ATOMIC(len);
5532 +
5533 +       if (!new) {
5534 +               return NULL;
5535 +       }
5536 +
5537 +       DWC_MEMCPY(new, str, len);
5538 +       return new;
5539 +}
5540 +
5541 +int DWC_ATOI(char *str, int32_t *value)
5542 +{
5543 +       char *end = NULL;
5544 +
5545 +       *value = strtol(str, &end, 0);
5546 +       if (*end == '\0') {
5547 +               return 0;
5548 +       }
5549 +
5550 +       return -1;
5551 +}
5552 +
5553 +int DWC_ATOUI(char *str, uint32_t *value)
5554 +{
5555 +       char *end = NULL;
5556 +
5557 +       *value = strtoul(str, &end, 0);
5558 +       if (*end == '\0') {
5559 +               return 0;
5560 +       }
5561 +
5562 +       return -1;
5563 +}
5564 +
5565 +
5566 +#ifdef DWC_UTFLIB
5567 +/* From usbstring.c */
5568 +
5569 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
5570 +{
5571 +       int     count = 0;
5572 +       u8      c;
5573 +       u16     uchar;
5574 +
5575 +       /* this insists on correct encodings, though not minimal ones.
5576 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
5577 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
5578 +        */
5579 +       while (len != 0 && (c = (u8) *s++) != 0) {
5580 +               if (unlikely(c & 0x80)) {
5581 +                       // 2-byte sequence:
5582 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
5583 +                       if ((c & 0xe0) == 0xc0) {
5584 +                               uchar = (c & 0x1f) << 6;
5585 +
5586 +                               c = (u8) *s++;
5587 +                               if ((c & 0xc0) != 0xc0)
5588 +                                       goto fail;
5589 +                               c &= 0x3f;
5590 +                               uchar |= c;
5591 +
5592 +                       // 3-byte sequence (most CJKV characters):
5593 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
5594 +                       } else if ((c & 0xf0) == 0xe0) {
5595 +                               uchar = (c & 0x0f) << 12;
5596 +
5597 +                               c = (u8) *s++;
5598 +                               if ((c & 0xc0) != 0xc0)
5599 +                                       goto fail;
5600 +                               c &= 0x3f;
5601 +                               uchar |= c << 6;
5602 +
5603 +                               c = (u8) *s++;
5604 +                               if ((c & 0xc0) != 0xc0)
5605 +                                       goto fail;
5606 +                               c &= 0x3f;
5607 +                               uchar |= c;
5608 +
5609 +                               /* no bogus surrogates */
5610 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
5611 +                                       goto fail;
5612 +
5613 +                       // 4-byte sequence (surrogate pairs, currently rare):
5614 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
5615 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
5616 +                       // (uuuuu = wwww + 1)
5617 +                       // FIXME accept the surrogate code points (only)
5618 +                       } else
5619 +                               goto fail;
5620 +               } else
5621 +                       uchar = c;
5622 +               put_unaligned (cpu_to_le16 (uchar), cp++);
5623 +               count++;
5624 +               len--;
5625 +       }
5626 +       return count;
5627 +fail:
5628 +       return -1;
5629 +}
5630 +
5631 +#endif /* DWC_UTFLIB */
5632 +
5633 +
5634 +/* dwc_debug.h */
5635 +
5636 +dwc_bool_t DWC_IN_IRQ(void)
5637 +{
5638 +//     return in_irq();
5639 +       return 0;
5640 +}
5641 +
5642 +dwc_bool_t DWC_IN_BH(void)
5643 +{
5644 +//     return in_softirq();
5645 +       return 0;
5646 +}
5647 +
5648 +void DWC_VPRINTF(char *format, va_list args)
5649 +{
5650 +       vprintf(format, args);
5651 +}
5652 +
5653 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
5654 +{
5655 +       return vsnprintf(str, size, format, args);
5656 +}
5657 +
5658 +void DWC_PRINTF(char *format, ...)
5659 +{
5660 +       va_list args;
5661 +
5662 +       va_start(args, format);
5663 +       DWC_VPRINTF(format, args);
5664 +       va_end(args);
5665 +}
5666 +
5667 +int DWC_SPRINTF(char *buffer, char *format, ...)
5668 +{
5669 +       int retval;
5670 +       va_list args;
5671 +
5672 +       va_start(args, format);
5673 +       retval = vsprintf(buffer, format, args);
5674 +       va_end(args);
5675 +       return retval;
5676 +}
5677 +
5678 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
5679 +{
5680 +       int retval;
5681 +       va_list args;
5682 +
5683 +       va_start(args, format);
5684 +       retval = vsnprintf(buffer, size, format, args);
5685 +       va_end(args);
5686 +       return retval;
5687 +}
5688 +
5689 +void __DWC_WARN(char *format, ...)
5690 +{
5691 +       va_list args;
5692 +
5693 +       va_start(args, format);
5694 +       DWC_VPRINTF(format, args);
5695 +       va_end(args);
5696 +}
5697 +
5698 +void __DWC_ERROR(char *format, ...)
5699 +{
5700 +       va_list args;
5701 +
5702 +       va_start(args, format);
5703 +       DWC_VPRINTF(format, args);
5704 +       va_end(args);
5705 +}
5706 +
5707 +void DWC_EXCEPTION(char *format, ...)
5708 +{
5709 +       va_list args;
5710 +
5711 +       va_start(args, format);
5712 +       DWC_VPRINTF(format, args);
5713 +       va_end(args);
5714 +//     BUG_ON(1);      ???
5715 +}
5716 +
5717 +#ifdef DEBUG
5718 +void __DWC_DEBUG(char *format, ...)
5719 +{
5720 +       va_list args;
5721 +
5722 +       va_start(args, format);
5723 +       DWC_VPRINTF(format, args);
5724 +       va_end(args);
5725 +}
5726 +#endif
5727 +
5728 +
5729 +/* dwc_mem.h */
5730 +
5731 +#if 0
5732 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
5733 +                               uint32_t align,
5734 +                               uint32_t alloc)
5735 +{
5736 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
5737 +                                               size, align, alloc);
5738 +       return (dwc_pool_t *)pool;
5739 +}
5740 +
5741 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
5742 +{
5743 +       dma_pool_destroy((struct dma_pool *)pool);
5744 +}
5745 +
5746 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5747 +{
5748 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
5749 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
5750 +}
5751 +
5752 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5753 +{
5754 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
5755 +       memset(..);
5756 +}
5757 +
5758 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
5759 +{
5760 +       dma_pool_free(pool, vaddr, daddr);
5761 +}
5762 +#endif
5763 +
5764 +static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5765 +{
5766 +       if (error)
5767 +               return;
5768 +       *(bus_addr_t *)arg = segs[0].ds_addr;
5769 +}
5770 +
5771 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
5772 +{
5773 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5774 +       int error;
5775 +
5776 +       error = bus_dma_tag_create(
5777 +#if __FreeBSD_version >= 700000
5778 +                       bus_get_dma_tag(dma->dev),      /* parent */
5779 +#else
5780 +                       NULL,                           /* parent */
5781 +#endif
5782 +                       4, 0,                           /* alignment, bounds */
5783 +                       BUS_SPACE_MAXADDR_32BIT,        /* lowaddr */
5784 +                       BUS_SPACE_MAXADDR,              /* highaddr */
5785 +                       NULL, NULL,                     /* filter, filterarg */
5786 +                       size,                           /* maxsize */
5787 +                       1,                              /* nsegments */
5788 +                       size,                           /* maxsegsize */
5789 +                       0,                              /* flags */
5790 +                       NULL,                           /* lockfunc */
5791 +                       NULL,                           /* lockarg */
5792 +                       &dma->dma_tag);
5793 +       if (error) {
5794 +               device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",
5795 +                             __func__, error);
5796 +               goto fail_0;
5797 +       }
5798 +
5799 +       error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,
5800 +                                BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
5801 +       if (error) {
5802 +               device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
5803 +                             __func__, (uintmax_t)size, error);
5804 +               goto fail_1;
5805 +       }
5806 +
5807 +       dma->dma_paddr = 0;
5808 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,
5809 +                               dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);
5810 +       if (error || dma->dma_paddr == 0) {
5811 +               device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",
5812 +                             __func__, error);
5813 +               goto fail_2;
5814 +       }
5815 +
5816 +       *dma_addr = dma->dma_paddr;
5817 +       return dma->dma_vaddr;
5818 +
5819 +fail_2:
5820 +       bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5821 +fail_1:
5822 +       bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5823 +       bus_dma_tag_destroy(dma->dma_tag);
5824 +fail_0:
5825 +       dma->dma_map = NULL;
5826 +       dma->dma_tag = NULL;
5827 +
5828 +       return NULL;
5829 +}
5830 +
5831 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
5832 +{
5833 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5834 +
5835 +       if (dma->dma_tag == NULL)
5836 +               return;
5837 +       if (dma->dma_map != NULL) {
5838 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map,
5839 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
5840 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5841 +               bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5842 +               dma->dma_map = NULL;
5843 +       }
5844 +
5845 +       bus_dma_tag_destroy(dma->dma_tag);
5846 +       dma->dma_tag = NULL;
5847 +}
5848 +
5849 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
5850 +{
5851 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
5852 +}
5853 +
5854 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
5855 +{
5856 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
5857 +}
5858 +
5859 +void __DWC_FREE(void *mem_ctx, void *addr)
5860 +{
5861 +       free(addr, M_DEVBUF);
5862 +}
5863 +
5864 +
5865 +#ifdef DWC_CRYPTOLIB
5866 +/* dwc_crypto.h */
5867 +
5868 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
5869 +{
5870 +       get_random_bytes(buffer, length);
5871 +}
5872 +
5873 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
5874 +{
5875 +       struct crypto_blkcipher *tfm;
5876 +       struct blkcipher_desc desc;
5877 +       struct scatterlist sgd;
5878 +       struct scatterlist sgs;
5879 +
5880 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
5881 +       if (tfm == NULL) {
5882 +               printk("failed to load transform for aes CBC\n");
5883 +               return -1;
5884 +       }
5885 +
5886 +       crypto_blkcipher_setkey(tfm, key, keylen);
5887 +       crypto_blkcipher_set_iv(tfm, iv, 16);
5888 +
5889 +       sg_init_one(&sgd, out, messagelen);
5890 +       sg_init_one(&sgs, message, messagelen);
5891 +
5892 +       desc.tfm = tfm;
5893 +       desc.flags = 0;
5894 +
5895 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
5896 +               crypto_free_blkcipher(tfm);
5897 +               DWC_ERROR("AES CBC encryption failed");
5898 +               return -1;
5899 +       }
5900 +
5901 +       crypto_free_blkcipher(tfm);
5902 +       return 0;
5903 +}
5904 +
5905 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
5906 +{
5907 +       struct crypto_hash *tfm;
5908 +       struct hash_desc desc;
5909 +       struct scatterlist sg;
5910 +
5911 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
5912 +       if (IS_ERR(tfm)) {
5913 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
5914 +               return 0;
5915 +       }
5916 +       desc.tfm = tfm;
5917 +       desc.flags = 0;
5918 +
5919 +       sg_init_one(&sg, message, len);
5920 +       crypto_hash_digest(&desc, &sg, len, out);
5921 +       crypto_free_hash(tfm);
5922 +
5923 +       return 1;
5924 +}
5925 +
5926 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
5927 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
5928 +{
5929 +       struct crypto_hash *tfm;
5930 +       struct hash_desc desc;
5931 +       struct scatterlist sg;
5932 +
5933 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
5934 +       if (IS_ERR(tfm)) {
5935 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
5936 +               return 0;
5937 +       }
5938 +       desc.tfm = tfm;
5939 +       desc.flags = 0;
5940 +
5941 +       sg_init_one(&sg, message, messagelen);
5942 +       crypto_hash_setkey(tfm, key, keylen);
5943 +       crypto_hash_digest(&desc, &sg, messagelen, out);
5944 +       crypto_free_hash(tfm);
5945 +
5946 +       return 1;
5947 +}
5948 +
5949 +#endif /* DWC_CRYPTOLIB */
5950 +
5951 +
5952 +/* Byte Ordering Conversions */
5953 +
5954 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
5955 +{
5956 +#ifdef __LITTLE_ENDIAN
5957 +       return *p;
5958 +#else
5959 +       uint8_t *u_p = (uint8_t *)p;
5960 +
5961 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5962 +#endif
5963 +}
5964 +
5965 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
5966 +{
5967 +#ifdef __BIG_ENDIAN
5968 +       return *p;
5969 +#else
5970 +       uint8_t *u_p = (uint8_t *)p;
5971 +
5972 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5973 +#endif
5974 +}
5975 +
5976 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
5977 +{
5978 +#ifdef __LITTLE_ENDIAN
5979 +       return *p;
5980 +#else
5981 +       uint8_t *u_p = (uint8_t *)p;
5982 +
5983 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5984 +#endif
5985 +}
5986 +
5987 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
5988 +{
5989 +#ifdef __BIG_ENDIAN
5990 +       return *p;
5991 +#else
5992 +       uint8_t *u_p = (uint8_t *)p;
5993 +
5994 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
5995 +#endif
5996 +}
5997 +
5998 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
5999 +{
6000 +#ifdef __LITTLE_ENDIAN
6001 +       return *p;
6002 +#else
6003 +       uint8_t *u_p = (uint8_t *)p;
6004 +       return (u_p[1] | (u_p[0] << 8));
6005 +#endif
6006 +}
6007 +
6008 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
6009 +{
6010 +#ifdef __BIG_ENDIAN
6011 +       return *p;
6012 +#else
6013 +       uint8_t *u_p = (uint8_t *)p;
6014 +       return (u_p[1] | (u_p[0] << 8));
6015 +#endif
6016 +}
6017 +
6018 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
6019 +{
6020 +#ifdef __LITTLE_ENDIAN
6021 +       return *p;
6022 +#else
6023 +       uint8_t *u_p = (uint8_t *)p;
6024 +       return (u_p[1] | (u_p[0] << 8));
6025 +#endif
6026 +}
6027 +
6028 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
6029 +{
6030 +#ifdef __BIG_ENDIAN
6031 +       return *p;
6032 +#else
6033 +       uint8_t *u_p = (uint8_t *)p;
6034 +       return (u_p[1] | (u_p[0] << 8));
6035 +#endif
6036 +}
6037 +
6038 +
6039 +/* Registers */
6040 +
6041 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
6042 +{
6043 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6044 +       bus_size_t ior = (bus_size_t)reg;
6045 +
6046 +       return bus_space_read_4(io->iot, io->ioh, ior);
6047 +}
6048 +
6049 +#if 0
6050 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
6051 +{
6052 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6053 +       bus_size_t ior = (bus_size_t)reg;
6054 +
6055 +       return bus_space_read_8(io->iot, io->ioh, ior);
6056 +}
6057 +#endif
6058 +
6059 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
6060 +{
6061 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6062 +       bus_size_t ior = (bus_size_t)reg;
6063 +
6064 +       bus_space_write_4(io->iot, io->ioh, ior, value);
6065 +}
6066 +
6067 +#if 0
6068 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
6069 +{
6070 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6071 +       bus_size_t ior = (bus_size_t)reg;
6072 +
6073 +       bus_space_write_8(io->iot, io->ioh, ior, value);
6074 +}
6075 +#endif
6076 +
6077 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
6078 +                     uint32_t set_mask)
6079 +{
6080 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6081 +       bus_size_t ior = (bus_size_t)reg;
6082 +
6083 +       bus_space_write_4(io->iot, io->ioh, ior,
6084 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
6085 +                          ~clear_mask) | set_mask);
6086 +}
6087 +
6088 +#if 0
6089 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
6090 +                     uint64_t set_mask)
6091 +{
6092 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6093 +       bus_size_t ior = (bus_size_t)reg;
6094 +
6095 +       bus_space_write_8(io->iot, io->ioh, ior,
6096 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
6097 +                          ~clear_mask) | set_mask);
6098 +}
6099 +#endif
6100 +
6101 +
6102 +/* Locking */
6103 +
6104 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
6105 +{
6106 +       struct mtx *sl = DWC_ALLOC(sizeof(*sl));
6107 +
6108 +       if (!sl) {
6109 +               DWC_ERROR("Cannot allocate memory for spinlock");
6110 +               return NULL;
6111 +       }
6112 +
6113 +       mtx_init(sl, "dw3spn", NULL, MTX_SPIN);
6114 +       return (dwc_spinlock_t *)sl;
6115 +}
6116 +
6117 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
6118 +{
6119 +       struct mtx *sl = (struct mtx *)lock;
6120 +
6121 +       mtx_destroy(sl);
6122 +       DWC_FREE(sl);
6123 +}
6124 +
6125 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
6126 +{
6127 +       mtx_lock_spin((struct mtx *)lock);      // ???
6128 +}
6129 +
6130 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
6131 +{
6132 +       mtx_unlock_spin((struct mtx *)lock);    // ???
6133 +}
6134 +
6135 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
6136 +{
6137 +       mtx_lock_spin((struct mtx *)lock);
6138 +}
6139 +
6140 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
6141 +{
6142 +       mtx_unlock_spin((struct mtx *)lock);
6143 +}
6144 +
6145 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
6146 +{
6147 +       struct mtx *m;
6148 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));
6149 +
6150 +       if (!mutex) {
6151 +               DWC_ERROR("Cannot allocate memory for mutex");
6152 +               return NULL;
6153 +       }
6154 +
6155 +       m = (struct mtx *)mutex;
6156 +       mtx_init(m, "dw3mtx", NULL, MTX_DEF);
6157 +       return mutex;
6158 +}
6159 +
6160 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
6161 +#else
6162 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
6163 +{
6164 +       mtx_destroy((struct mtx *)mutex);
6165 +       DWC_FREE(mutex);
6166 +}
6167 +#endif
6168 +
6169 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
6170 +{
6171 +       struct mtx *m = (struct mtx *)mutex;
6172 +
6173 +       mtx_lock(m);
6174 +}
6175 +
6176 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
6177 +{
6178 +       struct mtx *m = (struct mtx *)mutex;
6179 +
6180 +       return mtx_trylock(m);
6181 +}
6182 +
6183 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
6184 +{
6185 +       struct mtx *m = (struct mtx *)mutex;
6186 +
6187 +       mtx_unlock(m);
6188 +}
6189 +
6190 +
6191 +/* Timing */
6192 +
6193 +void DWC_UDELAY(uint32_t usecs)
6194 +{
6195 +       DELAY(usecs);
6196 +}
6197 +
6198 +void DWC_MDELAY(uint32_t msecs)
6199 +{
6200 +       do {
6201 +               DELAY(1000);
6202 +       } while (--msecs);
6203 +}
6204 +
6205 +void DWC_MSLEEP(uint32_t msecs)
6206 +{
6207 +       struct timeval tv;
6208 +
6209 +       tv.tv_sec = msecs / 1000;
6210 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6211 +       pause("dw3slp", tvtohz(&tv));
6212 +}
6213 +
6214 +uint32_t DWC_TIME(void)
6215 +{
6216 +       struct timeval tv;
6217 +
6218 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
6219 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
6220 +}
6221 +
6222 +
6223 +/* Timers */
6224 +
6225 +struct dwc_timer {
6226 +       struct callout t;
6227 +       char *name;
6228 +       dwc_spinlock_t *lock;
6229 +       dwc_timer_callback_t cb;
6230 +       void *data;
6231 +};
6232 +
6233 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
6234 +{
6235 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
6236 +
6237 +       if (!t) {
6238 +               DWC_ERROR("Cannot allocate memory for timer");
6239 +               return NULL;
6240 +       }
6241 +
6242 +       callout_init(&t->t, 1);
6243 +
6244 +       t->name = DWC_STRDUP(name);
6245 +       if (!t->name) {
6246 +               DWC_ERROR("Cannot allocate memory for timer->name");
6247 +               goto no_name;
6248 +       }
6249 +
6250 +       t->lock = DWC_SPINLOCK_ALLOC();
6251 +       if (!t->lock) {
6252 +               DWC_ERROR("Cannot allocate memory for lock");
6253 +               goto no_lock;
6254 +       }
6255 +
6256 +       t->cb = cb;
6257 +       t->data = data;
6258 +
6259 +       return t;
6260 +
6261 + no_lock:
6262 +       DWC_FREE(t->name);
6263 + no_name:
6264 +       DWC_FREE(t);
6265 +
6266 +       return NULL;
6267 +}
6268 +
6269 +void DWC_TIMER_FREE(dwc_timer_t *timer)
6270 +{
6271 +       callout_stop(&timer->t);
6272 +       DWC_SPINLOCK_FREE(timer->lock);
6273 +       DWC_FREE(timer->name);
6274 +       DWC_FREE(timer);
6275 +}
6276 +
6277 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
6278 +{
6279 +       struct timeval tv;
6280 +
6281 +       tv.tv_sec = time / 1000;
6282 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6283 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
6284 +}
6285 +
6286 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
6287 +{
6288 +       callout_stop(&timer->t);
6289 +}
6290 +
6291 +
6292 +/* Wait Queues */
6293 +
6294 +struct dwc_waitq {
6295 +       struct mtx lock;
6296 +       int abort;
6297 +};
6298 +
6299 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
6300 +{
6301 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
6302 +
6303 +       if (!wq) {
6304 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6305 +               return NULL;
6306 +       }
6307 +
6308 +       mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);
6309 +       wq->abort = 0;
6310 +
6311 +       return wq;
6312 +}
6313 +
6314 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
6315 +{
6316 +       mtx_destroy(&wq->lock);
6317 +       DWC_FREE(wq);
6318 +}
6319 +
6320 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
6321 +{
6322 +//     intrmask_t ipl;
6323 +       int result = 0;
6324 +
6325 +       mtx_lock(&wq->lock);
6326 +//     ipl = splbio();
6327 +
6328 +       /* Skip the sleep if already aborted or triggered */
6329 +       if (!wq->abort && !cond(data)) {
6330 +//             splx(ipl);
6331 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout
6332 +//             ipl = splbio();
6333 +       }
6334 +
6335 +       if (result == ERESTART) {       // signaled - restart
6336 +               result = -DWC_E_RESTART;
6337 +
6338 +       } else if (result == EINTR) {   // signaled - interrupt
6339 +               result = -DWC_E_ABORT;
6340 +
6341 +       } else if (wq->abort) {
6342 +               result = -DWC_E_ABORT;
6343 +
6344 +       } else {
6345 +               result = 0;
6346 +       }
6347 +
6348 +       wq->abort = 0;
6349 +//     splx(ipl);
6350 +       mtx_unlock(&wq->lock);
6351 +       return result;
6352 +}
6353 +
6354 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
6355 +                              void *data, int32_t msecs)
6356 +{
6357 +       struct timeval tv, tv1, tv2;
6358 +//     intrmask_t ipl;
6359 +       int result = 0;
6360 +
6361 +       tv.tv_sec = msecs / 1000;
6362 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6363 +
6364 +       mtx_lock(&wq->lock);
6365 +//     ipl = splbio();
6366 +
6367 +       /* Skip the sleep if already aborted or triggered */
6368 +       if (!wq->abort && !cond(data)) {
6369 +//             splx(ipl);
6370 +               getmicrouptime(&tv1);
6371 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));
6372 +               getmicrouptime(&tv2);
6373 +//             ipl = splbio();
6374 +       }
6375 +
6376 +       if (result == 0) {                      // awoken
6377 +               if (wq->abort) {
6378 +                       result = -DWC_E_ABORT;
6379 +               } else {
6380 +                       tv2.tv_usec -= tv1.tv_usec;
6381 +                       if (tv2.tv_usec < 0) {
6382 +                               tv2.tv_usec += 1000000;
6383 +                               tv2.tv_sec--;
6384 +                       }
6385 +
6386 +                       tv2.tv_sec -= tv1.tv_sec;
6387 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
6388 +                       result = msecs - result;
6389 +                       if (result <= 0)
6390 +                               result = 1;
6391 +               }
6392 +       } else if (result == ERESTART) {        // signaled - restart
6393 +               result = -DWC_E_RESTART;
6394 +
6395 +       } else if (result == EINTR) {           // signaled - interrupt
6396 +               result = -DWC_E_ABORT;
6397 +
6398 +       } else {                                // timed out
6399 +               result = -DWC_E_TIMEOUT;
6400 +       }
6401 +
6402 +       wq->abort = 0;
6403 +//     splx(ipl);
6404 +       mtx_unlock(&wq->lock);
6405 +       return result;
6406 +}
6407 +
6408 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
6409 +{
6410 +       wakeup(wq);
6411 +}
6412 +
6413 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
6414 +{
6415 +//     intrmask_t ipl;
6416 +
6417 +       mtx_lock(&wq->lock);
6418 +//     ipl = splbio();
6419 +       wq->abort = 1;
6420 +       wakeup(wq);
6421 +//     splx(ipl);
6422 +       mtx_unlock(&wq->lock);
6423 +}
6424 +
6425 +
6426 +/* Threading */
6427 +
6428 +struct dwc_thread {
6429 +       struct proc *proc;
6430 +       int abort;
6431 +};
6432 +
6433 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
6434 +{
6435 +       int retval;
6436 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
6437 +
6438 +       if (!thread) {
6439 +               return NULL;
6440 +       }
6441 +
6442 +       thread->abort = 0;
6443 +       retval = kthread_create((void (*)(void *))func, data, &thread->proc,
6444 +                               RFPROC | RFNOWAIT, 0, "%s", name);
6445 +       if (retval) {
6446 +               DWC_FREE(thread);
6447 +               return NULL;
6448 +       }
6449 +
6450 +       return thread;
6451 +}
6452 +
6453 +int DWC_THREAD_STOP(dwc_thread_t *thread)
6454 +{
6455 +       int retval;
6456 +
6457 +       thread->abort = 1;
6458 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
6459 +
6460 +       if (retval == 0) {
6461 +               /* DWC_THREAD_EXIT() will free the thread struct */
6462 +               return 0;
6463 +       }
6464 +
6465 +       /* NOTE: We leak the thread struct if thread doesn't die */
6466 +
6467 +       if (retval == EWOULDBLOCK) {
6468 +               return -DWC_E_TIMEOUT;
6469 +       }
6470 +
6471 +       return -DWC_E_UNKNOWN;
6472 +}
6473 +
6474 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
6475 +{
6476 +       return thread->abort;
6477 +}
6478 +
6479 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
6480 +{
6481 +       wakeup(&thread->abort);
6482 +       DWC_FREE(thread);
6483 +       kthread_exit(0);
6484 +}
6485 +
6486 +
6487 +/* tasklets
6488 + - Runs in interrupt context (cannot sleep)
6489 + - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]
6490 + - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]
6491 + */
6492 +struct dwc_tasklet {
6493 +       struct task t;
6494 +       dwc_tasklet_callback_t cb;
6495 +       void *data;
6496 +};
6497 +
6498 +static void tasklet_callback(void *data, int pending)  // what to do with pending ???
6499 +{
6500 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
6501 +
6502 +       task->cb(task->data);
6503 +}
6504 +
6505 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
6506 +{
6507 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
6508 +
6509 +       if (task) {
6510 +               task->cb = cb;
6511 +               task->data = data;
6512 +               TASK_INIT(&task->t, 0, tasklet_callback, task);
6513 +       } else {
6514 +               DWC_ERROR("Cannot allocate memory for tasklet");
6515 +       }
6516 +
6517 +       return task;
6518 +}
6519 +
6520 +void DWC_TASK_FREE(dwc_tasklet_t *task)
6521 +{
6522 +       taskqueue_drain(taskqueue_fast, &task->t);      // ???
6523 +       DWC_FREE(task);
6524 +}
6525 +
6526 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
6527 +{
6528 +       /* Uses predefined system queue */
6529 +       taskqueue_enqueue_fast(taskqueue_fast, &task->t);
6530 +}
6531 +
6532 +
6533 +/* workqueues
6534 + - Runs in process context (can sleep)
6535 + */
6536 +typedef struct work_container {
6537 +       dwc_work_callback_t cb;
6538 +       void *data;
6539 +       dwc_workq_t *wq;
6540 +       char *name;
6541 +       int hz;
6542 +
6543 +#ifdef DEBUG
6544 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
6545 +#endif
6546 +       struct task task;
6547 +} work_container_t;
6548 +
6549 +#ifdef DEBUG
6550 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
6551 +#endif
6552 +
6553 +struct dwc_workq {
6554 +       struct taskqueue *taskq;
6555 +       dwc_spinlock_t *lock;
6556 +       dwc_waitq_t *waitq;
6557 +       int pending;
6558 +
6559 +#ifdef DEBUG
6560 +       struct work_container_queue entries;
6561 +#endif
6562 +};
6563 +
6564 +static void do_work(void *data, int pending)   // what to do with pending ???
6565 +{
6566 +       work_container_t *container = (work_container_t *)data;
6567 +       dwc_workq_t *wq = container->wq;
6568 +       dwc_irqflags_t flags;
6569 +
6570 +       if (container->hz) {
6571 +               pause("dw3wrk", container->hz);
6572 +       }
6573 +
6574 +       container->cb(container->data);
6575 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
6576 +
6577 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6578 +
6579 +#ifdef DEBUG
6580 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
6581 +#endif
6582 +       if (container->name)
6583 +               DWC_FREE(container->name);
6584 +       DWC_FREE(container);
6585 +       wq->pending--;
6586 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6587 +       DWC_WAITQ_TRIGGER(wq->waitq);
6588 +}
6589 +
6590 +static int work_done(void *data)
6591 +{
6592 +       dwc_workq_t *workq = (dwc_workq_t *)data;
6593 +
6594 +       return workq->pending == 0;
6595 +}
6596 +
6597 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
6598 +{
6599 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
6600 +}
6601 +
6602 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
6603 +{
6604 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
6605 +
6606 +       if (!wq) {
6607 +               DWC_ERROR("Cannot allocate memory for workqueue");
6608 +               return NULL;
6609 +       }
6610 +
6611 +       wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);
6612 +       if (!wq->taskq) {
6613 +               DWC_ERROR("Cannot allocate memory for taskqueue");
6614 +               goto no_taskq;
6615 +       }
6616 +
6617 +       wq->pending = 0;
6618 +
6619 +       wq->lock = DWC_SPINLOCK_ALLOC();
6620 +       if (!wq->lock) {
6621 +               DWC_ERROR("Cannot allocate memory for spinlock");
6622 +               goto no_lock;
6623 +       }
6624 +
6625 +       wq->waitq = DWC_WAITQ_ALLOC();
6626 +       if (!wq->waitq) {
6627 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6628 +               goto no_waitq;
6629 +       }
6630 +
6631 +       taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");
6632 +
6633 +#ifdef DEBUG
6634 +       DWC_CIRCLEQ_INIT(&wq->entries);
6635 +#endif
6636 +       return wq;
6637 +
6638 + no_waitq:
6639 +       DWC_SPINLOCK_FREE(wq->lock);
6640 + no_lock:
6641 +       taskqueue_free(wq->taskq);
6642 + no_taskq:
6643 +       DWC_FREE(wq);
6644 +
6645 +       return NULL;
6646 +}
6647 +
6648 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
6649 +{
6650 +#ifdef DEBUG
6651 +       dwc_irqflags_t flags;
6652 +
6653 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6654 +
6655 +       if (wq->pending != 0) {
6656 +               struct work_container *container;
6657 +
6658 +               DWC_ERROR("Destroying work queue with pending work");
6659 +
6660 +               DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {
6661 +                       DWC_ERROR("Work %s still pending", container->name);
6662 +               }
6663 +       }
6664 +
6665 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6666 +#endif
6667 +       DWC_WAITQ_FREE(wq->waitq);
6668 +       DWC_SPINLOCK_FREE(wq->lock);
6669 +       taskqueue_free(wq->taskq);
6670 +       DWC_FREE(wq);
6671 +}
6672 +
6673 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
6674 +                       char *format, ...)
6675 +{
6676 +       dwc_irqflags_t flags;
6677 +       work_container_t *container;
6678 +       static char name[128];
6679 +       va_list args;
6680 +
6681 +       va_start(args, format);
6682 +       DWC_VSNPRINTF(name, 128, format, args);
6683 +       va_end(args);
6684 +
6685 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6686 +       wq->pending++;
6687 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6688 +       DWC_WAITQ_TRIGGER(wq->waitq);
6689 +
6690 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6691 +       if (!container) {
6692 +               DWC_ERROR("Cannot allocate memory for container");
6693 +               return;
6694 +       }
6695 +
6696 +       container->name = DWC_STRDUP(name);
6697 +       if (!container->name) {
6698 +               DWC_ERROR("Cannot allocate memory for container->name");
6699 +               DWC_FREE(container);
6700 +               return;
6701 +       }
6702 +
6703 +       container->cb = cb;
6704 +       container->data = data;
6705 +       container->wq = wq;
6706 +       container->hz = 0;
6707 +
6708 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6709 +
6710 +       TASK_INIT(&container->task, 0, do_work, container);
6711 +
6712 +#ifdef DEBUG
6713 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6714 +#endif
6715 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6716 +}
6717 +
6718 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
6719 +                               void *data, uint32_t time, char *format, ...)
6720 +{
6721 +       dwc_irqflags_t flags;
6722 +       work_container_t *container;
6723 +       static char name[128];
6724 +       struct timeval tv;
6725 +       va_list args;
6726 +
6727 +       va_start(args, format);
6728 +       DWC_VSNPRINTF(name, 128, format, args);
6729 +       va_end(args);
6730 +
6731 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6732 +       wq->pending++;
6733 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6734 +       DWC_WAITQ_TRIGGER(wq->waitq);
6735 +
6736 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6737 +       if (!container) {
6738 +               DWC_ERROR("Cannot allocate memory for container");
6739 +               return;
6740 +       }
6741 +
6742 +       container->name = DWC_STRDUP(name);
6743 +       if (!container->name) {
6744 +               DWC_ERROR("Cannot allocate memory for container->name");
6745 +               DWC_FREE(container);
6746 +               return;
6747 +       }
6748 +
6749 +       container->cb = cb;
6750 +       container->data = data;
6751 +       container->wq = wq;
6752 +
6753 +       tv.tv_sec = time / 1000;
6754 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6755 +       container->hz = tvtohz(&tv);
6756 +
6757 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6758 +
6759 +       TASK_INIT(&container->task, 0, do_work, container);
6760 +
6761 +#ifdef DEBUG
6762 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6763 +#endif
6764 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6765 +}
6766 +
6767 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
6768 +{
6769 +       return wq->pending;
6770 +}
6771 --- /dev/null
6772 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6773 @@ -0,0 +1,1429 @@
6774 +#include <linux/kernel.h>
6775 +#include <linux/init.h>
6776 +#include <linux/module.h>
6777 +#include <linux/kthread.h>
6778 +
6779 +#ifdef DWC_CCLIB
6780 +# include "dwc_cc.h"
6781 +#endif
6782 +
6783 +#ifdef DWC_CRYPTOLIB
6784 +# include "dwc_modpow.h"
6785 +# include "dwc_dh.h"
6786 +# include "dwc_crypto.h"
6787 +#endif
6788 +
6789 +#ifdef DWC_NOTIFYLIB
6790 +# include "dwc_notifier.h"
6791 +#endif
6792 +
6793 +/* OS-Level Implementations */
6794 +
6795 +/* This is the Linux kernel implementation of the DWC platform library. */
6796 +#include <linux/moduleparam.h>
6797 +#include <linux/ctype.h>
6798 +#include <linux/crypto.h>
6799 +#include <linux/delay.h>
6800 +#include <linux/device.h>
6801 +#include <linux/dma-mapping.h>
6802 +#include <linux/cdev.h>
6803 +#include <linux/errno.h>
6804 +#include <linux/interrupt.h>
6805 +#include <linux/jiffies.h>
6806 +#include <linux/list.h>
6807 +#include <linux/pci.h>
6808 +#include <linux/random.h>
6809 +#include <linux/scatterlist.h>
6810 +#include <linux/slab.h>
6811 +#include <linux/stat.h>
6812 +#include <linux/string.h>
6813 +#include <linux/timer.h>
6814 +#include <linux/usb.h>
6815 +
6816 +#include <linux/version.h>
6817 +
6818 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
6819 +# include <linux/usb/gadget.h>
6820 +#else
6821 +# include <linux/usb_gadget.h>
6822 +#endif
6823 +
6824 +#include <asm/io.h>
6825 +#include <asm/page.h>
6826 +#include <asm/uaccess.h>
6827 +#include <asm/unaligned.h>
6828 +
6829 +#include "dwc_os.h"
6830 +#include "dwc_list.h"
6831 +
6832 +
6833 +/* MISC */
6834 +
6835 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
6836 +{
6837 +       return memset(dest, byte, size);
6838 +}
6839 +
6840 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
6841 +{
6842 +       return memcpy(dest, src, size);
6843 +}
6844 +
6845 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
6846 +{
6847 +       return memmove(dest, src, size);
6848 +}
6849 +
6850 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
6851 +{
6852 +       return memcmp(m1, m2, size);
6853 +}
6854 +
6855 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
6856 +{
6857 +       return strncmp(s1, s2, size);
6858 +}
6859 +
6860 +int DWC_STRCMP(void *s1, void *s2)
6861 +{
6862 +       return strcmp(s1, s2);
6863 +}
6864 +
6865 +int DWC_STRLEN(char const *str)
6866 +{
6867 +       return strlen(str);
6868 +}
6869 +
6870 +char *DWC_STRCPY(char *to, char const *from)
6871 +{
6872 +       return strcpy(to, from);
6873 +}
6874 +
6875 +char *DWC_STRDUP(char const *str)
6876 +{
6877 +       int len = DWC_STRLEN(str) + 1;
6878 +       char *new = DWC_ALLOC_ATOMIC(len);
6879 +
6880 +       if (!new) {
6881 +               return NULL;
6882 +       }
6883 +
6884 +       DWC_MEMCPY(new, str, len);
6885 +       return new;
6886 +}
6887 +
6888 +int DWC_ATOI(const char *str, int32_t *value)
6889 +{
6890 +       char *end = NULL;
6891 +
6892 +       *value = simple_strtol(str, &end, 0);
6893 +       if (*end == '\0') {
6894 +               return 0;
6895 +       }
6896 +
6897 +       return -1;
6898 +}
6899 +
6900 +int DWC_ATOUI(const char *str, uint32_t *value)
6901 +{
6902 +       char *end = NULL;
6903 +
6904 +       *value = simple_strtoul(str, &end, 0);
6905 +       if (*end == '\0') {
6906 +               return 0;
6907 +       }
6908 +
6909 +       return -1;
6910 +}
6911 +
6912 +
6913 +#ifdef DWC_UTFLIB
6914 +/* From usbstring.c */
6915 +
6916 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
6917 +{
6918 +       int     count = 0;
6919 +       u8      c;
6920 +       u16     uchar;
6921 +
6922 +       /* this insists on correct encodings, though not minimal ones.
6923 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
6924 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
6925 +        */
6926 +       while (len != 0 && (c = (u8) *s++) != 0) {
6927 +               if (unlikely(c & 0x80)) {
6928 +                       // 2-byte sequence:
6929 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
6930 +                       if ((c & 0xe0) == 0xc0) {
6931 +                               uchar = (c & 0x1f) << 6;
6932 +
6933 +                               c = (u8) *s++;
6934 +                               if ((c & 0xc0) != 0xc0)
6935 +                                       goto fail;
6936 +                               c &= 0x3f;
6937 +                               uchar |= c;
6938 +
6939 +                       // 3-byte sequence (most CJKV characters):
6940 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
6941 +                       } else if ((c & 0xf0) == 0xe0) {
6942 +                               uchar = (c & 0x0f) << 12;
6943 +
6944 +                               c = (u8) *s++;
6945 +                               if ((c & 0xc0) != 0xc0)
6946 +                                       goto fail;
6947 +                               c &= 0x3f;
6948 +                               uchar |= c << 6;
6949 +
6950 +                               c = (u8) *s++;
6951 +                               if ((c & 0xc0) != 0xc0)
6952 +                                       goto fail;
6953 +                               c &= 0x3f;
6954 +                               uchar |= c;
6955 +
6956 +                               /* no bogus surrogates */
6957 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
6958 +                                       goto fail;
6959 +
6960 +                       // 4-byte sequence (surrogate pairs, currently rare):
6961 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
6962 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
6963 +                       // (uuuuu = wwww + 1)
6964 +                       // FIXME accept the surrogate code points (only)
6965 +                       } else
6966 +                               goto fail;
6967 +               } else
6968 +                       uchar = c;
6969 +               put_unaligned (cpu_to_le16 (uchar), cp++);
6970 +               count++;
6971 +               len--;
6972 +       }
6973 +       return count;
6974 +fail:
6975 +       return -1;
6976 +}
6977 +#endif /* DWC_UTFLIB */
6978 +
6979 +
6980 +/* dwc_debug.h */
6981 +
6982 +dwc_bool_t DWC_IN_IRQ(void)
6983 +{
6984 +       return in_irq();
6985 +}
6986 +
6987 +dwc_bool_t DWC_IN_BH(void)
6988 +{
6989 +       return in_softirq();
6990 +}
6991 +
6992 +void DWC_VPRINTF(char *format, va_list args)
6993 +{
6994 +       vprintk(format, args);
6995 +}
6996 +
6997 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
6998 +{
6999 +       return vsnprintf(str, size, format, args);
7000 +}
7001 +
7002 +void DWC_PRINTF(char *format, ...)
7003 +{
7004 +       va_list args;
7005 +
7006 +       va_start(args, format);
7007 +       DWC_VPRINTF(format, args);
7008 +       va_end(args);
7009 +}
7010 +
7011 +int DWC_SPRINTF(char *buffer, char *format, ...)
7012 +{
7013 +       int retval;
7014 +       va_list args;
7015 +
7016 +       va_start(args, format);
7017 +       retval = vsprintf(buffer, format, args);
7018 +       va_end(args);
7019 +       return retval;
7020 +}
7021 +
7022 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
7023 +{
7024 +       int retval;
7025 +       va_list args;
7026 +
7027 +       va_start(args, format);
7028 +       retval = vsnprintf(buffer, size, format, args);
7029 +       va_end(args);
7030 +       return retval;
7031 +}
7032 +
7033 +void __DWC_WARN(char *format, ...)
7034 +{
7035 +       va_list args;
7036 +
7037 +       va_start(args, format);
7038 +       DWC_PRINTF(KERN_WARNING);
7039 +       DWC_VPRINTF(format, args);
7040 +       va_end(args);
7041 +}
7042 +
7043 +void __DWC_ERROR(char *format, ...)
7044 +{
7045 +       va_list args;
7046 +
7047 +       va_start(args, format);
7048 +       DWC_PRINTF(KERN_ERR);
7049 +       DWC_VPRINTF(format, args);
7050 +       va_end(args);
7051 +}
7052 +
7053 +void DWC_EXCEPTION(char *format, ...)
7054 +{
7055 +       va_list args;
7056 +
7057 +       va_start(args, format);
7058 +       DWC_PRINTF(KERN_ERR);
7059 +       DWC_VPRINTF(format, args);
7060 +       va_end(args);
7061 +       BUG_ON(1);
7062 +}
7063 +
7064 +#ifdef DEBUG
7065 +void __DWC_DEBUG(char *format, ...)
7066 +{
7067 +       va_list args;
7068 +
7069 +       va_start(args, format);
7070 +       DWC_PRINTF(KERN_DEBUG);
7071 +       DWC_VPRINTF(format, args);
7072 +       va_end(args);
7073 +}
7074 +#endif
7075 +
7076 +
7077 +/* dwc_mem.h */
7078 +
7079 +#if 0
7080 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
7081 +                               uint32_t align,
7082 +                               uint32_t alloc)
7083 +{
7084 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
7085 +                                               size, align, alloc);
7086 +       return (dwc_pool_t *)pool;
7087 +}
7088 +
7089 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
7090 +{
7091 +       dma_pool_destroy((struct dma_pool *)pool);
7092 +}
7093 +
7094 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7095 +{
7096 +       return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
7097 +}
7098 +
7099 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7100 +{
7101 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
7102 +       memset(..);
7103 +}
7104 +
7105 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
7106 +{
7107 +       dma_pool_free(pool, vaddr, daddr);
7108 +}
7109 +#endif
7110 +
7111 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7112 +{
7113 +#ifdef xxCOSIM /* Only works for 32-bit cosim */
7114 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);
7115 +#else
7116 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);
7117 +#endif
7118 +       if (!buf) {
7119 +               return NULL;
7120 +       }
7121 +
7122 +       memset(buf, 0, (size_t)size);
7123 +       return buf;
7124 +}
7125 +
7126 +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7127 +{
7128 +       void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
7129 +       if (!buf) {
7130 +               return NULL;
7131 +       }
7132 +       memset(buf, 0, (size_t)size);
7133 +       return buf;
7134 +}
7135 +
7136 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
7137 +{
7138 +       dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);
7139 +}
7140 +
7141 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
7142 +{
7143 +       return kzalloc(size, GFP_KERNEL);
7144 +}
7145 +
7146 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
7147 +{
7148 +       return kzalloc(size, GFP_ATOMIC);
7149 +}
7150 +
7151 +void __DWC_FREE(void *mem_ctx, void *addr)
7152 +{
7153 +       kfree(addr);
7154 +}
7155 +
7156 +
7157 +#ifdef DWC_CRYPTOLIB
7158 +/* dwc_crypto.h */
7159 +
7160 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
7161 +{
7162 +       get_random_bytes(buffer, length);
7163 +}
7164 +
7165 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
7166 +{
7167 +       struct crypto_blkcipher *tfm;
7168 +       struct blkcipher_desc desc;
7169 +       struct scatterlist sgd;
7170 +       struct scatterlist sgs;
7171 +
7172 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
7173 +       if (tfm == NULL) {
7174 +               printk("failed to load transform for aes CBC\n");
7175 +               return -1;
7176 +       }
7177 +
7178 +       crypto_blkcipher_setkey(tfm, key, keylen);
7179 +       crypto_blkcipher_set_iv(tfm, iv, 16);
7180 +
7181 +       sg_init_one(&sgd, out, messagelen);
7182 +       sg_init_one(&sgs, message, messagelen);
7183 +
7184 +       desc.tfm = tfm;
7185 +       desc.flags = 0;
7186 +
7187 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
7188 +               crypto_free_blkcipher(tfm);
7189 +               DWC_ERROR("AES CBC encryption failed");
7190 +               return -1;
7191 +       }
7192 +
7193 +       crypto_free_blkcipher(tfm);
7194 +       return 0;
7195 +}
7196 +
7197 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
7198 +{
7199 +       struct crypto_hash *tfm;
7200 +       struct hash_desc desc;
7201 +       struct scatterlist sg;
7202 +
7203 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
7204 +       if (IS_ERR(tfm)) {
7205 +               DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
7206 +               return 0;
7207 +       }
7208 +       desc.tfm = tfm;
7209 +       desc.flags = 0;
7210 +
7211 +       sg_init_one(&sg, message, len);
7212 +       crypto_hash_digest(&desc, &sg, len, out);
7213 +       crypto_free_hash(tfm);
7214 +
7215 +       return 1;
7216 +}
7217 +
7218 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
7219 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
7220 +{
7221 +       struct crypto_hash *tfm;
7222 +       struct hash_desc desc;
7223 +       struct scatterlist sg;
7224 +
7225 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
7226 +       if (IS_ERR(tfm)) {
7227 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
7228 +               return 0;
7229 +       }
7230 +       desc.tfm = tfm;
7231 +       desc.flags = 0;
7232 +
7233 +       sg_init_one(&sg, message, messagelen);
7234 +       crypto_hash_setkey(tfm, key, keylen);
7235 +       crypto_hash_digest(&desc, &sg, messagelen, out);
7236 +       crypto_free_hash(tfm);
7237 +
7238 +       return 1;
7239 +}
7240 +#endif /* DWC_CRYPTOLIB */
7241 +
7242 +
7243 +/* Byte Ordering Conversions */
7244 +
7245 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
7246 +{
7247 +#ifdef __LITTLE_ENDIAN
7248 +       return *p;
7249 +#else
7250 +       uint8_t *u_p = (uint8_t *)p;
7251 +
7252 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7253 +#endif
7254 +}
7255 +
7256 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
7257 +{
7258 +#ifdef __BIG_ENDIAN
7259 +       return *p;
7260 +#else
7261 +       uint8_t *u_p = (uint8_t *)p;
7262 +
7263 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7264 +#endif
7265 +}
7266 +
7267 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
7268 +{
7269 +#ifdef __LITTLE_ENDIAN
7270 +       return *p;
7271 +#else
7272 +       uint8_t *u_p = (uint8_t *)p;
7273 +
7274 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7275 +#endif
7276 +}
7277 +
7278 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
7279 +{
7280 +#ifdef __BIG_ENDIAN
7281 +       return *p;
7282 +#else
7283 +       uint8_t *u_p = (uint8_t *)p;
7284 +
7285 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7286 +#endif
7287 +}
7288 +
7289 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
7290 +{
7291 +#ifdef __LITTLE_ENDIAN
7292 +       return *p;
7293 +#else
7294 +       uint8_t *u_p = (uint8_t *)p;
7295 +       return (u_p[1] | (u_p[0] << 8));
7296 +#endif
7297 +}
7298 +
7299 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
7300 +{
7301 +#ifdef __BIG_ENDIAN
7302 +       return *p;
7303 +#else
7304 +       uint8_t *u_p = (uint8_t *)p;
7305 +       return (u_p[1] | (u_p[0] << 8));
7306 +#endif
7307 +}
7308 +
7309 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
7310 +{
7311 +#ifdef __LITTLE_ENDIAN
7312 +       return *p;
7313 +#else
7314 +       uint8_t *u_p = (uint8_t *)p;
7315 +       return (u_p[1] | (u_p[0] << 8));
7316 +#endif
7317 +}
7318 +
7319 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
7320 +{
7321 +#ifdef __BIG_ENDIAN
7322 +       return *p;
7323 +#else
7324 +       uint8_t *u_p = (uint8_t *)p;
7325 +       return (u_p[1] | (u_p[0] << 8));
7326 +#endif
7327 +}
7328 +
7329 +
7330 +/* Registers */
7331 +
7332 +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
7333 +{
7334 +       return readl(reg);
7335 +}
7336 +
7337 +#if 0
7338 +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
7339 +{
7340 +}
7341 +#endif
7342 +
7343 +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
7344 +{
7345 +       writel(value, reg);
7346 +}
7347 +
7348 +#if 0
7349 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
7350 +{
7351 +}
7352 +#endif
7353 +
7354 +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
7355 +{
7356 +       writel((readl(reg) & ~clear_mask) | set_mask, reg);
7357 +}
7358 +
7359 +#if 0
7360 +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)
7361 +{
7362 +}
7363 +#endif
7364 +
7365 +
7366 +/* Locking */
7367 +
7368 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
7369 +{
7370 +       spinlock_t *sl = (spinlock_t *)1;
7371 +
7372 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7373 +       sl = DWC_ALLOC(sizeof(*sl));
7374 +       if (!sl) {
7375 +               DWC_ERROR("Cannot allocate memory for spinlock\n");
7376 +               return NULL;
7377 +       }
7378 +
7379 +       spin_lock_init(sl);
7380 +#endif
7381 +       return (dwc_spinlock_t *)sl;
7382 +}
7383 +
7384 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
7385 +{
7386 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7387 +       DWC_FREE(lock);
7388 +#endif
7389 +}
7390 +
7391 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
7392 +{
7393 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7394 +       spin_lock((spinlock_t *)lock);
7395 +#endif
7396 +}
7397 +
7398 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
7399 +{
7400 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7401 +       spin_unlock((spinlock_t *)lock);
7402 +#endif
7403 +}
7404 +
7405 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
7406 +{
7407 +       dwc_irqflags_t f;
7408 +
7409 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7410 +       spin_lock_irqsave((spinlock_t *)lock, f);
7411 +#else
7412 +       local_irq_save(f);
7413 +#endif
7414 +       *flags = f;
7415 +}
7416 +
7417 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
7418 +{
7419 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7420 +       spin_unlock_irqrestore((spinlock_t *)lock, flags);
7421 +#else
7422 +       local_irq_restore(flags);
7423 +#endif
7424 +}
7425 +
7426 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
7427 +{
7428 +       struct mutex *m;
7429 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));
7430 +
7431 +       if (!mutex) {
7432 +               DWC_ERROR("Cannot allocate memory for mutex\n");
7433 +               return NULL;
7434 +       }
7435 +
7436 +       m = (struct mutex *)mutex;
7437 +       mutex_init(m);
7438 +       return mutex;
7439 +}
7440 +
7441 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
7442 +#else
7443 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
7444 +{
7445 +       mutex_destroy((struct mutex *)mutex);
7446 +       DWC_FREE(mutex);
7447 +}
7448 +#endif
7449 +
7450 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
7451 +{
7452 +       struct mutex *m = (struct mutex *)mutex;
7453 +       mutex_lock(m);
7454 +}
7455 +
7456 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
7457 +{
7458 +       struct mutex *m = (struct mutex *)mutex;
7459 +       return mutex_trylock(m);
7460 +}
7461 +
7462 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
7463 +{
7464 +       struct mutex *m = (struct mutex *)mutex;
7465 +       mutex_unlock(m);
7466 +}
7467 +
7468 +
7469 +/* Timing */
7470 +
7471 +void DWC_UDELAY(uint32_t usecs)
7472 +{
7473 +       udelay(usecs);
7474 +}
7475 +
7476 +void DWC_MDELAY(uint32_t msecs)
7477 +{
7478 +       mdelay(msecs);
7479 +}
7480 +
7481 +void DWC_MSLEEP(uint32_t msecs)
7482 +{
7483 +       msleep(msecs);
7484 +}
7485 +
7486 +uint32_t DWC_TIME(void)
7487 +{
7488 +       return jiffies_to_msecs(jiffies);
7489 +}
7490 +
7491 +
7492 +/* Timers */
7493 +
7494 +struct dwc_timer {
7495 +       struct timer_list *t;
7496 +       char *name;
7497 +       dwc_timer_callback_t cb;
7498 +       void *data;
7499 +       uint8_t scheduled;
7500 +       dwc_spinlock_t *lock;
7501 +};
7502 +
7503 +static void timer_callback(unsigned long data)
7504 +{
7505 +       dwc_timer_t *timer = (dwc_timer_t *)data;
7506 +       dwc_irqflags_t flags;
7507 +
7508 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7509 +       timer->scheduled = 0;
7510 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7511 +       DWC_DEBUGC("Timer %s callback", timer->name);
7512 +       timer->cb(timer->data);
7513 +}
7514 +
7515 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
7516 +{
7517 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
7518 +
7519 +       if (!t) {
7520 +               DWC_ERROR("Cannot allocate memory for timer");
7521 +               return NULL;
7522 +       }
7523 +
7524 +       t->t = DWC_ALLOC(sizeof(*t->t));
7525 +       if (!t->t) {
7526 +               DWC_ERROR("Cannot allocate memory for timer->t");
7527 +               goto no_timer;
7528 +       }
7529 +
7530 +       t->name = DWC_STRDUP(name);
7531 +       if (!t->name) {
7532 +               DWC_ERROR("Cannot allocate memory for timer->name");
7533 +               goto no_name;
7534 +       }
7535 +
7536 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
7537 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(t->lock);
7538 +#else
7539 +       t->lock = DWC_SPINLOCK_ALLOC();
7540 +#endif
7541 +       if (!t->lock) {
7542 +               DWC_ERROR("Cannot allocate memory for lock");
7543 +               goto no_lock;
7544 +       }
7545 +
7546 +       t->scheduled = 0;
7547 +       t->t->base = &boot_tvec_bases;
7548 +       t->t->expires = jiffies;
7549 +       setup_timer(t->t, timer_callback, (unsigned long)t);
7550 +
7551 +       t->cb = cb;
7552 +       t->data = data;
7553 +
7554 +       return t;
7555 +
7556 + no_lock:
7557 +       DWC_FREE(t->name);
7558 + no_name:
7559 +       DWC_FREE(t->t);
7560 + no_timer:
7561 +       DWC_FREE(t);
7562 +       return NULL;
7563 +}
7564 +
7565 +void DWC_TIMER_FREE(dwc_timer_t *timer)
7566 +{
7567 +       dwc_irqflags_t flags;
7568 +
7569 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7570 +
7571 +       if (timer->scheduled) {
7572 +               del_timer(timer->t);
7573 +               timer->scheduled = 0;
7574 +       }
7575 +
7576 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7577 +       DWC_SPINLOCK_FREE(timer->lock);
7578 +       DWC_FREE(timer->t);
7579 +       DWC_FREE(timer->name);
7580 +       DWC_FREE(timer);
7581 +}
7582 +
7583 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
7584 +{
7585 +       dwc_irqflags_t flags;
7586 +
7587 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7588 +
7589 +       if (!timer->scheduled) {
7590 +               timer->scheduled = 1;
7591 +               DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);
7592 +               timer->t->expires = jiffies + msecs_to_jiffies(time);
7593 +               add_timer(timer->t);
7594 +       } else {
7595 +               DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);
7596 +               mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
7597 +       }
7598 +
7599 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7600 +}
7601 +
7602 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
7603 +{
7604 +       del_timer(timer->t);
7605 +}
7606 +
7607 +
7608 +/* Wait Queues */
7609 +
7610 +struct dwc_waitq {
7611 +       wait_queue_head_t queue;
7612 +       int abort;
7613 +};
7614 +
7615 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
7616 +{
7617 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
7618 +
7619 +       if (!wq) {
7620 +               DWC_ERROR("Cannot allocate memory for waitqueue\n");
7621 +               return NULL;
7622 +       }
7623 +
7624 +       init_waitqueue_head(&wq->queue);
7625 +       wq->abort = 0;
7626 +       return wq;
7627 +}
7628 +
7629 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
7630 +{
7631 +       DWC_FREE(wq);
7632 +}
7633 +
7634 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
7635 +{
7636 +       int result = wait_event_interruptible(wq->queue,
7637 +                                             cond(data) || wq->abort);
7638 +       if (result == -ERESTARTSYS) {
7639 +               wq->abort = 0;
7640 +               return -DWC_E_RESTART;
7641 +       }
7642 +
7643 +       if (wq->abort == 1) {
7644 +               wq->abort = 0;
7645 +               return -DWC_E_ABORT;
7646 +       }
7647 +
7648 +       wq->abort = 0;
7649 +
7650 +       if (result == 0) {
7651 +               return 0;
7652 +       }
7653 +
7654 +       return -DWC_E_UNKNOWN;
7655 +}
7656 +
7657 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
7658 +                              void *data, int32_t msecs)
7659 +{
7660 +       int32_t tmsecs;
7661 +       int result = wait_event_interruptible_timeout(wq->queue,
7662 +                                                     cond(data) || wq->abort,
7663 +                                                     msecs_to_jiffies(msecs));
7664 +       if (result == -ERESTARTSYS) {
7665 +               wq->abort = 0;
7666 +               return -DWC_E_RESTART;
7667 +       }
7668 +
7669 +       if (wq->abort == 1) {
7670 +               wq->abort = 0;
7671 +               return -DWC_E_ABORT;
7672 +       }
7673 +
7674 +       wq->abort = 0;
7675 +
7676 +       if (result > 0) {
7677 +               tmsecs = jiffies_to_msecs(result);
7678 +               if (!tmsecs) {
7679 +                       return 1;
7680 +               }
7681 +
7682 +               return tmsecs;
7683 +       }
7684 +
7685 +       if (result == 0) {
7686 +               return -DWC_E_TIMEOUT;
7687 +       }
7688 +
7689 +       return -DWC_E_UNKNOWN;
7690 +}
7691 +
7692 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
7693 +{
7694 +       wq->abort = 0;
7695 +       wake_up_interruptible(&wq->queue);
7696 +}
7697 +
7698 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
7699 +{
7700 +       wq->abort = 1;
7701 +       wake_up_interruptible(&wq->queue);
7702 +}
7703 +
7704 +
7705 +/* Threading */
7706 +
7707 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
7708 +{
7709 +       struct task_struct *thread = kthread_run(func, data, name);
7710 +
7711 +       if (thread == ERR_PTR(-ENOMEM)) {
7712 +               return NULL;
7713 +       }
7714 +
7715 +       return (dwc_thread_t *)thread;
7716 +}
7717 +
7718 +int DWC_THREAD_STOP(dwc_thread_t *thread)
7719 +{
7720 +       return kthread_stop((struct task_struct *)thread);
7721 +}
7722 +
7723 +dwc_bool_t DWC_THREAD_SHOULD_STOP(void)
7724 +{
7725 +       return kthread_should_stop();
7726 +}
7727 +
7728 +
7729 +/* tasklets
7730 + - run in interrupt context (cannot sleep)
7731 + - each tasklet runs on a single CPU
7732 + - different tasklets can be running simultaneously on different CPUs
7733 + */
7734 +struct dwc_tasklet {
7735 +       struct tasklet_struct t;
7736 +       dwc_tasklet_callback_t cb;
7737 +       void *data;
7738 +};
7739 +
7740 +static void tasklet_callback(unsigned long data)
7741 +{
7742 +       dwc_tasklet_t *t = (dwc_tasklet_t *)data;
7743 +       t->cb(t->data);
7744 +}
7745 +
7746 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
7747 +{
7748 +       dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
7749 +
7750 +       if (t) {
7751 +               t->cb = cb;
7752 +               t->data = data;
7753 +               tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
7754 +       } else {
7755 +               DWC_ERROR("Cannot allocate memory for tasklet\n");
7756 +       }
7757 +
7758 +       return t;
7759 +}
7760 +
7761 +void DWC_TASK_FREE(dwc_tasklet_t *task)
7762 +{
7763 +       DWC_FREE(task);
7764 +}
7765 +
7766 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
7767 +{
7768 +       tasklet_schedule(&task->t);
7769 +}
7770 +
7771 +
7772 +/* workqueues
7773 + - run in process context (can sleep)
7774 + */
7775 +typedef struct work_container {
7776 +       dwc_work_callback_t cb;
7777 +       void *data;
7778 +       dwc_workq_t *wq;
7779 +       char *name;
7780 +
7781 +#ifdef DEBUG
7782 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
7783 +#endif
7784 +       struct delayed_work work;
7785 +} work_container_t;
7786 +
7787 +#ifdef DEBUG
7788 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
7789 +#endif
7790 +
7791 +struct dwc_workq {
7792 +       struct workqueue_struct *wq;
7793 +       dwc_spinlock_t *lock;
7794 +       dwc_waitq_t *waitq;
7795 +       int pending;
7796 +
7797 +#ifdef DEBUG
7798 +       struct work_container_queue entries;
7799 +#endif
7800 +};
7801 +
7802 +static void do_work(struct work_struct *work)
7803 +{
7804 +       dwc_irqflags_t flags;
7805 +       struct delayed_work *dw = container_of(work, struct delayed_work, work);
7806 +       work_container_t *container = container_of(dw, struct work_container, work);
7807 +       dwc_workq_t *wq = container->wq;
7808 +
7809 +       container->cb(container->data);
7810 +
7811 +#ifdef DEBUG
7812 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
7813 +#endif
7814 +       DWC_DEBUGC("Work done: %s, container=%p", container->name, container);
7815 +       if (container->name) {
7816 +               DWC_FREE(container->name);
7817 +       }
7818 +       DWC_FREE(container);
7819 +
7820 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7821 +       wq->pending--;
7822 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7823 +       DWC_WAITQ_TRIGGER(wq->waitq);
7824 +}
7825 +
7826 +static int work_done(void *data)
7827 +{
7828 +       dwc_workq_t *workq = (dwc_workq_t *)data;
7829 +       return workq->pending == 0;
7830 +}
7831 +
7832 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
7833 +{
7834 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
7835 +}
7836 +
7837 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
7838 +{
7839 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
7840 +
7841 +       if (!wq) {
7842 +               return NULL;
7843 +       }
7844 +
7845 +       wq->wq = create_singlethread_workqueue(name);
7846 +       if (!wq->wq) {
7847 +               goto no_wq;
7848 +       }
7849 +
7850 +       wq->pending = 0;
7851 +
7852 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
7853 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(wq->lock);
7854 +#else
7855 +       wq->lock = DWC_SPINLOCK_ALLOC();
7856 +#endif
7857 +       if (!wq->lock) {
7858 +               goto no_lock;
7859 +       }
7860 +
7861 +       wq->waitq = DWC_WAITQ_ALLOC();
7862 +       if (!wq->waitq) {
7863 +               goto no_waitq;
7864 +       }
7865 +
7866 +#ifdef DEBUG
7867 +       DWC_CIRCLEQ_INIT(&wq->entries);
7868 +#endif
7869 +       return wq;
7870 +
7871 + no_waitq:
7872 +       DWC_SPINLOCK_FREE(wq->lock);
7873 + no_lock:
7874 +       destroy_workqueue(wq->wq);
7875 + no_wq:
7876 +       DWC_FREE(wq);
7877 +
7878 +       return NULL;
7879 +}
7880 +
7881 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
7882 +{
7883 +#ifdef DEBUG
7884 +       if (wq->pending != 0) {
7885 +               struct work_container *wc;
7886 +               DWC_ERROR("Destroying work queue with pending work");
7887 +               DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
7888 +                       DWC_ERROR("Work %s still pending", wc->name);
7889 +               }
7890 +       }
7891 +#endif
7892 +       destroy_workqueue(wq->wq);
7893 +       DWC_SPINLOCK_FREE(wq->lock);
7894 +       DWC_WAITQ_FREE(wq->waitq);
7895 +       DWC_FREE(wq);
7896 +}
7897 +
7898 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
7899 +                       char *format, ...)
7900 +{
7901 +       dwc_irqflags_t flags;
7902 +       work_container_t *container;
7903 +       static char name[128];
7904 +       va_list args;
7905 +
7906 +       va_start(args, format);
7907 +       DWC_VSNPRINTF(name, 128, format, args);
7908 +       va_end(args);
7909 +
7910 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7911 +       wq->pending++;
7912 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7913 +       DWC_WAITQ_TRIGGER(wq->waitq);
7914 +
7915 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
7916 +       if (!container) {
7917 +               DWC_ERROR("Cannot allocate memory for container\n");
7918 +               return;
7919 +       }
7920 +
7921 +       container->name = DWC_STRDUP(name);
7922 +       if (!container->name) {
7923 +               DWC_ERROR("Cannot allocate memory for container->name\n");
7924 +               DWC_FREE(container);
7925 +               return;
7926 +       }
7927 +
7928 +       container->cb = cb;
7929 +       container->data = data;
7930 +       container->wq = wq;
7931 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
7932 +       INIT_WORK(&container->work.work, do_work);
7933 +
7934 +#ifdef DEBUG
7935 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
7936 +#endif
7937 +       queue_work(wq->wq, &container->work.work);
7938 +}
7939 +
7940 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
7941 +                               void *data, uint32_t time, char *format, ...)
7942 +{
7943 +       dwc_irqflags_t flags;
7944 +       work_container_t *container;
7945 +       static char name[128];
7946 +       va_list args;
7947 +
7948 +       va_start(args, format);
7949 +       DWC_VSNPRINTF(name, 128, format, args);
7950 +       va_end(args);
7951 +
7952 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7953 +       wq->pending++;
7954 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7955 +       DWC_WAITQ_TRIGGER(wq->waitq);
7956 +
7957 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
7958 +       if (!container) {
7959 +               DWC_ERROR("Cannot allocate memory for container\n");
7960 +               return;
7961 +       }
7962 +
7963 +       container->name = DWC_STRDUP(name);
7964 +       if (!container->name) {
7965 +               DWC_ERROR("Cannot allocate memory for container->name\n");
7966 +               DWC_FREE(container);
7967 +               return;
7968 +       }
7969 +
7970 +       container->cb = cb;
7971 +       container->data = data;
7972 +       container->wq = wq;
7973 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
7974 +       INIT_DELAYED_WORK(&container->work, do_work);
7975 +
7976 +#ifdef DEBUG
7977 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
7978 +#endif
7979 +       queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
7980 +}
7981 +
7982 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
7983 +{
7984 +       return wq->pending;
7985 +}
7986 +
7987 +
7988 +#ifdef DWC_LIBMODULE
7989 +
7990 +#ifdef DWC_CCLIB
7991 +/* CC */
7992 +EXPORT_SYMBOL(dwc_cc_if_alloc);
7993 +EXPORT_SYMBOL(dwc_cc_if_free);
7994 +EXPORT_SYMBOL(dwc_cc_clear);
7995 +EXPORT_SYMBOL(dwc_cc_add);
7996 +EXPORT_SYMBOL(dwc_cc_remove);
7997 +EXPORT_SYMBOL(dwc_cc_change);
7998 +EXPORT_SYMBOL(dwc_cc_data_for_save);
7999 +EXPORT_SYMBOL(dwc_cc_restore_from_data);
8000 +EXPORT_SYMBOL(dwc_cc_match_chid);
8001 +EXPORT_SYMBOL(dwc_cc_match_cdid);
8002 +EXPORT_SYMBOL(dwc_cc_ck);
8003 +EXPORT_SYMBOL(dwc_cc_chid);
8004 +EXPORT_SYMBOL(dwc_cc_cdid);
8005 +EXPORT_SYMBOL(dwc_cc_name);
8006 +#endif /* DWC_CCLIB */
8007 +
8008 +#ifdef DWC_CRYPTOLIB
8009 +# ifndef CONFIG_MACH_IPMATE
8010 +/* Modpow */
8011 +EXPORT_SYMBOL(dwc_modpow);
8012 +
8013 +/* DH */
8014 +EXPORT_SYMBOL(dwc_dh_modpow);
8015 +EXPORT_SYMBOL(dwc_dh_derive_keys);
8016 +EXPORT_SYMBOL(dwc_dh_pk);
8017 +# endif        /* CONFIG_MACH_IPMATE */
8018 +
8019 +/* Crypto */
8020 +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
8021 +EXPORT_SYMBOL(dwc_wusb_cmf);
8022 +EXPORT_SYMBOL(dwc_wusb_prf);
8023 +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
8024 +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
8025 +EXPORT_SYMBOL(dwc_wusb_gen_key);
8026 +EXPORT_SYMBOL(dwc_wusb_gen_mic);
8027 +#endif /* DWC_CRYPTOLIB */
8028 +
8029 +/* Notification */
8030 +#ifdef DWC_NOTIFYLIB
8031 +EXPORT_SYMBOL(dwc_alloc_notification_manager);
8032 +EXPORT_SYMBOL(dwc_free_notification_manager);
8033 +EXPORT_SYMBOL(dwc_register_notifier);
8034 +EXPORT_SYMBOL(dwc_unregister_notifier);
8035 +EXPORT_SYMBOL(dwc_add_observer);
8036 +EXPORT_SYMBOL(dwc_remove_observer);
8037 +EXPORT_SYMBOL(dwc_notify);
8038 +#endif
8039 +
8040 +/* Memory Debugging Routines */
8041 +#ifdef DWC_DEBUG_MEMORY
8042 +EXPORT_SYMBOL(dwc_alloc_debug);
8043 +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
8044 +EXPORT_SYMBOL(dwc_free_debug);
8045 +EXPORT_SYMBOL(dwc_dma_alloc_debug);
8046 +EXPORT_SYMBOL(dwc_dma_free_debug);
8047 +#endif
8048 +
8049 +EXPORT_SYMBOL(DWC_MEMSET);
8050 +EXPORT_SYMBOL(DWC_MEMCPY);
8051 +EXPORT_SYMBOL(DWC_MEMMOVE);
8052 +EXPORT_SYMBOL(DWC_MEMCMP);
8053 +EXPORT_SYMBOL(DWC_STRNCMP);
8054 +EXPORT_SYMBOL(DWC_STRCMP);
8055 +EXPORT_SYMBOL(DWC_STRLEN);
8056 +EXPORT_SYMBOL(DWC_STRCPY);
8057 +EXPORT_SYMBOL(DWC_STRDUP);
8058 +EXPORT_SYMBOL(DWC_ATOI);
8059 +EXPORT_SYMBOL(DWC_ATOUI);
8060 +
8061 +#ifdef DWC_UTFLIB
8062 +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
8063 +#endif /* DWC_UTFLIB */
8064 +
8065 +EXPORT_SYMBOL(DWC_IN_IRQ);
8066 +EXPORT_SYMBOL(DWC_IN_BH);
8067 +EXPORT_SYMBOL(DWC_VPRINTF);
8068 +EXPORT_SYMBOL(DWC_VSNPRINTF);
8069 +EXPORT_SYMBOL(DWC_PRINTF);
8070 +EXPORT_SYMBOL(DWC_SPRINTF);
8071 +EXPORT_SYMBOL(DWC_SNPRINTF);
8072 +EXPORT_SYMBOL(__DWC_WARN);
8073 +EXPORT_SYMBOL(__DWC_ERROR);
8074 +EXPORT_SYMBOL(DWC_EXCEPTION);
8075 +
8076 +#ifdef DEBUG
8077 +EXPORT_SYMBOL(__DWC_DEBUG);
8078 +#endif
8079 +
8080 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
8081 +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
8082 +EXPORT_SYMBOL(__DWC_DMA_FREE);
8083 +EXPORT_SYMBOL(__DWC_ALLOC);
8084 +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
8085 +EXPORT_SYMBOL(__DWC_FREE);
8086 +
8087 +#ifdef DWC_CRYPTOLIB
8088 +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
8089 +EXPORT_SYMBOL(DWC_AES_CBC);
8090 +EXPORT_SYMBOL(DWC_SHA256);
8091 +EXPORT_SYMBOL(DWC_HMAC_SHA256);
8092 +#endif
8093 +
8094 +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
8095 +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
8096 +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
8097 +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
8098 +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
8099 +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
8100 +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
8101 +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
8102 +EXPORT_SYMBOL(DWC_READ_REG32);
8103 +EXPORT_SYMBOL(DWC_WRITE_REG32);
8104 +EXPORT_SYMBOL(DWC_MODIFY_REG32);
8105 +
8106 +#if 0
8107 +EXPORT_SYMBOL(DWC_READ_REG64);
8108 +EXPORT_SYMBOL(DWC_WRITE_REG64);
8109 +EXPORT_SYMBOL(DWC_MODIFY_REG64);
8110 +#endif
8111 +
8112 +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
8113 +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
8114 +EXPORT_SYMBOL(DWC_SPINLOCK);
8115 +EXPORT_SYMBOL(DWC_SPINUNLOCK);
8116 +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
8117 +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
8118 +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
8119 +
8120 +#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))
8121 +EXPORT_SYMBOL(DWC_MUTEX_FREE);
8122 +#endif
8123 +
8124 +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
8125 +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
8126 +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
8127 +EXPORT_SYMBOL(DWC_UDELAY);
8128 +EXPORT_SYMBOL(DWC_MDELAY);
8129 +EXPORT_SYMBOL(DWC_MSLEEP);
8130 +EXPORT_SYMBOL(DWC_TIME);
8131 +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
8132 +EXPORT_SYMBOL(DWC_TIMER_FREE);
8133 +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
8134 +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
8135 +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
8136 +EXPORT_SYMBOL(DWC_WAITQ_FREE);
8137 +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
8138 +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
8139 +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
8140 +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
8141 +EXPORT_SYMBOL(DWC_THREAD_RUN);
8142 +EXPORT_SYMBOL(DWC_THREAD_STOP);
8143 +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
8144 +EXPORT_SYMBOL(DWC_TASK_ALLOC);
8145 +EXPORT_SYMBOL(DWC_TASK_FREE);
8146 +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
8147 +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
8148 +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
8149 +EXPORT_SYMBOL(DWC_WORKQ_FREE);
8150 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
8151 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
8152 +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
8153 +
8154 +static int dwc_common_port_init_module(void)
8155 +{
8156 +       int result = 0;
8157 +
8158 +       printk(KERN_DEBUG "Module dwc_common_port init\n" );
8159 +
8160 +#ifdef DWC_DEBUG_MEMORY
8161 +       result = dwc_memory_debug_start(NULL);
8162 +       if (result) {
8163 +               printk(KERN_ERR
8164 +                      "dwc_memory_debug_start() failed with error %d\n",
8165 +                      result);
8166 +               return result;
8167 +       }
8168 +#endif
8169 +
8170 +#ifdef DWC_NOTIFYLIB
8171 +       result = dwc_alloc_notification_manager(NULL, NULL);
8172 +       if (result) {
8173 +               printk(KERN_ERR
8174 +                      "dwc_alloc_notification_manager() failed with error %d\n",
8175 +                      result);
8176 +               return result;
8177 +       }
8178 +#endif
8179 +       return result;
8180 +}
8181 +
8182 +static void dwc_common_port_exit_module(void)
8183 +{
8184 +       printk(KERN_DEBUG "Module dwc_common_port exit\n" );
8185 +
8186 +#ifdef DWC_NOTIFYLIB
8187 +       dwc_free_notification_manager();
8188 +#endif
8189 +
8190 +#ifdef DWC_DEBUG_MEMORY
8191 +       dwc_memory_debug_stop();
8192 +#endif
8193 +}
8194 +
8195 +module_init(dwc_common_port_init_module);
8196 +module_exit(dwc_common_port_exit_module);
8197 +
8198 +MODULE_DESCRIPTION("DWC Common Library - Portable version");
8199 +MODULE_AUTHOR("Synopsys Inc.");
8200 +MODULE_LICENSE ("GPL");
8201 +
8202 +#endif /* DWC_LIBMODULE */
8203 --- /dev/null
8204 +++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
8205 @@ -0,0 +1,1275 @@
8206 +#include "dwc_os.h"
8207 +#include "dwc_list.h"
8208 +
8209 +#ifdef DWC_CCLIB
8210 +# include "dwc_cc.h"
8211 +#endif
8212 +
8213 +#ifdef DWC_CRYPTOLIB
8214 +# include "dwc_modpow.h"
8215 +# include "dwc_dh.h"
8216 +# include "dwc_crypto.h"
8217 +#endif
8218 +
8219 +#ifdef DWC_NOTIFYLIB
8220 +# include "dwc_notifier.h"
8221 +#endif
8222 +
8223 +/* OS-Level Implementations */
8224 +
8225 +/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */
8226 +
8227 +
8228 +/* MISC */
8229 +
8230 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
8231 +{
8232 +       return memset(dest, byte, size);
8233 +}
8234 +
8235 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
8236 +{
8237 +       return memcpy(dest, src, size);
8238 +}
8239 +
8240 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
8241 +{
8242 +       bcopy(src, dest, size);
8243 +       return dest;
8244 +}
8245 +
8246 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
8247 +{
8248 +       return memcmp(m1, m2, size);
8249 +}
8250 +
8251 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
8252 +{
8253 +       return strncmp(s1, s2, size);
8254 +}
8255 +
8256 +int DWC_STRCMP(void *s1, void *s2)
8257 +{
8258 +       return strcmp(s1, s2);
8259 +}
8260 +
8261 +int DWC_STRLEN(char const *str)
8262 +{
8263 +       return strlen(str);
8264 +}
8265 +
8266 +char *DWC_STRCPY(char *to, char const *from)
8267 +{
8268 +       return strcpy(to, from);
8269 +}
8270 +
8271 +char *DWC_STRDUP(char const *str)
8272 +{
8273 +       int len = DWC_STRLEN(str) + 1;
8274 +       char *new = DWC_ALLOC_ATOMIC(len);
8275 +
8276 +       if (!new) {
8277 +               return NULL;
8278 +       }
8279 +
8280 +       DWC_MEMCPY(new, str, len);
8281 +       return new;
8282 +}
8283 +
8284 +int DWC_ATOI(char *str, int32_t *value)
8285 +{
8286 +       char *end = NULL;
8287 +
8288 +       /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'
8289 +        * should be equivalent on 2's complement machines
8290 +        */
8291 +       *value = strtoul(str, &end, 0);
8292 +       if (*end == '\0') {
8293 +               return 0;
8294 +       }
8295 +
8296 +       return -1;
8297 +}
8298 +
8299 +int DWC_ATOUI(char *str, uint32_t *value)
8300 +{
8301 +       char *end = NULL;
8302 +
8303 +       *value = strtoul(str, &end, 0);
8304 +       if (*end == '\0') {
8305 +               return 0;
8306 +       }
8307 +
8308 +       return -1;
8309 +}
8310 +
8311 +
8312 +#ifdef DWC_UTFLIB
8313 +/* From usbstring.c */
8314 +
8315 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
8316 +{
8317 +       int     count = 0;
8318 +       u8      c;
8319 +       u16     uchar;
8320 +
8321 +       /* this insists on correct encodings, though not minimal ones.
8322 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
8323 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
8324 +        */
8325 +       while (len != 0 && (c = (u8) *s++) != 0) {
8326 +               if (unlikely(c & 0x80)) {
8327 +                       // 2-byte sequence:
8328 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
8329 +                       if ((c & 0xe0) == 0xc0) {
8330 +                               uchar = (c & 0x1f) << 6;
8331 +
8332 +                               c = (u8) *s++;
8333 +                               if ((c & 0xc0) != 0xc0)
8334 +                                       goto fail;
8335 +                               c &= 0x3f;
8336 +                               uchar |= c;
8337 +
8338 +                       // 3-byte sequence (most CJKV characters):
8339 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
8340 +                       } else if ((c & 0xf0) == 0xe0) {
8341 +                               uchar = (c & 0x0f) << 12;
8342 +
8343 +                               c = (u8) *s++;
8344 +                               if ((c & 0xc0) != 0xc0)
8345 +                                       goto fail;
8346 +                               c &= 0x3f;
8347 +                               uchar |= c << 6;
8348 +
8349 +                               c = (u8) *s++;
8350 +                               if ((c & 0xc0) != 0xc0)
8351 +                                       goto fail;
8352 +                               c &= 0x3f;
8353 +                               uchar |= c;
8354 +
8355 +                               /* no bogus surrogates */
8356 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
8357 +                                       goto fail;
8358 +
8359 +                       // 4-byte sequence (surrogate pairs, currently rare):
8360 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
8361 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
8362 +                       // (uuuuu = wwww + 1)
8363 +                       // FIXME accept the surrogate code points (only)
8364 +                       } else
8365 +                               goto fail;
8366 +               } else
8367 +                       uchar = c;
8368 +               put_unaligned (cpu_to_le16 (uchar), cp++);
8369 +               count++;
8370 +               len--;
8371 +       }
8372 +       return count;
8373 +fail:
8374 +       return -1;
8375 +}
8376 +
8377 +#endif /* DWC_UTFLIB */
8378 +
8379 +
8380 +/* dwc_debug.h */
8381 +
8382 +dwc_bool_t DWC_IN_IRQ(void)
8383 +{
8384 +//     return in_irq();
8385 +       return 0;
8386 +}
8387 +
8388 +dwc_bool_t DWC_IN_BH(void)
8389 +{
8390 +//     return in_softirq();
8391 +       return 0;
8392 +}
8393 +
8394 +void DWC_VPRINTF(char *format, va_list args)
8395 +{
8396 +       vprintf(format, args);
8397 +}
8398 +
8399 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
8400 +{
8401 +       return vsnprintf(str, size, format, args);
8402 +}
8403 +
8404 +void DWC_PRINTF(char *format, ...)
8405 +{
8406 +       va_list args;
8407 +
8408 +       va_start(args, format);
8409 +       DWC_VPRINTF(format, args);
8410 +       va_end(args);
8411 +}
8412 +
8413 +int DWC_SPRINTF(char *buffer, char *format, ...)
8414 +{
8415 +       int retval;
8416 +       va_list args;
8417 +
8418 +       va_start(args, format);
8419 +       retval = vsprintf(buffer, format, args);
8420 +       va_end(args);
8421 +       return retval;
8422 +}
8423 +
8424 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
8425 +{
8426 +       int retval;
8427 +       va_list args;
8428 +
8429 +       va_start(args, format);
8430 +       retval = vsnprintf(buffer, size, format, args);
8431 +       va_end(args);
8432 +       return retval;
8433 +}
8434 +
8435 +void __DWC_WARN(char *format, ...)
8436 +{
8437 +       va_list args;
8438 +
8439 +       va_start(args, format);
8440 +       DWC_VPRINTF(format, args);
8441 +       va_end(args);
8442 +}
8443 +
8444 +void __DWC_ERROR(char *format, ...)
8445 +{
8446 +       va_list args;
8447 +
8448 +       va_start(args, format);
8449 +       DWC_VPRINTF(format, args);
8450 +       va_end(args);
8451 +}
8452 +
8453 +void DWC_EXCEPTION(char *format, ...)
8454 +{
8455 +       va_list args;
8456 +
8457 +       va_start(args, format);
8458 +       DWC_VPRINTF(format, args);
8459 +       va_end(args);
8460 +//     BUG_ON(1);      ???
8461 +}
8462 +
8463 +#ifdef DEBUG
8464 +void __DWC_DEBUG(char *format, ...)
8465 +{
8466 +       va_list args;
8467 +
8468 +       va_start(args, format);
8469 +       DWC_VPRINTF(format, args);
8470 +       va_end(args);
8471 +}
8472 +#endif
8473 +
8474 +
8475 +/* dwc_mem.h */
8476 +
8477 +#if 0
8478 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
8479 +                               uint32_t align,
8480 +                               uint32_t alloc)
8481 +{
8482 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
8483 +                                               size, align, alloc);
8484 +       return (dwc_pool_t *)pool;
8485 +}
8486 +
8487 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
8488 +{
8489 +       dma_pool_destroy((struct dma_pool *)pool);
8490 +}
8491 +
8492 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8493 +{
8494 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
8495 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
8496 +}
8497 +
8498 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8499 +{
8500 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
8501 +       memset(..);
8502 +}
8503 +
8504 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
8505 +{
8506 +       dma_pool_free(pool, vaddr, daddr);
8507 +}
8508 +#endif
8509 +
8510 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
8511 +{
8512 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8513 +       int error;
8514 +
8515 +       error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,
8516 +                                sizeof(dma->segs) / sizeof(dma->segs[0]),
8517 +                                &dma->nsegs, BUS_DMA_NOWAIT);
8518 +       if (error) {
8519 +               printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,
8520 +                      (uintmax_t)size, error);
8521 +               goto fail_0;
8522 +       }
8523 +
8524 +       error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,
8525 +                              (caddr_t *)&dma->dma_vaddr,
8526 +                              BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
8527 +       if (error) {
8528 +               printf("%s: bus_dmamem_map failed: %d\n", __func__, error);
8529 +               goto fail_1;
8530 +       }
8531 +
8532 +       error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
8533 +                                 BUS_DMA_NOWAIT, &dma->dma_map);
8534 +       if (error) {
8535 +               printf("%s: bus_dmamap_create failed: %d\n", __func__, error);
8536 +               goto fail_2;
8537 +       }
8538 +
8539 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
8540 +                               size, NULL, BUS_DMA_NOWAIT);
8541 +       if (error) {
8542 +               printf("%s: bus_dmamap_load failed: %d\n", __func__, error);
8543 +               goto fail_3;
8544 +       }
8545 +
8546 +       dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;
8547 +       *dma_addr = dma->dma_paddr;
8548 +       return dma->dma_vaddr;
8549 +
8550 +fail_3:
8551 +       bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8552 +fail_2:
8553 +       bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8554 +fail_1:
8555 +       bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8556 +fail_0:
8557 +       dma->dma_map = NULL;
8558 +       dma->dma_vaddr = NULL;
8559 +       dma->nsegs = 0;
8560 +
8561 +       return NULL;
8562 +}
8563 +
8564 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
8565 +{
8566 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8567 +
8568 +       if (dma->dma_map != NULL) {
8569 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,
8570 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
8571 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
8572 +               bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8573 +               bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8574 +               bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8575 +               dma->dma_paddr = 0;
8576 +               dma->dma_map = NULL;
8577 +               dma->dma_vaddr = NULL;
8578 +               dma->nsegs = 0;
8579 +       }
8580 +}
8581 +
8582 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
8583 +{
8584 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
8585 +}
8586 +
8587 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
8588 +{
8589 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
8590 +}
8591 +
8592 +void __DWC_FREE(void *mem_ctx, void *addr)
8593 +{
8594 +       free(addr, M_DEVBUF);
8595 +}
8596 +
8597 +
8598 +#ifdef DWC_CRYPTOLIB
8599 +/* dwc_crypto.h */
8600 +
8601 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
8602 +{
8603 +       get_random_bytes(buffer, length);
8604 +}
8605 +
8606 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
8607 +{
8608 +       struct crypto_blkcipher *tfm;
8609 +       struct blkcipher_desc desc;
8610 +       struct scatterlist sgd;
8611 +       struct scatterlist sgs;
8612 +
8613 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
8614 +       if (tfm == NULL) {
8615 +               printk("failed to load transform for aes CBC\n");
8616 +               return -1;
8617 +       }
8618 +
8619 +       crypto_blkcipher_setkey(tfm, key, keylen);
8620 +       crypto_blkcipher_set_iv(tfm, iv, 16);
8621 +
8622 +       sg_init_one(&sgd, out, messagelen);
8623 +       sg_init_one(&sgs, message, messagelen);
8624 +
8625 +       desc.tfm = tfm;
8626 +       desc.flags = 0;
8627 +
8628 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
8629 +               crypto_free_blkcipher(tfm);
8630 +               DWC_ERROR("AES CBC encryption failed");
8631 +               return -1;
8632 +       }
8633 +
8634 +       crypto_free_blkcipher(tfm);
8635 +       return 0;
8636 +}
8637 +
8638 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
8639 +{
8640 +       struct crypto_hash *tfm;
8641 +       struct hash_desc desc;
8642 +       struct scatterlist sg;
8643 +
8644 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
8645 +       if (IS_ERR(tfm)) {
8646 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
8647 +               return 0;
8648 +       }
8649 +       desc.tfm = tfm;
8650 +       desc.flags = 0;
8651 +
8652 +       sg_init_one(&sg, message, len);
8653 +       crypto_hash_digest(&desc, &sg, len, out);
8654 +       crypto_free_hash(tfm);
8655 +
8656 +       return 1;
8657 +}
8658 +
8659 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
8660 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
8661 +{
8662 +       struct crypto_hash *tfm;
8663 +       struct hash_desc desc;
8664 +       struct scatterlist sg;
8665 +
8666 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
8667 +       if (IS_ERR(tfm)) {
8668 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
8669 +               return 0;
8670 +       }
8671 +       desc.tfm = tfm;
8672 +       desc.flags = 0;
8673 +
8674 +       sg_init_one(&sg, message, messagelen);
8675 +       crypto_hash_setkey(tfm, key, keylen);
8676 +       crypto_hash_digest(&desc, &sg, messagelen, out);
8677 +       crypto_free_hash(tfm);
8678 +
8679 +       return 1;
8680 +}
8681 +
8682 +#endif /* DWC_CRYPTOLIB */
8683 +
8684 +
8685 +/* Byte Ordering Conversions */
8686 +
8687 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
8688 +{
8689 +#ifdef __LITTLE_ENDIAN
8690 +       return *p;
8691 +#else
8692 +       uint8_t *u_p = (uint8_t *)p;
8693 +
8694 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8695 +#endif
8696 +}
8697 +
8698 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
8699 +{
8700 +#ifdef __BIG_ENDIAN
8701 +       return *p;
8702 +#else
8703 +       uint8_t *u_p = (uint8_t *)p;
8704 +
8705 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8706 +#endif
8707 +}
8708 +
8709 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
8710 +{
8711 +#ifdef __LITTLE_ENDIAN
8712 +       return *p;
8713 +#else
8714 +       uint8_t *u_p = (uint8_t *)p;
8715 +
8716 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8717 +#endif
8718 +}
8719 +
8720 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
8721 +{
8722 +#ifdef __BIG_ENDIAN
8723 +       return *p;
8724 +#else
8725 +       uint8_t *u_p = (uint8_t *)p;
8726 +
8727 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8728 +#endif
8729 +}
8730 +
8731 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
8732 +{
8733 +#ifdef __LITTLE_ENDIAN
8734 +       return *p;
8735 +#else
8736 +       uint8_t *u_p = (uint8_t *)p;
8737 +       return (u_p[1] | (u_p[0] << 8));
8738 +#endif
8739 +}
8740 +
8741 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
8742 +{
8743 +#ifdef __BIG_ENDIAN
8744 +       return *p;
8745 +#else
8746 +       uint8_t *u_p = (uint8_t *)p;
8747 +       return (u_p[1] | (u_p[0] << 8));
8748 +#endif
8749 +}
8750 +
8751 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
8752 +{
8753 +#ifdef __LITTLE_ENDIAN
8754 +       return *p;
8755 +#else
8756 +       uint8_t *u_p = (uint8_t *)p;
8757 +       return (u_p[1] | (u_p[0] << 8));
8758 +#endif
8759 +}
8760 +
8761 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
8762 +{
8763 +#ifdef __BIG_ENDIAN
8764 +       return *p;
8765 +#else
8766 +       uint8_t *u_p = (uint8_t *)p;
8767 +       return (u_p[1] | (u_p[0] << 8));
8768 +#endif
8769 +}
8770 +
8771 +
8772 +/* Registers */
8773 +
8774 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
8775 +{
8776 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8777 +       bus_size_t ior = (bus_size_t)reg;
8778 +
8779 +       return bus_space_read_4(io->iot, io->ioh, ior);
8780 +}
8781 +
8782 +#if 0
8783 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
8784 +{
8785 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8786 +       bus_size_t ior = (bus_size_t)reg;
8787 +
8788 +       return bus_space_read_8(io->iot, io->ioh, ior);
8789 +}
8790 +#endif
8791 +
8792 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
8793 +{
8794 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8795 +       bus_size_t ior = (bus_size_t)reg;
8796 +
8797 +       bus_space_write_4(io->iot, io->ioh, ior, value);
8798 +}
8799 +
8800 +#if 0
8801 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
8802 +{
8803 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8804 +       bus_size_t ior = (bus_size_t)reg;
8805 +
8806 +       bus_space_write_8(io->iot, io->ioh, ior, value);
8807 +}
8808 +#endif
8809 +
8810 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
8811 +                     uint32_t set_mask)
8812 +{
8813 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8814 +       bus_size_t ior = (bus_size_t)reg;
8815 +
8816 +       bus_space_write_4(io->iot, io->ioh, ior,
8817 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
8818 +                          ~clear_mask) | set_mask);
8819 +}
8820 +
8821 +#if 0
8822 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
8823 +                     uint64_t set_mask)
8824 +{
8825 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8826 +       bus_size_t ior = (bus_size_t)reg;
8827 +
8828 +       bus_space_write_8(io->iot, io->ioh, ior,
8829 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
8830 +                          ~clear_mask) | set_mask);
8831 +}
8832 +#endif
8833 +
8834 +
8835 +/* Locking */
8836 +
8837 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
8838 +{
8839 +       struct simplelock *sl = DWC_ALLOC(sizeof(*sl));
8840 +
8841 +       if (!sl) {
8842 +               DWC_ERROR("Cannot allocate memory for spinlock");
8843 +               return NULL;
8844 +       }
8845 +
8846 +       simple_lock_init(sl);
8847 +       return (dwc_spinlock_t *)sl;
8848 +}
8849 +
8850 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
8851 +{
8852 +       struct simplelock *sl = (struct simplelock *)lock;
8853 +
8854 +       DWC_FREE(sl);
8855 +}
8856 +
8857 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
8858 +{
8859 +       simple_lock((struct simplelock *)lock);
8860 +}
8861 +
8862 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
8863 +{
8864 +       simple_unlock((struct simplelock *)lock);
8865 +}
8866 +
8867 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
8868 +{
8869 +       simple_lock((struct simplelock *)lock);
8870 +       *flags = splbio();
8871 +}
8872 +
8873 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
8874 +{
8875 +       splx(flags);
8876 +       simple_unlock((struct simplelock *)lock);
8877 +}
8878 +
8879 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
8880 +{
8881 +       dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));
8882 +
8883 +       if (!mutex) {
8884 +               DWC_ERROR("Cannot allocate memory for mutex");
8885 +               return NULL;
8886 +       }
8887 +
8888 +       lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);
8889 +       return mutex;
8890 +}
8891 +
8892 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
8893 +#else
8894 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
8895 +{
8896 +       DWC_FREE(mutex);
8897 +}
8898 +#endif
8899 +
8900 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
8901 +{
8902 +       lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);
8903 +}
8904 +
8905 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
8906 +{
8907 +       int status;
8908 +
8909 +       status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);
8910 +       return status == 0;
8911 +}
8912 +
8913 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
8914 +{
8915 +       lockmgr((struct lock *)mutex, LK_RELEASE, NULL);
8916 +}
8917 +
8918 +
8919 +/* Timing */
8920 +
8921 +void DWC_UDELAY(uint32_t usecs)
8922 +{
8923 +       DELAY(usecs);
8924 +}
8925 +
8926 +void DWC_MDELAY(uint32_t msecs)
8927 +{
8928 +       do {
8929 +               DELAY(1000);
8930 +       } while (--msecs);
8931 +}
8932 +
8933 +void DWC_MSLEEP(uint32_t msecs)
8934 +{
8935 +       struct timeval tv;
8936 +
8937 +       tv.tv_sec = msecs / 1000;
8938 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
8939 +       tsleep(&tv, 0, "dw3slp", tvtohz(&tv));
8940 +}
8941 +
8942 +uint32_t DWC_TIME(void)
8943 +{
8944 +       struct timeval tv;
8945 +
8946 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
8947 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
8948 +}
8949 +
8950 +
8951 +/* Timers */
8952 +
8953 +struct dwc_timer {
8954 +       struct callout t;
8955 +       char *name;
8956 +       dwc_spinlock_t *lock;
8957 +       dwc_timer_callback_t cb;
8958 +       void *data;
8959 +};
8960 +
8961 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
8962 +{
8963 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
8964 +
8965 +       if (!t) {
8966 +               DWC_ERROR("Cannot allocate memory for timer");
8967 +               return NULL;
8968 +       }
8969 +
8970 +       callout_init(&t->t);
8971 +
8972 +       t->name = DWC_STRDUP(name);
8973 +       if (!t->name) {
8974 +               DWC_ERROR("Cannot allocate memory for timer->name");
8975 +               goto no_name;
8976 +       }
8977 +
8978 +       t->lock = DWC_SPINLOCK_ALLOC();
8979 +       if (!t->lock) {
8980 +               DWC_ERROR("Cannot allocate memory for timer->lock");
8981 +               goto no_lock;
8982 +       }
8983 +
8984 +       t->cb = cb;
8985 +       t->data = data;
8986 +
8987 +       return t;
8988 +
8989 + no_lock:
8990 +       DWC_FREE(t->name);
8991 + no_name:
8992 +       DWC_FREE(t);
8993 +
8994 +       return NULL;
8995 +}
8996 +
8997 +void DWC_TIMER_FREE(dwc_timer_t *timer)
8998 +{
8999 +       callout_stop(&timer->t);
9000 +       DWC_SPINLOCK_FREE(timer->lock);
9001 +       DWC_FREE(timer->name);
9002 +       DWC_FREE(timer);
9003 +}
9004 +
9005 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
9006 +{
9007 +       struct timeval tv;
9008 +
9009 +       tv.tv_sec = time / 1000;
9010 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9011 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
9012 +}
9013 +
9014 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
9015 +{
9016 +       callout_stop(&timer->t);
9017 +}
9018 +
9019 +
9020 +/* Wait Queues */
9021 +
9022 +struct dwc_waitq {
9023 +       struct simplelock lock;
9024 +       int abort;
9025 +};
9026 +
9027 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
9028 +{
9029 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
9030 +
9031 +       if (!wq) {
9032 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9033 +               return NULL;
9034 +       }
9035 +
9036 +       simple_lock_init(&wq->lock);
9037 +       wq->abort = 0;
9038 +
9039 +       return wq;
9040 +}
9041 +
9042 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
9043 +{
9044 +       DWC_FREE(wq);
9045 +}
9046 +
9047 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
9048 +{
9049 +       int ipl;
9050 +       int result = 0;
9051 +
9052 +       simple_lock(&wq->lock);
9053 +       ipl = splbio();
9054 +
9055 +       /* Skip the sleep if already aborted or triggered */
9056 +       if (!wq->abort && !cond(data)) {
9057 +               splx(ipl);
9058 +               result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout
9059 +               ipl = splbio();
9060 +       }
9061 +
9062 +       if (result == 0) {                      // awoken
9063 +               if (wq->abort) {
9064 +                       wq->abort = 0;
9065 +                       result = -DWC_E_ABORT;
9066 +               } else {
9067 +                       result = 0;
9068 +               }
9069 +
9070 +               splx(ipl);
9071 +               simple_unlock(&wq->lock);
9072 +       } else {
9073 +               wq->abort = 0;
9074 +               splx(ipl);
9075 +               simple_unlock(&wq->lock);
9076 +
9077 +               if (result == ERESTART) {       // signaled - restart
9078 +                       result = -DWC_E_RESTART;
9079 +               } else {                        // signaled - must be EINTR
9080 +                       result = -DWC_E_ABORT;
9081 +               }
9082 +       }
9083 +
9084 +       return result;
9085 +}
9086 +
9087 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
9088 +                              void *data, int32_t msecs)
9089 +{
9090 +       struct timeval tv, tv1, tv2;
9091 +       int ipl;
9092 +       int result = 0;
9093 +
9094 +       tv.tv_sec = msecs / 1000;
9095 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
9096 +
9097 +       simple_lock(&wq->lock);
9098 +       ipl = splbio();
9099 +
9100 +       /* Skip the sleep if already aborted or triggered */
9101 +       if (!wq->abort && !cond(data)) {
9102 +               splx(ipl);
9103 +               getmicrouptime(&tv1);
9104 +               result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);
9105 +               getmicrouptime(&tv2);
9106 +               ipl = splbio();
9107 +       }
9108 +
9109 +       if (result == 0) {                      // awoken
9110 +               if (wq->abort) {
9111 +                       wq->abort = 0;
9112 +                       splx(ipl);
9113 +                       simple_unlock(&wq->lock);
9114 +                       result = -DWC_E_ABORT;
9115 +               } else {
9116 +                       splx(ipl);
9117 +                       simple_unlock(&wq->lock);
9118 +
9119 +                       tv2.tv_usec -= tv1.tv_usec;
9120 +                       if (tv2.tv_usec < 0) {
9121 +                               tv2.tv_usec += 1000000;
9122 +                               tv2.tv_sec--;
9123 +                       }
9124 +
9125 +                       tv2.tv_sec -= tv1.tv_sec;
9126 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
9127 +                       result = msecs - result;
9128 +                       if (result <= 0)
9129 +                               result = 1;
9130 +               }
9131 +       } else {
9132 +               wq->abort = 0;
9133 +               splx(ipl);
9134 +               simple_unlock(&wq->lock);
9135 +
9136 +               if (result == ERESTART) {       // signaled - restart
9137 +                       result = -DWC_E_RESTART;
9138 +
9139 +               } else if (result == EINTR) {           // signaled - interrupt
9140 +                       result = -DWC_E_ABORT;
9141 +
9142 +               } else {                                // timed out
9143 +                       result = -DWC_E_TIMEOUT;
9144 +               }
9145 +       }
9146 +
9147 +       return result;
9148 +}
9149 +
9150 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
9151 +{
9152 +       wakeup(wq);
9153 +}
9154 +
9155 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
9156 +{
9157 +       int ipl;
9158 +
9159 +       simple_lock(&wq->lock);
9160 +       ipl = splbio();
9161 +       wq->abort = 1;
9162 +       wakeup(wq);
9163 +       splx(ipl);
9164 +       simple_unlock(&wq->lock);
9165 +}
9166 +
9167 +
9168 +/* Threading */
9169 +
9170 +struct dwc_thread {
9171 +       struct proc *proc;
9172 +       int abort;
9173 +};
9174 +
9175 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
9176 +{
9177 +       int retval;
9178 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
9179 +
9180 +       if (!thread) {
9181 +               return NULL;
9182 +       }
9183 +
9184 +       thread->abort = 0;
9185 +       retval = kthread_create1((void (*)(void *))func, data, &thread->proc,
9186 +                                "%s", name);
9187 +       if (retval) {
9188 +               DWC_FREE(thread);
9189 +               return NULL;
9190 +       }
9191 +
9192 +       return thread;
9193 +}
9194 +
9195 +int DWC_THREAD_STOP(dwc_thread_t *thread)
9196 +{
9197 +       int retval;
9198 +
9199 +       thread->abort = 1;
9200 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
9201 +
9202 +       if (retval == 0) {
9203 +               /* DWC_THREAD_EXIT() will free the thread struct */
9204 +               return 0;
9205 +       }
9206 +
9207 +       /* NOTE: We leak the thread struct if thread doesn't die */
9208 +
9209 +       if (retval == EWOULDBLOCK) {
9210 +               return -DWC_E_TIMEOUT;
9211 +       }
9212 +
9213 +       return -DWC_E_UNKNOWN;
9214 +}
9215 +
9216 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
9217 +{
9218 +       return thread->abort;
9219 +}
9220 +
9221 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
9222 +{
9223 +       wakeup(&thread->abort);
9224 +       DWC_FREE(thread);
9225 +       kthread_exit(0);
9226 +}
9227 +
9228 +/* tasklets
9229 + - Runs in interrupt context (cannot sleep)
9230 + - Each tasklet runs on a single CPU
9231 + - Different tasklets can be running simultaneously on different CPUs
9232 + [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-
9233 +   halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]
9234 + */
9235 +struct dwc_tasklet {
9236 +       dwc_tasklet_callback_t cb;
9237 +       void *data;
9238 +};
9239 +
9240 +static void tasklet_callback(void *data)
9241 +{
9242 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
9243 +
9244 +       task->cb(task->data);
9245 +}
9246 +
9247 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
9248 +{
9249 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
9250 +
9251 +       if (task) {
9252 +               task->cb = cb;
9253 +               task->data = data;
9254 +       } else {
9255 +               DWC_ERROR("Cannot allocate memory for tasklet");
9256 +       }
9257 +
9258 +       return task;
9259 +}
9260 +
9261 +void DWC_TASK_FREE(dwc_tasklet_t *task)
9262 +{
9263 +       DWC_FREE(task);
9264 +}
9265 +
9266 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
9267 +{
9268 +       tasklet_callback(task);
9269 +}
9270 +
9271 +
9272 +/* workqueues
9273 + - Runs in process context (can sleep)
9274 + */
9275 +typedef struct work_container {
9276 +       dwc_work_callback_t cb;
9277 +       void *data;
9278 +       dwc_workq_t *wq;
9279 +       char *name;
9280 +       int hz;
9281 +       struct work task;
9282 +} work_container_t;
9283 +
9284 +struct dwc_workq {
9285 +       struct workqueue *taskq;
9286 +       dwc_spinlock_t *lock;
9287 +       dwc_waitq_t *waitq;
9288 +       int pending;
9289 +       struct work_container *container;
9290 +};
9291 +
9292 +static void do_work(struct work *task, void *data)
9293 +{
9294 +       dwc_workq_t *wq = (dwc_workq_t *)data;
9295 +       work_container_t *container = wq->container;
9296 +       dwc_irqflags_t flags;
9297 +
9298 +       if (container->hz) {
9299 +               tsleep(container, 0, "dw3wrk", container->hz);
9300 +       }
9301 +
9302 +       container->cb(container->data);
9303 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
9304 +
9305 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9306 +       if (container->name)
9307 +               DWC_FREE(container->name);
9308 +       DWC_FREE(container);
9309 +       wq->pending--;
9310 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9311 +       DWC_WAITQ_TRIGGER(wq->waitq);
9312 +}
9313 +
9314 +static int work_done(void *data)
9315 +{
9316 +       dwc_workq_t *workq = (dwc_workq_t *)data;
9317 +
9318 +       return workq->pending == 0;
9319 +}
9320 +
9321 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
9322 +{
9323 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
9324 +}
9325 +
9326 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
9327 +{
9328 +       int result;
9329 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
9330 +
9331 +       if (!wq) {
9332 +               DWC_ERROR("Cannot allocate memory for workqueue");
9333 +               return NULL;
9334 +       }
9335 +
9336 +       result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,
9337 +                                 IPL_BIO, 0);
9338 +       if (result) {
9339 +               DWC_ERROR("Cannot create workqueue");
9340 +               goto no_taskq;
9341 +       }
9342 +
9343 +       wq->pending = 0;
9344 +
9345 +       wq->lock = DWC_SPINLOCK_ALLOC();
9346 +       if (!wq->lock) {
9347 +               DWC_ERROR("Cannot allocate memory for spinlock");
9348 +               goto no_lock;
9349 +       }
9350 +
9351 +       wq->waitq = DWC_WAITQ_ALLOC();
9352 +       if (!wq->waitq) {
9353 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9354 +               goto no_waitq;
9355 +       }
9356 +
9357 +       return wq;
9358 +
9359 + no_waitq:
9360 +       DWC_SPINLOCK_FREE(wq->lock);
9361 + no_lock:
9362 +       workqueue_destroy(wq->taskq);
9363 + no_taskq:
9364 +       DWC_FREE(wq);
9365 +
9366 +       return NULL;
9367 +}
9368 +
9369 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
9370 +{
9371 +#ifdef DEBUG
9372 +       dwc_irqflags_t flags;
9373 +
9374 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9375 +
9376 +       if (wq->pending != 0) {
9377 +               struct work_container *container = wq->container;
9378 +
9379 +               DWC_ERROR("Destroying work queue with pending work");
9380 +
9381 +               if (container && container->name) {
9382 +                       DWC_ERROR("Work %s still pending", container->name);
9383 +               }
9384 +       }
9385 +
9386 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9387 +#endif
9388 +       DWC_WAITQ_FREE(wq->waitq);
9389 +       DWC_SPINLOCK_FREE(wq->lock);
9390 +       workqueue_destroy(wq->taskq);
9391 +       DWC_FREE(wq);
9392 +}
9393 +
9394 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
9395 +                       char *format, ...)
9396 +{
9397 +       dwc_irqflags_t flags;
9398 +       work_container_t *container;
9399 +       static char name[128];
9400 +       va_list args;
9401 +
9402 +       va_start(args, format);
9403 +       DWC_VSNPRINTF(name, 128, format, args);
9404 +       va_end(args);
9405 +
9406 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9407 +       wq->pending++;
9408 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9409 +       DWC_WAITQ_TRIGGER(wq->waitq);
9410 +
9411 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9412 +       if (!container) {
9413 +               DWC_ERROR("Cannot allocate memory for container");
9414 +               return;
9415 +       }
9416 +
9417 +       container->name = DWC_STRDUP(name);
9418 +       if (!container->name) {
9419 +               DWC_ERROR("Cannot allocate memory for container->name");
9420 +               DWC_FREE(container);
9421 +               return;
9422 +       }
9423 +
9424 +       container->cb = cb;
9425 +       container->data = data;
9426 +       container->wq = wq;
9427 +       container->hz = 0;
9428 +       wq->container = container;
9429 +
9430 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9431 +       workqueue_enqueue(wq->taskq, &container->task);
9432 +}
9433 +
9434 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
9435 +                               void *data, uint32_t time, char *format, ...)
9436 +{
9437 +       dwc_irqflags_t flags;
9438 +       work_container_t *container;
9439 +       static char name[128];
9440 +       struct timeval tv;
9441 +       va_list args;
9442 +
9443 +       va_start(args, format);
9444 +       DWC_VSNPRINTF(name, 128, format, args);
9445 +       va_end(args);
9446 +
9447 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9448 +       wq->pending++;
9449 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9450 +       DWC_WAITQ_TRIGGER(wq->waitq);
9451 +
9452 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9453 +       if (!container) {
9454 +               DWC_ERROR("Cannot allocate memory for container");
9455 +               return;
9456 +       }
9457 +
9458 +       container->name = DWC_STRDUP(name);
9459 +       if (!container->name) {
9460 +               DWC_ERROR("Cannot allocate memory for container->name");
9461 +               DWC_FREE(container);
9462 +               return;
9463 +       }
9464 +
9465 +       container->cb = cb;
9466 +       container->data = data;
9467 +       container->wq = wq;
9468 +       tv.tv_sec = time / 1000;
9469 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9470 +       container->hz = tvtohz(&tv);
9471 +       wq->container = container;
9472 +
9473 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9474 +       workqueue_enqueue(wq->taskq, &container->task);
9475 +}
9476 +
9477 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
9478 +{
9479 +       return wq->pending;
9480 +}
9481 --- /dev/null
9482 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
9483 @@ -0,0 +1,308 @@
9484 +/* =========================================================================
9485 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
9486 + * $Revision: #5 $
9487 + * $Date: 2010/09/28 $
9488 + * $Change: 1596182 $
9489 + *
9490 + * Synopsys Portability Library Software and documentation
9491 + * (hereinafter, "Software") is an Unsupported proprietary work of
9492 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9493 + * between Synopsys and you.
9494 + *
9495 + * The Software IS NOT an item of Licensed Software or Licensed Product
9496 + * under any End User Software License Agreement or Agreement for
9497 + * Licensed Product with Synopsys or any supplement thereto. You are
9498 + * permitted to use and redistribute this Software in source and binary
9499 + * forms, with or without modification, provided that redistributions
9500 + * of source code must retain this notice. You may not view, use,
9501 + * disclose, copy or distribute this file or any information contained
9502 + * herein except pursuant to this license grant from Synopsys. If you
9503 + * do not agree with this notice, including the disclaimer below, then
9504 + * you are not authorized to use the Software.
9505 + *
9506 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9507 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9508 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9509 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9510 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9511 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9512 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9513 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9514 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9515 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9516 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9517 + * DAMAGE.
9518 + * ========================================================================= */
9519 +
9520 +/** @file
9521 + * This file contains the WUSB cryptographic routines.
9522 + */
9523 +
9524 +#ifdef DWC_CRYPTOLIB
9525 +
9526 +#include "dwc_crypto.h"
9527 +#include "usb.h"
9528 +
9529 +#ifdef DEBUG
9530 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
9531 +{
9532 +       int i;
9533 +       DWC_PRINTF("%s: ", name);
9534 +       for (i=0; i<len; i++) {
9535 +               DWC_PRINTF("%02x ", bytes[i]);
9536 +       }
9537 +       DWC_PRINTF("\n");
9538 +}
9539 +#else
9540 +#define dump_bytes(x...)
9541 +#endif
9542 +
9543 +/* Display a block */
9544 +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
9545 +{
9546 +#ifdef DWC_DEBUG_CRYPTO
9547 +       int i, blksize = 16;
9548 +
9549 +       DWC_DEBUG("%s", prefix);
9550 +
9551 +       if (suffix == NULL) {
9552 +               suffix = "\n";
9553 +               blksize = a;
9554 +       }
9555 +
9556 +       for (i = 0; i < blksize; i++)
9557 +               DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
9558 +       DWC_PRINT(suffix);
9559 +#endif
9560 +}
9561 +
9562 +/**
9563 + * Encrypts an array of bytes using the AES encryption engine.
9564 + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
9565 + * in-place.
9566 + *
9567 + * @return  0 on success, negative error code on error.
9568 + */
9569 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
9570 +{
9571 +       u8 block_t[16];
9572 +       DWC_MEMSET(block_t, 0, 16);
9573 +
9574 +       return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
9575 +}
9576 +
9577 +/**
9578 + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
9579 + * This function takes a data string and returns the encrypted CBC
9580 + * Counter-mode MIC.
9581 + *
9582 + * @param key     The 128-bit symmetric key.
9583 + * @param nonce   The CCM nonce.
9584 + * @param label   The unique 14-byte ASCII text label.
9585 + * @param bytes   The byte array to be encrypted.
9586 + * @param len     Length of the byte array.
9587 + * @param result  Byte array to receive the 8-byte encrypted MIC.
9588 + */
9589 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9590 +                 char *label, u8 *bytes, int len, u8 *result)
9591 +{
9592 +       u8 block_m[16];
9593 +       u8 block_x[16];
9594 +       u8 block_t[8];
9595 +       int idx, blkNum;
9596 +       u16 la = (u16)(len + 14);
9597 +
9598 +       /* Set the AES-128 key */
9599 +       //dwc_aes_setkey(tfm, key, 16);
9600 +
9601 +       /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
9602 +       block_m[0] = 0x59;
9603 +       for (idx = 0; idx < 13; idx++)
9604 +               block_m[idx + 1] = nonce[idx];
9605 +       block_m[14] = 0;
9606 +       block_m[15] = 0;
9607 +
9608 +       /* Produce the CBC IV */
9609 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9610 +       show_block(block_m, "CBC IV in: ", "\n", 0);
9611 +       show_block(block_x, "CBC IV out:", "\n", 0);
9612 +
9613 +       /* Fill block B1 from l(a) = Blen + 14, and A */
9614 +       block_x[0] ^= (u8)(la >> 8);
9615 +       block_x[1] ^= (u8)la;
9616 +       for (idx = 0; idx < 14; idx++)
9617 +               block_x[idx + 2] ^= label[idx];
9618 +       show_block(block_x, "After xor: ", "b1\n", 16);
9619 +
9620 +       dwc_wusb_aes_encrypt(block_x, key, block_x);
9621 +       show_block(block_x, "After AES: ", "b1\n", 16);
9622 +
9623 +       idx = 0;
9624 +       blkNum = 0;
9625 +
9626 +       /* Fill remaining blocks with B */
9627 +       while (len-- > 0) {
9628 +               block_x[idx] ^= *bytes++;
9629 +               if (++idx >= 16) {
9630 +                       idx = 0;
9631 +                       show_block(block_x, "After xor: ", "\n", blkNum);
9632 +                       dwc_wusb_aes_encrypt(block_x, key, block_x);
9633 +                       show_block(block_x, "After AES: ", "\n", blkNum);
9634 +                       blkNum++;
9635 +               }
9636 +       }
9637 +
9638 +       /* Handle partial last block */
9639 +       if (idx > 0) {
9640 +               show_block(block_x, "After xor: ", "\n", blkNum);
9641 +               dwc_wusb_aes_encrypt(block_x, key, block_x);
9642 +               show_block(block_x, "After AES: ", "\n", blkNum);
9643 +       }
9644 +
9645 +       /* Save the MIC tag */
9646 +       DWC_MEMCPY(block_t, block_x, 8);
9647 +       show_block(block_t, "MIC tag  : ", NULL, 8);
9648 +
9649 +       /* Fill block A0 from flags = 0x01, N, and counter = 0 */
9650 +       block_m[0] = 0x01;
9651 +       block_m[14] = 0;
9652 +       block_m[15] = 0;
9653 +
9654 +       /* Encrypt the counter */
9655 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9656 +       show_block(block_x, "CTR[MIC] : ", NULL, 8);
9657 +
9658 +       /* XOR with MIC tag */
9659 +       for (idx = 0; idx < 8; idx++) {
9660 +               block_t[idx] ^= block_x[idx];
9661 +       }
9662 +
9663 +       /* Return result to caller */
9664 +       DWC_MEMCPY(result, block_t, 8);
9665 +       show_block(result, "CCM-MIC  : ", NULL, 8);
9666 +
9667 +}
9668 +
9669 +/**
9670 + * The PRF function described in section 6.5 of the WUSB spec. This function
9671 + * concatenates MIC values returned from dwc_cmf() to create a value of
9672 + * the requested length.
9673 + *
9674 + * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
9675 + * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
9676 + * @param result   Byte array to receive the result.
9677 + */
9678 +void dwc_wusb_prf(int prf_len, u8 *key,
9679 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
9680 +{
9681 +       int i;
9682 +
9683 +       nonce[0] = 0;
9684 +       for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
9685 +               dwc_wusb_cmf(key, nonce, label, bytes, len, result);
9686 +               result += 8;
9687 +       }
9688 +}
9689 +
9690 +/**
9691 + * Fills in CCM Nonce per the WUSB spec.
9692 + *
9693 + * @param[in] haddr Host address.
9694 + * @param[in] daddr Device address.
9695 + * @param[in] tkid Session Key(PTK) identifier.
9696 + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
9697 + */
9698 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9699 +                            uint8_t *nonce)
9700 +{
9701 +
9702 +       DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
9703 +
9704 +       DWC_MEMSET(&nonce[0], 0, 16);
9705 +
9706 +       DWC_MEMCPY(&nonce[6], tkid, 3);
9707 +       nonce[9] = daddr & 0xFF;
9708 +       nonce[10] = (daddr >> 8) & 0xFF;
9709 +       nonce[11] = haddr & 0xFF;
9710 +       nonce[12] = (haddr >> 8) & 0xFF;
9711 +
9712 +       dump_bytes("CCM nonce", nonce, 16);
9713 +}
9714 +
9715 +/**
9716 + * Generates a 16-byte cryptographic-grade random number for the Host/Device
9717 + * Nonce.
9718 + */
9719 +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
9720 +{
9721 +       uint8_t inonce[16];
9722 +       uint32_t temp[4];
9723 +
9724 +       /* Fill in the Nonce */
9725 +       DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
9726 +       inonce[9] = addr & 0xFF;
9727 +       inonce[10] = (addr >> 8) & 0xFF;
9728 +       inonce[11] = inonce[9];
9729 +       inonce[12] = inonce[10];
9730 +
9731 +       /* Collect "randomness samples" */
9732 +       DWC_RANDOM_BYTES((uint8_t *)temp, 16);
9733 +
9734 +       dwc_wusb_prf_128((uint8_t *)temp, nonce,
9735 +                        "Random Numbers", (uint8_t *)temp, sizeof(temp),
9736 +                        nonce);
9737 +}
9738 +
9739 +/**
9740 + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
9741 + * WUSB spec.
9742 + *
9743 + * @param[in] ccm_nonce Pointer to CCM Nonce.
9744 + * @param[in] mk Master Key to derive the session from
9745 + * @param[in] hnonce Pointer to Host Nonce.
9746 + * @param[in] dnonce Pointer to Device Nonce.
9747 + * @param[out] kck Pointer to where the KCK output is to be written.
9748 + * @param[out] ptk Pointer to where the PTK output is to be written.
9749 + */
9750 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
9751 +                     uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
9752 +{
9753 +       uint8_t idata[32];
9754 +       uint8_t odata[32];
9755 +
9756 +       dump_bytes("ck", mk, 16);
9757 +       dump_bytes("hnonce", hnonce, 16);
9758 +       dump_bytes("dnonce", dnonce, 16);
9759 +
9760 +       /* The data is the HNonce and DNonce concatenated */
9761 +       DWC_MEMCPY(&idata[0], hnonce, 16);
9762 +       DWC_MEMCPY(&idata[16], dnonce, 16);
9763 +
9764 +       dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
9765 +
9766 +       /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
9767 +       DWC_MEMCPY(kck, &odata[0], 16);
9768 +       DWC_MEMCPY(ptk, &odata[16], 16);
9769 +
9770 +       dump_bytes("kck", kck, 16);
9771 +       dump_bytes("ptk", ptk, 16);
9772 +}
9773 +
9774 +/**
9775 + * Generates the Message Integrity Code over the Handshake data per the
9776 + * WUSB spec.
9777 + *
9778 + * @param ccm_nonce Pointer to CCM Nonce.
9779 + * @param kck   Pointer to Key Confirmation Key.
9780 + * @param data  Pointer to Handshake data to be checked.
9781 + * @param mic   Pointer to where the MIC output is to be written.
9782 + */
9783 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
9784 +                     uint8_t *data, uint8_t *mic)
9785 +{
9786 +
9787 +       dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
9788 +                       data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
9789 +}
9790 +
9791 +#endif /* DWC_CRYPTOLIB */
9792 --- /dev/null
9793 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
9794 @@ -0,0 +1,111 @@
9795 +/* =========================================================================
9796 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
9797 + * $Revision: #3 $
9798 + * $Date: 2010/09/28 $
9799 + * $Change: 1596182 $
9800 + *
9801 + * Synopsys Portability Library Software and documentation
9802 + * (hereinafter, "Software") is an Unsupported proprietary work of
9803 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9804 + * between Synopsys and you.
9805 + *
9806 + * The Software IS NOT an item of Licensed Software or Licensed Product
9807 + * under any End User Software License Agreement or Agreement for
9808 + * Licensed Product with Synopsys or any supplement thereto. You are
9809 + * permitted to use and redistribute this Software in source and binary
9810 + * forms, with or without modification, provided that redistributions
9811 + * of source code must retain this notice. You may not view, use,
9812 + * disclose, copy or distribute this file or any information contained
9813 + * herein except pursuant to this license grant from Synopsys. If you
9814 + * do not agree with this notice, including the disclaimer below, then
9815 + * you are not authorized to use the Software.
9816 + *
9817 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9818 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9819 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9820 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9821 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9822 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9823 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9824 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9825 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9826 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9827 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9828 + * DAMAGE.
9829 + * ========================================================================= */
9830 +
9831 +#ifndef _DWC_CRYPTO_H_
9832 +#define _DWC_CRYPTO_H_
9833 +
9834 +#ifdef __cplusplus
9835 +extern "C" {
9836 +#endif
9837 +
9838 +/** @file
9839 + *
9840 + * This file contains declarations for the WUSB Cryptographic routines as
9841 + * defined in the WUSB spec.  They are only to be used internally by the DWC UWB
9842 + * modules.
9843 + */
9844 +
9845 +#include "dwc_os.h"
9846 +
9847 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
9848 +
9849 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9850 +                 char *label, u8 *bytes, int len, u8 *result);
9851 +void dwc_wusb_prf(int prf_len, u8 *key,
9852 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
9853 +
9854 +/**
9855 + * The PRF-64 function described in section 6.5 of the WUSB spec.
9856 + *
9857 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9858 + */
9859 +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
9860 +                                  char *label, u8 *bytes, int len, u8 *result)
9861 +{
9862 +       dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
9863 +}
9864 +
9865 +/**
9866 + * The PRF-128 function described in section 6.5 of the WUSB spec.
9867 + *
9868 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9869 + */
9870 +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
9871 +                                   char *label, u8 *bytes, int len, u8 *result)
9872 +{
9873 +       dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
9874 +}
9875 +
9876 +/**
9877 + * The PRF-256 function described in section 6.5 of the WUSB spec.
9878 + *
9879 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9880 + */
9881 +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
9882 +                                   char *label, u8 *bytes, int len, u8 *result)
9883 +{
9884 +       dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
9885 +}
9886 +
9887 +
9888 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9889 +                              uint8_t *nonce);
9890 +void dwc_wusb_gen_nonce(uint16_t addr,
9891 +                         uint8_t *nonce);
9892 +
9893 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
9894 +                       uint8_t *hnonce, uint8_t *dnonce,
9895 +                       uint8_t *kck, uint8_t *ptk);
9896 +
9897 +
9898 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
9899 +                       *kck, uint8_t *data, uint8_t *mic);
9900 +
9901 +#ifdef __cplusplus
9902 +}
9903 +#endif
9904 +
9905 +#endif /* _DWC_CRYPTO_H_ */
9906 --- /dev/null
9907 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
9908 @@ -0,0 +1,291 @@
9909 +/* =========================================================================
9910 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
9911 + * $Revision: #3 $
9912 + * $Date: 2010/09/28 $
9913 + * $Change: 1596182 $
9914 + *
9915 + * Synopsys Portability Library Software and documentation
9916 + * (hereinafter, "Software") is an Unsupported proprietary work of
9917 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9918 + * between Synopsys and you.
9919 + *
9920 + * The Software IS NOT an item of Licensed Software or Licensed Product
9921 + * under any End User Software License Agreement or Agreement for
9922 + * Licensed Product with Synopsys or any supplement thereto. You are
9923 + * permitted to use and redistribute this Software in source and binary
9924 + * forms, with or without modification, provided that redistributions
9925 + * of source code must retain this notice. You may not view, use,
9926 + * disclose, copy or distribute this file or any information contained
9927 + * herein except pursuant to this license grant from Synopsys. If you
9928 + * do not agree with this notice, including the disclaimer below, then
9929 + * you are not authorized to use the Software.
9930 + *
9931 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9932 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9933 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9934 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9935 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9936 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9937 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9938 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9939 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9940 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9941 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9942 + * DAMAGE.
9943 + * ========================================================================= */
9944 +#ifdef DWC_CRYPTOLIB
9945 +
9946 +#ifndef CONFIG_MACH_IPMATE
9947 +
9948 +#include "dwc_dh.h"
9949 +#include "dwc_modpow.h"
9950 +
9951 +#ifdef DEBUG
9952 +/* This function prints out a buffer in the format described in the Association
9953 + * Model specification. */
9954 +static void dh_dump(char *str, void *_num, int len)
9955 +{
9956 +       uint8_t *num = _num;
9957 +       int i;
9958 +       DWC_PRINTF("%s\n", str);
9959 +       for (i = 0; i < len; i ++) {
9960 +               DWC_PRINTF("%02x", num[i]);
9961 +               if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
9962 +               if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
9963 +       }
9964 +
9965 +       DWC_PRINTF("\n");
9966 +}
9967 +#else
9968 +#define dh_dump(_x...) do {; } while(0)
9969 +#endif
9970 +
9971 +/* Constant g value */
9972 +static __u32 dh_g[] = {
9973 +       0x02000000,
9974 +};
9975 +
9976 +/* Constant p value */
9977 +static __u32 dh_p[] = {
9978 +       0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
9979 +       0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
9980 +       0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
9981 +       0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
9982 +       0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
9983 +       0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
9984 +       0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
9985 +       0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
9986 +       0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
9987 +       0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
9988 +       0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
9989 +       0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
9990 +};
9991 +
9992 +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
9993 +{
9994 +       uint8_t *in = _in;
9995 +       uint8_t *out = _out;
9996 +       int i;
9997 +       for (i=0; i<len; i++) {
9998 +               out[i] = in[len-1-i];
9999 +       }
10000 +}
10001 +
10002 +/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
10003 + * big endian numbers of size len, in bytes.  Each len value must be a multiple
10004 + * of 4. */
10005 +int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10006 +                 void *exp, uint32_t exp_len,
10007 +                 void *mod, uint32_t mod_len,
10008 +                 void *out)
10009 +{
10010 +       /* modpow() takes little endian numbers.  AM uses big-endian.  This
10011 +        * function swaps bytes of numbers before passing onto modpow. */
10012 +
10013 +       int retval = 0;
10014 +       uint32_t *result;
10015 +
10016 +       uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
10017 +       uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
10018 +       uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
10019 +
10020 +       dh_swap_bytes(num, &bignum_num[1], num_len);
10021 +       bignum_num[0] = num_len / 4;
10022 +
10023 +       dh_swap_bytes(exp, &bignum_exp[1], exp_len);
10024 +       bignum_exp[0] = exp_len / 4;
10025 +
10026 +       dh_swap_bytes(mod, &bignum_mod[1], mod_len);
10027 +       bignum_mod[0] = mod_len / 4;
10028 +
10029 +       result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
10030 +       if (!result) {
10031 +               retval = -1;
10032 +               goto dh_modpow_nomem;
10033 +       }
10034 +
10035 +       dh_swap_bytes(&result[1], out, result[0] * 4);
10036 +       dwc_free(mem_ctx, result);
10037 +
10038 + dh_modpow_nomem:
10039 +       dwc_free(mem_ctx, bignum_num);
10040 +       dwc_free(mem_ctx, bignum_exp);
10041 +       dwc_free(mem_ctx, bignum_mod);
10042 +       return retval;
10043 +}
10044 +
10045 +
10046 +int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
10047 +{
10048 +       int retval;
10049 +       uint8_t m3[385];
10050 +
10051 +#ifndef DH_TEST_VECTORS
10052 +       DWC_RANDOM_BYTES(exp, 32);
10053 +#endif
10054 +
10055 +       /* Compute the pkd */
10056 +       if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
10057 +                                   exp, 32,
10058 +                                   dh_p, 384, pk))) {
10059 +               return retval;
10060 +       }
10061 +
10062 +       m3[384] = nd;
10063 +       DWC_MEMCPY(&m3[0], pk, 384);
10064 +       DWC_SHA256(m3, 385, hash);
10065 +
10066 +       dh_dump("PK", pk, 384);
10067 +       dh_dump("SHA-256(M3)", hash, 32);
10068 +       return 0;
10069 +}
10070 +
10071 +int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10072 +                      uint8_t *exp, int is_host,
10073 +                      char *dd, uint8_t *ck, uint8_t *kdk)
10074 +{
10075 +       int retval;
10076 +       uint8_t mv[784];
10077 +       uint8_t sha_result[32];
10078 +       uint8_t dhkey[384];
10079 +       uint8_t shared_secret[384];
10080 +       char *message;
10081 +       uint32_t vd;
10082 +
10083 +       uint8_t *pk;
10084 +
10085 +       if (is_host) {
10086 +               pk = pkd;
10087 +       }
10088 +       else {
10089 +               pk = pkh;
10090 +       }
10091 +
10092 +       if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
10093 +                                   exp, 32,
10094 +                                   dh_p, 384, shared_secret))) {
10095 +               return retval;
10096 +       }
10097 +       dh_dump("Shared Secret", shared_secret, 384);
10098 +
10099 +       DWC_SHA256(shared_secret, 384, dhkey);
10100 +       dh_dump("DHKEY", dhkey, 384);
10101 +
10102 +       DWC_MEMCPY(&mv[0], pkd, 384);
10103 +       DWC_MEMCPY(&mv[384], pkh, 384);
10104 +       DWC_MEMCPY(&mv[768], "displayed digest", 16);
10105 +       dh_dump("MV", mv, 784);
10106 +
10107 +       DWC_SHA256(mv, 784, sha_result);
10108 +       dh_dump("SHA-256(MV)", sha_result, 32);
10109 +       dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
10110 +
10111 +       dh_swap_bytes(sha_result, &vd, 4);
10112 +#ifdef DEBUG
10113 +       DWC_PRINTF("Vd (decimal) = %d\n", vd);
10114 +#endif
10115 +
10116 +       switch (nd) {
10117 +       case 2:
10118 +               vd = vd % 100;
10119 +               DWC_SPRINTF(dd, "%02d", vd);
10120 +               break;
10121 +       case 3:
10122 +               vd = vd % 1000;
10123 +               DWC_SPRINTF(dd, "%03d", vd);
10124 +               break;
10125 +       case 4:
10126 +               vd = vd % 10000;
10127 +               DWC_SPRINTF(dd, "%04d", vd);
10128 +               break;
10129 +       }
10130 +#ifdef DEBUG
10131 +       DWC_PRINTF("Display Digits: %s\n", dd);
10132 +#endif
10133 +
10134 +       message = "connection key";
10135 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10136 +       dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
10137 +       DWC_MEMCPY(ck, sha_result, 16);
10138 +
10139 +       message = "key derivation key";
10140 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10141 +       dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
10142 +       DWC_MEMCPY(kdk, sha_result, 32);
10143 +
10144 +       return 0;
10145 +}
10146 +
10147 +
10148 +#ifdef DH_TEST_VECTORS
10149 +
10150 +static __u8 dh_a[] = {
10151 +       0x44, 0x00, 0x51, 0xd6,
10152 +       0xf0, 0xb5, 0x5e, 0xa9,
10153 +       0x67, 0xab, 0x31, 0xc6,
10154 +       0x8a, 0x8b, 0x5e, 0x37,
10155 +       0xd9, 0x10, 0xda, 0xe0,
10156 +       0xe2, 0xd4, 0x59, 0xa4,
10157 +       0x86, 0x45, 0x9c, 0xaa,
10158 +       0xdf, 0x36, 0x75, 0x16,
10159 +};
10160 +
10161 +static __u8 dh_b[] = {
10162 +       0x5d, 0xae, 0xc7, 0x86,
10163 +       0x79, 0x80, 0xa3, 0x24,
10164 +       0x8c, 0xe3, 0x57, 0x8f,
10165 +       0xc7, 0x5f, 0x1b, 0x0f,
10166 +       0x2d, 0xf8, 0x9d, 0x30,
10167 +       0x6f, 0xa4, 0x52, 0xcd,
10168 +       0xe0, 0x7a, 0x04, 0x8a,
10169 +       0xde, 0xd9, 0x26, 0x56,
10170 +};
10171 +
10172 +void dwc_run_dh_test_vectors(void *mem_ctx)
10173 +{
10174 +       uint8_t pkd[384];
10175 +       uint8_t pkh[384];
10176 +       uint8_t hashd[32];
10177 +       uint8_t hashh[32];
10178 +       uint8_t ck[16];
10179 +       uint8_t kdk[32];
10180 +       char dd[5];
10181 +
10182 +       DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
10183 +
10184 +       /* compute the PKd and SHA-256(PKd || Nd) */
10185 +       DWC_PRINTF("Computing PKd\n");
10186 +       dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
10187 +
10188 +       /* compute the PKd and SHA-256(PKh || Nd) */
10189 +       DWC_PRINTF("Computing PKh\n");
10190 +       dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
10191 +
10192 +       /* compute the dhkey */
10193 +       dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
10194 +}
10195 +#endif /* DH_TEST_VECTORS */
10196 +
10197 +#endif /* !CONFIG_MACH_IPMATE */
10198 +
10199 +#endif /* DWC_CRYPTOLIB */
10200 --- /dev/null
10201 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
10202 @@ -0,0 +1,106 @@
10203 +/* =========================================================================
10204 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
10205 + * $Revision: #4 $
10206 + * $Date: 2010/09/28 $
10207 + * $Change: 1596182 $
10208 + *
10209 + * Synopsys Portability Library Software and documentation
10210 + * (hereinafter, "Software") is an Unsupported proprietary work of
10211 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
10212 + * between Synopsys and you.
10213 + *
10214 + * The Software IS NOT an item of Licensed Software or Licensed Product
10215 + * under any End User Software License Agreement or Agreement for
10216 + * Licensed Product with Synopsys or any supplement thereto. You are
10217 + * permitted to use and redistribute this Software in source and binary
10218 + * forms, with or without modification, provided that redistributions
10219 + * of source code must retain this notice. You may not view, use,
10220 + * disclose, copy or distribute this file or any information contained
10221 + * herein except pursuant to this license grant from Synopsys. If you
10222 + * do not agree with this notice, including the disclaimer below, then
10223 + * you are not authorized to use the Software.
10224 + *
10225 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
10226 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10227 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
10228 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
10229 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10230 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10231 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10232 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
10233 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10234 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
10235 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
10236 + * DAMAGE.
10237 + * ========================================================================= */
10238 +#ifndef _DWC_DH_H_
10239 +#define _DWC_DH_H_
10240 +
10241 +#ifdef __cplusplus
10242 +extern "C" {
10243 +#endif
10244 +
10245 +#include "dwc_os.h"
10246 +
10247 +/** @file
10248 + *
10249 + * This file defines the common functions on device and host for performing
10250 + * numeric association as defined in the WUSB spec.  They are only to be
10251 + * used internally by the DWC UWB modules. */
10252 +
10253 +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
10254 +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
10255 +                             uint8_t *key, uint32_t keylen,
10256 +                             uint8_t *out);
10257 +extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10258 +                        void *exp, uint32_t exp_len,
10259 +                        void *mod, uint32_t mod_len,
10260 +                        void *out);
10261 +
10262 +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
10263 + *
10264 + * PK = g^exp mod p.
10265 + *
10266 + * Input:
10267 + * Nd = Number of digits on the device.
10268 + *
10269 + * Output:
10270 + * exp = A 32-byte buffer to be filled with a randomly generated number.
10271 + *       used as either A or B.
10272 + * pk = A 384-byte buffer to be filled with the PKH or PKD.
10273 + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
10274 + */
10275 +extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
10276 +
10277 +/** Computes the DHKEY, and VD.
10278 + *
10279 + * If called from host, then it will comput DHKEY=PKD^exp % p.
10280 + * If called from device, then it will comput DHKEY=PKH^exp % p.
10281 + *
10282 + * Input:
10283 + * pkd = The PKD value.
10284 + * pkh = The PKH value.
10285 + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
10286 + * is_host = Set to non zero if a WUSB host is calling this function.
10287 + *
10288 + * Output:
10289 +
10290 + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
10291 + *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a
10292 + *      null termination character.  This buffer can be used directly for display.
10293 + * ck = A 16-byte buffer to be filled with the CK.
10294 + * kdk = A 32-byte buffer to be filled with the KDK.
10295 + */
10296 +extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10297 +                             uint8_t *exp, int is_host,
10298 +                             char *dd, uint8_t *ck, uint8_t *kdk);
10299 +
10300 +#ifdef DH_TEST_VECTORS
10301 +extern void dwc_run_dh_test_vectors(void);
10302 +#endif
10303 +
10304 +#ifdef __cplusplus
10305 +}
10306 +#endif
10307 +
10308 +#endif /* _DWC_DH_H_ */
10309 --- /dev/null
10310 +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
10311 @@ -0,0 +1,594 @@
10312 +/*     $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $       */
10313 +/*     $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $       */
10314 +
10315 +/*
10316 + * Copyright (c) 1991, 1993
10317 + *     The Regents of the University of California.  All rights reserved.
10318 + *
10319 + * Redistribution and use in source and binary forms, with or without
10320 + * modification, are permitted provided that the following conditions
10321 + * are met:
10322 + * 1. Redistributions of source code must retain the above copyright
10323 + *    notice, this list of conditions and the following disclaimer.
10324 + * 2. Redistributions in binary form must reproduce the above copyright
10325 + *    notice, this list of conditions and the following disclaimer in the
10326 + *    documentation and/or other materials provided with the distribution.
10327 + * 3. Neither the name of the University nor the names of its contributors
10328 + *    may be used to endorse or promote products derived from this software
10329 + *    without specific prior written permission.
10330 + *
10331 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
10332 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10333 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10334 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
10335 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10336 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10337 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10338 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10339 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10340 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10341 + * SUCH DAMAGE.
10342 + *
10343 + *     @(#)queue.h     8.5 (Berkeley) 8/20/94
10344 + */
10345 +
10346 +#ifndef _DWC_LIST_H_
10347 +#define _DWC_LIST_H_
10348 +
10349 +#ifdef __cplusplus
10350 +extern "C" {
10351 +#endif
10352 +
10353 +/** @file
10354 + *
10355 + * This file defines linked list operations.  It is derived from BSD with
10356 + * only the MACRO names being prefixed with DWC_.  This is because a few of
10357 + * these names conflict with those on Linux.  For documentation on use, see the
10358 + * inline comments in the source code.  The original license for this source
10359 + * code applies and is preserved in the dwc_list.h source file.
10360 + */
10361 +
10362 +/*
10363 + * This file defines five types of data structures: singly-linked lists,
10364 + * lists, simple queues, tail queues, and circular queues.
10365 + *
10366 + *
10367 + * A singly-linked list is headed by a single forward pointer. The elements
10368 + * are singly linked for minimum space and pointer manipulation overhead at
10369 + * the expense of O(n) removal for arbitrary elements. New elements can be
10370 + * added to the list after an existing element or at the head of the list.
10371 + * Elements being removed from the head of the list should use the explicit
10372 + * macro for this purpose for optimum efficiency. A singly-linked list may
10373 + * only be traversed in the forward direction.  Singly-linked lists are ideal
10374 + * for applications with large datasets and few or no removals or for
10375 + * implementing a LIFO queue.
10376 + *
10377 + * A list is headed by a single forward pointer (or an array of forward
10378 + * pointers for a hash table header). The elements are doubly linked
10379 + * so that an arbitrary element can be removed without a need to
10380 + * traverse the list. New elements can be added to the list before
10381 + * or after an existing element or at the head of the list. A list
10382 + * may only be traversed in the forward direction.
10383 + *
10384 + * A simple queue is headed by a pair of pointers, one the head of the
10385 + * list and the other to the tail of the list. The elements are singly
10386 + * linked to save space, so elements can only be removed from the
10387 + * head of the list. New elements can be added to the list before or after
10388 + * an existing element, at the head of the list, or at the end of the
10389 + * list. A simple queue may only be traversed in the forward direction.
10390 + *
10391 + * A tail queue is headed by a pair of pointers, one to the head of the
10392 + * list and the other to the tail of the list. The elements are doubly
10393 + * linked so that an arbitrary element can be removed without a need to
10394 + * traverse the list. New elements can be added to the list before or
10395 + * after an existing element, at the head of the list, or at the end of
10396 + * the list. A tail queue may be traversed in either direction.
10397 + *
10398 + * A circle queue is headed by a pair of pointers, one to the head of the
10399 + * list and the other to the tail of the list. The elements are doubly
10400 + * linked so that an arbitrary element can be removed without a need to
10401 + * traverse the list. New elements can be added to the list before or after
10402 + * an existing element, at the head of the list, or at the end of the list.
10403 + * A circle queue may be traversed in either direction, but has a more
10404 + * complex end of list detection.
10405 + *
10406 + * For details on the use of these macros, see the queue(3) manual page.
10407 + */
10408 +
10409 +/*
10410 + * Double-linked List.
10411 + */
10412 +
10413 +typedef struct dwc_list_link {
10414 +       struct dwc_list_link *next;
10415 +       struct dwc_list_link *prev;
10416 +} dwc_list_link_t;
10417 +
10418 +#define DWC_LIST_INIT(link) do {       \
10419 +       (link)->next = (link);          \
10420 +       (link)->prev = (link);          \
10421 +} while (0)
10422 +
10423 +#define DWC_LIST_FIRST(link)   ((link)->next)
10424 +#define DWC_LIST_LAST(link)    ((link)->prev)
10425 +#define DWC_LIST_END(link)     (link)
10426 +#define DWC_LIST_NEXT(link)    ((link)->next)
10427 +#define DWC_LIST_PREV(link)    ((link)->prev)
10428 +#define DWC_LIST_EMPTY(link)   \
10429 +       (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
10430 +#define DWC_LIST_ENTRY(link, type, field)                      \
10431 +       (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))
10432 +
10433 +#if 0
10434 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10435 +       (link)->next = (list)->next;                            \
10436 +       (link)->prev = (list);                                  \
10437 +       (list)->next->prev = (link);                            \
10438 +       (list)->next = (link);                                  \
10439 +} while (0)
10440 +
10441 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10442 +       (link)->next = (list);                                  \
10443 +       (link)->prev = (list)->prev;                            \
10444 +       (list)->prev->next = (link);                            \
10445 +       (list)->prev = (link);                                  \
10446 +} while (0)
10447 +#else
10448 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10449 +       dwc_list_link_t *__next__ = (list)->next;               \
10450 +       __next__->prev = (link);                                \
10451 +       (link)->next = __next__;                                \
10452 +       (link)->prev = (list);                                  \
10453 +       (list)->next = (link);                                  \
10454 +} while (0)
10455 +
10456 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10457 +       dwc_list_link_t *__prev__ = (list)->prev;               \
10458 +       (list)->prev = (link);                                  \
10459 +       (link)->next = (list);                                  \
10460 +       (link)->prev = __prev__;                                \
10461 +       __prev__->next = (link);                                \
10462 +} while (0)
10463 +#endif
10464 +
10465 +#if 0
10466 +static inline void __list_add(struct list_head *new,
10467 +                              struct list_head *prev,
10468 +                              struct list_head *next)
10469 +{
10470 +        next->prev = new;
10471 +        new->next = next;
10472 +        new->prev = prev;
10473 +        prev->next = new;
10474 +}
10475 +
10476 +static inline void list_add(struct list_head *new, struct list_head *head)
10477 +{
10478 +        __list_add(new, head, head->next);
10479 +}
10480 +
10481 +static inline void list_add_tail(struct list_head *new, struct list_head *head)
10482 +{
10483 +        __list_add(new, head->prev, head);
10484 +}
10485 +
10486 +static inline void __list_del(struct list_head * prev, struct list_head * next)
10487 +{
10488 +        next->prev = prev;
10489 +        prev->next = next;
10490 +}
10491 +
10492 +static inline void list_del(struct list_head *entry)
10493 +{
10494 +        __list_del(entry->prev, entry->next);
10495 +        entry->next = LIST_POISON1;
10496 +        entry->prev = LIST_POISON2;
10497 +}
10498 +#endif
10499 +
10500 +#define DWC_LIST_REMOVE(link) do {                             \
10501 +       (link)->next->prev = (link)->prev;                      \
10502 +       (link)->prev->next = (link)->next;                      \
10503 +} while (0)
10504 +
10505 +#define DWC_LIST_REMOVE_INIT(link) do {                                \
10506 +       DWC_LIST_REMOVE(link);                                  \
10507 +       DWC_LIST_INIT(link);                                    \
10508 +} while (0)
10509 +
10510 +#define DWC_LIST_MOVE_HEAD(list, link) do {                    \
10511 +       DWC_LIST_REMOVE(link);                                  \
10512 +       DWC_LIST_INSERT_HEAD(list, link);                       \
10513 +} while (0)
10514 +
10515 +#define DWC_LIST_MOVE_TAIL(list, link) do {                    \
10516 +       DWC_LIST_REMOVE(link);                                  \
10517 +       DWC_LIST_INSERT_TAIL(list, link);                       \
10518 +} while (0)
10519 +
10520 +#define DWC_LIST_FOREACH(var, list)                            \
10521 +       for((var) = DWC_LIST_FIRST(list);                       \
10522 +           (var) != DWC_LIST_END(list);                        \
10523 +           (var) = DWC_LIST_NEXT(var))
10524 +
10525 +#define DWC_LIST_FOREACH_SAFE(var, var2, list)                 \
10526 +       for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var);  \
10527 +           (var) != DWC_LIST_END(list);                        \
10528 +           (var) = (var2), (var2) = DWC_LIST_NEXT(var2))
10529 +
10530 +#define DWC_LIST_FOREACH_REVERSE(var, list)                    \
10531 +       for((var) = DWC_LIST_LAST(list);                        \
10532 +           (var) != DWC_LIST_END(list);                        \
10533 +           (var) = DWC_LIST_PREV(var))
10534 +
10535 +/*
10536 + * Singly-linked List definitions.
10537 + */
10538 +#define DWC_SLIST_HEAD(name, type)                                     \
10539 +struct name {                                                          \
10540 +       struct type *slh_first; /* first element */                     \
10541 +}
10542 +
10543 +#define DWC_SLIST_HEAD_INITIALIZER(head)                               \
10544 +       { NULL }
10545 +
10546 +#define DWC_SLIST_ENTRY(type)                                          \
10547 +struct {                                                               \
10548 +       struct type *sle_next;  /* next element */                      \
10549 +}
10550 +
10551 +/*
10552 + * Singly-linked List access methods.
10553 + */
10554 +#define DWC_SLIST_FIRST(head)  ((head)->slh_first)
10555 +#define DWC_SLIST_END(head)            NULL
10556 +#define DWC_SLIST_EMPTY(head)  (SLIST_FIRST(head) == SLIST_END(head))
10557 +#define DWC_SLIST_NEXT(elm, field)     ((elm)->field.sle_next)
10558 +
10559 +#define DWC_SLIST_FOREACH(var, head, field)                            \
10560 +       for((var) = SLIST_FIRST(head);                                  \
10561 +           (var) != SLIST_END(head);                                   \
10562 +           (var) = SLIST_NEXT(var, field))
10563 +
10564 +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)              \
10565 +       for((varp) = &SLIST_FIRST((head));                              \
10566 +           ((var) = *(varp)) != SLIST_END(head);                       \
10567 +           (varp) = &SLIST_NEXT((var), field))
10568 +
10569 +/*
10570 + * Singly-linked List functions.
10571 + */
10572 +#define DWC_SLIST_INIT(head) {                                         \
10573 +       SLIST_FIRST(head) = SLIST_END(head);                            \
10574 +}
10575 +
10576 +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {              \
10577 +       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
10578 +       (slistelm)->field.sle_next = (elm);                             \
10579 +} while (0)
10580 +
10581 +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {                   \
10582 +       (elm)->field.sle_next = (head)->slh_first;                      \
10583 +       (head)->slh_first = (elm);                                      \
10584 +} while (0)
10585 +
10586 +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {                   \
10587 +       (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
10588 +} while (0)
10589 +
10590 +#define DWC_SLIST_REMOVE_HEAD(head, field) do {                                \
10591 +       (head)->slh_first = (head)->slh_first->field.sle_next;          \
10592 +} while (0)
10593 +
10594 +#define DWC_SLIST_REMOVE(head, elm, type, field) do {                  \
10595 +       if ((head)->slh_first == (elm)) {                               \
10596 +               SLIST_REMOVE_HEAD((head), field);                       \
10597 +       }                                                               \
10598 +       else {                                                          \
10599 +               struct type *curelm = (head)->slh_first;                \
10600 +               while( curelm->field.sle_next != (elm) )                \
10601 +                       curelm = curelm->field.sle_next;                \
10602 +               curelm->field.sle_next =                                \
10603 +                   curelm->field.sle_next->field.sle_next;             \
10604 +       }                                                               \
10605 +} while (0)
10606 +
10607 +/*
10608 + * Simple queue definitions.
10609 + */
10610 +#define DWC_SIMPLEQ_HEAD(name, type)                                   \
10611 +struct name {                                                          \
10612 +       struct type *sqh_first; /* first element */                     \
10613 +       struct type **sqh_last; /* addr of last next element */         \
10614 +}
10615 +
10616 +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)                             \
10617 +       { NULL, &(head).sqh_first }
10618 +
10619 +#define DWC_SIMPLEQ_ENTRY(type)                                                \
10620 +struct {                                                               \
10621 +       struct type *sqe_next;  /* next element */                      \
10622 +}
10623 +
10624 +/*
10625 + * Simple queue access methods.
10626 + */
10627 +#define DWC_SIMPLEQ_FIRST(head)            ((head)->sqh_first)
10628 +#define DWC_SIMPLEQ_END(head)      NULL
10629 +#define DWC_SIMPLEQ_EMPTY(head)            (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
10630 +#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
10631 +
10632 +#define DWC_SIMPLEQ_FOREACH(var, head, field)                          \
10633 +       for((var) = SIMPLEQ_FIRST(head);                                \
10634 +           (var) != SIMPLEQ_END(head);                                 \
10635 +           (var) = SIMPLEQ_NEXT(var, field))
10636 +
10637 +/*
10638 + * Simple queue functions.
10639 + */
10640 +#define DWC_SIMPLEQ_INIT(head) do {                                    \
10641 +       (head)->sqh_first = NULL;                                       \
10642 +       (head)->sqh_last = &(head)->sqh_first;                          \
10643 +} while (0)
10644 +
10645 +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {                 \
10646 +       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
10647 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10648 +       (head)->sqh_first = (elm);                                      \
10649 +} while (0)
10650 +
10651 +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {                 \
10652 +       (elm)->field.sqe_next = NULL;                                   \
10653 +       *(head)->sqh_last = (elm);                                      \
10654 +       (head)->sqh_last = &(elm)->field.sqe_next;                      \
10655 +} while (0)
10656 +
10657 +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10658 +       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
10659 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10660 +       (listelm)->field.sqe_next = (elm);                              \
10661 +} while (0)
10662 +
10663 +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {                      \
10664 +       if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
10665 +               (head)->sqh_last = &(head)->sqh_first;                  \
10666 +} while (0)
10667 +
10668 +/*
10669 + * Tail queue definitions.
10670 + */
10671 +#define DWC_TAILQ_HEAD(name, type)                                     \
10672 +struct name {                                                          \
10673 +       struct type *tqh_first; /* first element */                     \
10674 +       struct type **tqh_last; /* addr of last next element */         \
10675 +}
10676 +
10677 +#define DWC_TAILQ_HEAD_INITIALIZER(head)                               \
10678 +       { NULL, &(head).tqh_first }
10679 +
10680 +#define DWC_TAILQ_ENTRY(type)                                          \
10681 +struct {                                                               \
10682 +       struct type *tqe_next;  /* next element */                      \
10683 +       struct type **tqe_prev; /* address of previous next element */  \
10684 +}
10685 +
10686 +/*
10687 + * tail queue access methods
10688 + */
10689 +#define DWC_TAILQ_FIRST(head)          ((head)->tqh_first)
10690 +#define DWC_TAILQ_END(head)            NULL
10691 +#define DWC_TAILQ_NEXT(elm, field)     ((elm)->field.tqe_next)
10692 +#define DWC_TAILQ_LAST(head, headname)                                 \
10693 +       (*(((struct headname *)((head)->tqh_last))->tqh_last))
10694 +/* XXX */
10695 +#define DWC_TAILQ_PREV(elm, headname, field)                           \
10696 +       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
10697 +#define DWC_TAILQ_EMPTY(head)                                          \
10698 +       (TAILQ_FIRST(head) == TAILQ_END(head))
10699 +
10700 +#define DWC_TAILQ_FOREACH(var, head, field)                            \
10701 +       for((var) = TAILQ_FIRST(head);                                  \
10702 +           (var) != TAILQ_END(head);                                   \
10703 +           (var) = TAILQ_NEXT(var, field))
10704 +
10705 +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)          \
10706 +       for((var) = TAILQ_LAST(head, headname);                         \
10707 +           (var) != TAILQ_END(head);                                   \
10708 +           (var) = TAILQ_PREV(var, headname, field))
10709 +
10710 +/*
10711 + * Tail queue functions.
10712 + */
10713 +#define DWC_TAILQ_INIT(head) do {                                      \
10714 +       (head)->tqh_first = NULL;                                       \
10715 +       (head)->tqh_last = &(head)->tqh_first;                          \
10716 +} while (0)
10717 +
10718 +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {                   \
10719 +       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
10720 +               (head)->tqh_first->field.tqe_prev =                     \
10721 +                   &(elm)->field.tqe_next;                             \
10722 +       else                                                            \
10723 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10724 +       (head)->tqh_first = (elm);                                      \
10725 +       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
10726 +} while (0)
10727 +
10728 +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {                   \
10729 +       (elm)->field.tqe_next = NULL;                                   \
10730 +       (elm)->field.tqe_prev = (head)->tqh_last;                       \
10731 +       *(head)->tqh_last = (elm);                                      \
10732 +       (head)->tqh_last = &(elm)->field.tqe_next;                      \
10733 +} while (0)
10734 +
10735 +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {         \
10736 +       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
10737 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10738 +                   &(elm)->field.tqe_next;                             \
10739 +       else                                                            \
10740 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10741 +       (listelm)->field.tqe_next = (elm);                              \
10742 +       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
10743 +} while (0)
10744 +
10745 +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {              \
10746 +       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
10747 +       (elm)->field.tqe_next = (listelm);                              \
10748 +       *(listelm)->field.tqe_prev = (elm);                             \
10749 +       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
10750 +} while (0)
10751 +
10752 +#define DWC_TAILQ_REMOVE(head, elm, field) do {                                \
10753 +       if (((elm)->field.tqe_next) != NULL)                            \
10754 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10755 +                   (elm)->field.tqe_prev;                              \
10756 +       else                                                            \
10757 +               (head)->tqh_last = (elm)->field.tqe_prev;               \
10758 +       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
10759 +} while (0)
10760 +
10761 +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {                 \
10762 +       if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
10763 +               (elm2)->field.tqe_next->field.tqe_prev =                \
10764 +                   &(elm2)->field.tqe_next;                            \
10765 +       else                                                            \
10766 +               (head)->tqh_last = &(elm2)->field.tqe_next;             \
10767 +       (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
10768 +       *(elm2)->field.tqe_prev = (elm2);                               \
10769 +} while (0)
10770 +
10771 +/*
10772 + * Circular queue definitions.
10773 + */
10774 +#define DWC_CIRCLEQ_HEAD(name, type)                                   \
10775 +struct name {                                                          \
10776 +       struct type *cqh_first;         /* first element */             \
10777 +       struct type *cqh_last;          /* last element */              \
10778 +}
10779 +
10780 +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)                             \
10781 +       { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
10782 +
10783 +#define DWC_CIRCLEQ_ENTRY(type)                                                \
10784 +struct {                                                               \
10785 +       struct type *cqe_next;          /* next element */              \
10786 +       struct type *cqe_prev;          /* previous element */          \
10787 +}
10788 +
10789 +/*
10790 + * Circular queue access methods
10791 + */
10792 +#define DWC_CIRCLEQ_FIRST(head)                ((head)->cqh_first)
10793 +#define DWC_CIRCLEQ_LAST(head)         ((head)->cqh_last)
10794 +#define DWC_CIRCLEQ_END(head)          ((void *)(head))
10795 +#define DWC_CIRCLEQ_NEXT(elm, field)   ((elm)->field.cqe_next)
10796 +#define DWC_CIRCLEQ_PREV(elm, field)   ((elm)->field.cqe_prev)
10797 +#define DWC_CIRCLEQ_EMPTY(head)                                                \
10798 +       (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
10799 +
10800 +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
10801 +
10802 +#define DWC_CIRCLEQ_FOREACH(var, head, field)                          \
10803 +       for((var) = DWC_CIRCLEQ_FIRST(head);                            \
10804 +           (var) != DWC_CIRCLEQ_END(head);                             \
10805 +           (var) = DWC_CIRCLEQ_NEXT(var, field))
10806 +
10807 +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)                       \
10808 +       for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \
10809 +           (var) != DWC_CIRCLEQ_END(head);                                     \
10810 +           (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
10811 +
10812 +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)                  \
10813 +       for((var) = DWC_CIRCLEQ_LAST(head);                             \
10814 +           (var) != DWC_CIRCLEQ_END(head);                             \
10815 +           (var) = DWC_CIRCLEQ_PREV(var, field))
10816 +
10817 +/*
10818 + * Circular queue functions.
10819 + */
10820 +#define DWC_CIRCLEQ_INIT(head) do {                                    \
10821 +       (head)->cqh_first = DWC_CIRCLEQ_END(head);                      \
10822 +       (head)->cqh_last = DWC_CIRCLEQ_END(head);                       \
10823 +} while (0)
10824 +
10825 +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do {                                \
10826 +       (elm)->field.cqe_next = NULL;                                   \
10827 +       (elm)->field.cqe_prev = NULL;                                   \
10828 +} while (0)
10829 +
10830 +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10831 +       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
10832 +       (elm)->field.cqe_prev = (listelm);                              \
10833 +       if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))         \
10834 +               (head)->cqh_last = (elm);                               \
10835 +       else                                                            \
10836 +               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
10837 +       (listelm)->field.cqe_next = (elm);                              \
10838 +} while (0)
10839 +
10840 +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {      \
10841 +       (elm)->field.cqe_next = (listelm);                              \
10842 +       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
10843 +       if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))         \
10844 +               (head)->cqh_first = (elm);                              \
10845 +       else                                                            \
10846 +               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
10847 +       (listelm)->field.cqe_prev = (elm);                              \
10848 +} while (0)
10849 +
10850 +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {                 \
10851 +       (elm)->field.cqe_next = (head)->cqh_first;                      \
10852 +       (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);                  \
10853 +       if ((head)->cqh_last == DWC_CIRCLEQ_END(head))                  \
10854 +               (head)->cqh_last = (elm);                               \
10855 +       else                                                            \
10856 +               (head)->cqh_first->field.cqe_prev = (elm);              \
10857 +       (head)->cqh_first = (elm);                                      \
10858 +} while (0)
10859 +
10860 +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {                 \
10861 +       (elm)->field.cqe_next = DWC_CIRCLEQ_END(head);                  \
10862 +       (elm)->field.cqe_prev = (head)->cqh_last;                       \
10863 +       if ((head)->cqh_first == DWC_CIRCLEQ_END(head))                 \
10864 +               (head)->cqh_first = (elm);                              \
10865 +       else                                                            \
10866 +               (head)->cqh_last->field.cqe_next = (elm);               \
10867 +       (head)->cqh_last = (elm);                                       \
10868 +} while (0)
10869 +
10870 +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {                      \
10871 +       if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))             \
10872 +               (head)->cqh_last = (elm)->field.cqe_prev;               \
10873 +       else                                                            \
10874 +               (elm)->field.cqe_next->field.cqe_prev =                 \
10875 +                   (elm)->field.cqe_prev;                              \
10876 +       if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))             \
10877 +               (head)->cqh_first = (elm)->field.cqe_next;              \
10878 +       else                                                            \
10879 +               (elm)->field.cqe_prev->field.cqe_next =                 \
10880 +                   (elm)->field.cqe_next;                              \
10881 +} while (0)
10882 +
10883 +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do {                 \
10884 +       DWC_CIRCLEQ_REMOVE(head, elm, field);                           \
10885 +       DWC_CIRCLEQ_INIT_ENTRY(elm, field);                             \
10886 +} while (0)
10887 +
10888 +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {               \
10889 +       if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
10890 +           DWC_CIRCLEQ_END(head))                                      \
10891 +               (head).cqh_last = (elm2);                               \
10892 +       else                                                            \
10893 +               (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
10894 +       if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
10895 +           DWC_CIRCLEQ_END(head))                                      \
10896 +               (head).cqh_first = (elm2);                              \
10897 +       else                                                            \
10898 +               (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
10899 +} while (0)
10900 +
10901 +#ifdef __cplusplus
10902 +}
10903 +#endif
10904 +
10905 +#endif /* _DWC_LIST_H_ */
10906 --- /dev/null
10907 +++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
10908 @@ -0,0 +1,245 @@
10909 +/* Memory Debugging */
10910 +#ifdef DWC_DEBUG_MEMORY
10911 +
10912 +#include "dwc_os.h"
10913 +#include "dwc_list.h"
10914 +
10915 +struct allocation {
10916 +       void *addr;
10917 +       void *ctx;
10918 +       char *func;
10919 +       int line;
10920 +       uint32_t size;
10921 +       int dma;
10922 +       DWC_CIRCLEQ_ENTRY(allocation) entry;
10923 +};
10924 +
10925 +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
10926 +
10927 +struct allocation_manager {
10928 +       void *mem_ctx;
10929 +       struct allocation_queue allocations;
10930 +
10931 +       /* statistics */
10932 +       int num;
10933 +       int num_freed;
10934 +       int num_active;
10935 +       uint32_t total;
10936 +       uint32_t cur;
10937 +       uint32_t max;
10938 +};
10939 +
10940 +static struct allocation_manager *manager = NULL;
10941 +
10942 +static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
10943 +                         int dma)
10944 +{
10945 +       struct allocation *a;
10946 +
10947 +       DWC_ASSERT(manager != NULL, "manager not allocated");
10948 +
10949 +       a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
10950 +       if (!a) {
10951 +               return -DWC_E_NO_MEMORY;
10952 +       }
10953 +
10954 +       a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
10955 +       if (!a->func) {
10956 +               __DWC_FREE(manager->mem_ctx, a);
10957 +               return -DWC_E_NO_MEMORY;
10958 +       }
10959 +
10960 +       DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
10961 +       a->addr = addr;
10962 +       a->ctx = ctx;
10963 +       a->line = line;
10964 +       a->size = size;
10965 +       a->dma = dma;
10966 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
10967 +
10968 +       /* Update stats */
10969 +       manager->num++;
10970 +       manager->num_active++;
10971 +       manager->total += size;
10972 +       manager->cur += size;
10973 +
10974 +       if (manager->max < manager->cur) {
10975 +               manager->max = manager->cur;
10976 +       }
10977 +
10978 +       return 0;
10979 +}
10980 +
10981 +static struct allocation *find_allocation(void *ctx, void *addr)
10982 +{
10983 +       struct allocation *a;
10984 +
10985 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
10986 +               if (a->ctx == ctx && a->addr == addr) {
10987 +                       return a;
10988 +               }
10989 +       }
10990 +
10991 +       return NULL;
10992 +}
10993 +
10994 +static void free_allocation(void *ctx, void *addr, char const *func, int line)
10995 +{
10996 +       struct allocation *a = find_allocation(ctx, addr);
10997 +
10998 +       if (!a) {
10999 +               DWC_ASSERT(0,
11000 +                          "Free of address %p that was never allocated or already freed %s:%d",
11001 +                          addr, func, line);
11002 +               return;
11003 +       }
11004 +
11005 +       DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
11006 +
11007 +       manager->num_active--;
11008 +       manager->num_freed++;
11009 +       manager->cur -= a->size;
11010 +       __DWC_FREE(manager->mem_ctx, a->func);
11011 +       __DWC_FREE(manager->mem_ctx, a);
11012 +}
11013 +
11014 +int dwc_memory_debug_start(void *mem_ctx)
11015 +{
11016 +       DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
11017 +
11018 +       if (manager) {
11019 +               return -DWC_E_BUSY;
11020 +       }
11021 +
11022 +       manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
11023 +       if (!manager) {
11024 +               return -DWC_E_NO_MEMORY;
11025 +       }
11026 +
11027 +       DWC_CIRCLEQ_INIT(&manager->allocations);
11028 +       manager->mem_ctx = mem_ctx;
11029 +       manager->num = 0;
11030 +       manager->num_freed = 0;
11031 +       manager->num_active = 0;
11032 +       manager->total = 0;
11033 +       manager->cur = 0;
11034 +       manager->max = 0;
11035 +
11036 +       return 0;
11037 +}
11038 +
11039 +void dwc_memory_debug_stop(void)
11040 +{
11041 +       struct allocation *a;
11042 +
11043 +       dwc_memory_debug_report();
11044 +
11045 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11046 +               DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
11047 +               free_allocation(a->ctx, a->addr, NULL, -1);
11048 +       }
11049 +
11050 +       __DWC_FREE(manager->mem_ctx, manager);
11051 +}
11052 +
11053 +void dwc_memory_debug_report(void)
11054 +{
11055 +       struct allocation *a;
11056 +
11057 +       DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
11058 +       DWC_PRINTF("Num Allocations = %d\n", manager->num);
11059 +       DWC_PRINTF("Freed = %d\n", manager->num_freed);
11060 +       DWC_PRINTF("Active = %d\n", manager->num_active);
11061 +       DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
11062 +       DWC_PRINTF("Total Memory Used = %d\n", manager->total);
11063 +       DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
11064 +       DWC_PRINTF("Unfreed allocations:\n");
11065 +
11066 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11067 +               DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n",
11068 +                          a->addr, a->size, a->func, a->line, a->dma);
11069 +       }
11070 +}
11071 +
11072 +/* The replacement functions */
11073 +void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
11074 +{
11075 +       void *addr = __DWC_ALLOC(mem_ctx, size);
11076 +
11077 +       if (!addr) {
11078 +               return NULL;
11079 +       }
11080 +
11081 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11082 +               __DWC_FREE(mem_ctx, addr);
11083 +               return NULL;
11084 +       }
11085 +
11086 +       return addr;
11087 +}
11088 +
11089 +void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
11090 +                            int line)
11091 +{
11092 +       void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);
11093 +
11094 +       if (!addr) {
11095 +               return NULL;
11096 +       }
11097 +
11098 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11099 +               __DWC_FREE(mem_ctx, addr);
11100 +               return NULL;
11101 +       }
11102 +
11103 +       return addr;
11104 +}
11105 +
11106 +void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)
11107 +{
11108 +       free_allocation(mem_ctx, addr, func, line);
11109 +       __DWC_FREE(mem_ctx, addr);
11110 +}
11111 +
11112 +void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
11113 +                         char const *func, int line)
11114 +{
11115 +       void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
11116 +
11117 +       if (!addr) {
11118 +               return NULL;
11119 +       }
11120 +
11121 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11122 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11123 +               return NULL;
11124 +       }
11125 +
11126 +       return addr;
11127 +}
11128 +
11129 +void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
11130 +                                dwc_dma_t *dma_addr, char const *func, int line)
11131 +{
11132 +       void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);
11133 +
11134 +       if (!addr) {
11135 +               return NULL;
11136 +       }
11137 +
11138 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11139 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11140 +               return NULL;
11141 +       }
11142 +
11143 +       return addr;
11144 +}
11145 +
11146 +void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
11147 +                       dwc_dma_t dma_addr, char const *func, int line)
11148 +{
11149 +       free_allocation(dma_ctx, virt_addr, func, line);
11150 +       __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
11151 +}
11152 +
11153 +#endif /* DWC_DEBUG_MEMORY */
11154 --- /dev/null
11155 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
11156 @@ -0,0 +1,636 @@
11157 +/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.
11158 + *
11159 + * PuTTY is copyright 1997-2007 Simon Tatham.
11160 + *
11161 + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
11162 + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
11163 + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
11164 + * Kuhn, and CORE SDI S.A.
11165 + *
11166 + * Permission is hereby granted, free of charge, to any person
11167 + * obtaining a copy of this software and associated documentation files
11168 + * (the "Software"), to deal in the Software without restriction,
11169 + * including without limitation the rights to use, copy, modify, merge,
11170 + * publish, distribute, sublicense, and/or sell copies of the Software,
11171 + * and to permit persons to whom the Software is furnished to do so,
11172 + * subject to the following conditions:
11173 + *
11174 + * The above copyright notice and this permission notice shall be
11175 + * included in all copies or substantial portions of the Software.
11176 +
11177 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11178 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11179 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11180 + * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
11181 + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
11182 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
11183 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11184 + *
11185 + */
11186 +#ifdef DWC_CRYPTOLIB
11187 +
11188 +#ifndef CONFIG_MACH_IPMATE
11189 +
11190 +#include "dwc_modpow.h"
11191 +
11192 +#define BIGNUM_INT_MASK  0xFFFFFFFFUL
11193 +#define BIGNUM_TOP_BIT   0x80000000UL
11194 +#define BIGNUM_INT_BITS  32
11195 +
11196 +
11197 +static void *snmalloc(void *mem_ctx, size_t n, size_t size)
11198 +{
11199 +    void *p;
11200 +    size *= n;
11201 +    if (size == 0) size = 1;
11202 +    p = dwc_alloc(mem_ctx, size);
11203 +    return p;
11204 +}
11205 +
11206 +#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))
11207 +#define sfree dwc_free
11208 +
11209 +/*
11210 + * Usage notes:
11211 + *  * Do not call the DIVMOD_WORD macro with expressions such as array
11212 + *    subscripts, as some implementations object to this (see below).
11213 + *  * Note that none of the division methods below will cope if the
11214 + *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
11215 + *    to avoid this case.
11216 + *    If this condition occurs, in the case of the x86 DIV instruction,
11217 + *    an overflow exception will occur, which (according to a correspondent)
11218 + *    will manifest on Windows as something like
11219 + *      0xC0000095: Integer overflow
11220 + *    The C variant won't give the right answer, either.
11221 + */
11222 +
11223 +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
11224 +
11225 +#if defined __GNUC__ && defined __i386__
11226 +#define DIVMOD_WORD(q, r, hi, lo, w) \
11227 +    __asm__("div %2" : \
11228 +           "=d" (r), "=a" (q) : \
11229 +           "r" (w), "d" (hi), "a" (lo))
11230 +#else
11231 +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
11232 +    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
11233 +    q = n / w; \
11234 +    r = n % w; \
11235 +} while (0)
11236 +#endif
11237 +
11238 +//    q = n / w;
11239 +//    r = n % w;
11240 +
11241 +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
11242 +
11243 +#define BIGNUM_INTERNAL
11244 +
11245 +static Bignum newbn(void *mem_ctx, int length)
11246 +{
11247 +    Bignum b = snewn(mem_ctx, length + 1, BignumInt);
11248 +    //if (!b)
11249 +    //abort();                /* FIXME */
11250 +    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
11251 +    b[0] = length;
11252 +    return b;
11253 +}
11254 +
11255 +void freebn(void *mem_ctx, Bignum b)
11256 +{
11257 +    /*
11258 +     * Burn the evidence, just in case.
11259 +     */
11260 +    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
11261 +    sfree(mem_ctx, b);
11262 +}
11263 +
11264 +/*
11265 + * Compute c = a * b.
11266 + * Input is in the first len words of a and b.
11267 + * Result is returned in the first 2*len words of c.
11268 + */
11269 +static void internal_mul(BignumInt *a, BignumInt *b,
11270 +                        BignumInt *c, int len)
11271 +{
11272 +    int i, j;
11273 +    BignumDblInt t;
11274 +
11275 +    for (j = 0; j < 2 * len; j++)
11276 +       c[j] = 0;
11277 +
11278 +    for (i = len - 1; i >= 0; i--) {
11279 +       t = 0;
11280 +       for (j = len - 1; j >= 0; j--) {
11281 +           t += MUL_WORD(a[i], (BignumDblInt) b[j]);
11282 +           t += (BignumDblInt) c[i + j + 1];
11283 +           c[i + j + 1] = (BignumInt) t;
11284 +           t = t >> BIGNUM_INT_BITS;
11285 +       }
11286 +       c[i] = (BignumInt) t;
11287 +    }
11288 +}
11289 +
11290 +static void internal_add_shifted(BignumInt *number,
11291 +                                unsigned n, int shift)
11292 +{
11293 +    int word = 1 + (shift / BIGNUM_INT_BITS);
11294 +    int bshift = shift % BIGNUM_INT_BITS;
11295 +    BignumDblInt addend;
11296 +
11297 +    addend = (BignumDblInt)n << bshift;
11298 +
11299 +    while (addend) {
11300 +       addend += number[word];
11301 +       number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
11302 +       addend >>= BIGNUM_INT_BITS;
11303 +       word++;
11304 +    }
11305 +}
11306 +
11307 +/*
11308 + * Compute a = a % m.
11309 + * Input in first alen words of a and first mlen words of m.
11310 + * Output in first alen words of a
11311 + * (of which first alen-mlen words will be zero).
11312 + * The MSW of m MUST have its high bit set.
11313 + * Quotient is accumulated in the `quotient' array, which is a Bignum
11314 + * rather than the internal bigendian format. Quotient parts are shifted
11315 + * left by `qshift' before adding into quot.
11316 + */
11317 +static void internal_mod(BignumInt *a, int alen,
11318 +                        BignumInt *m, int mlen,
11319 +                        BignumInt *quot, int qshift)
11320 +{
11321 +    BignumInt m0, m1;
11322 +    unsigned int h;
11323 +    int i, k;
11324 +
11325 +    m0 = m[0];
11326 +    if (mlen > 1)
11327 +       m1 = m[1];
11328 +    else
11329 +       m1 = 0;
11330 +
11331 +    for (i = 0; i <= alen - mlen; i++) {
11332 +       BignumDblInt t;
11333 +       unsigned int q, r, c, ai1;
11334 +
11335 +       if (i == 0) {
11336 +           h = 0;
11337 +       } else {
11338 +           h = a[i - 1];
11339 +           a[i - 1] = 0;
11340 +       }
11341 +
11342 +       if (i == alen - 1)
11343 +           ai1 = 0;
11344 +       else
11345 +           ai1 = a[i + 1];
11346 +
11347 +       /* Find q = h:a[i] / m0 */
11348 +       if (h >= m0) {
11349 +           /*
11350 +            * Special case.
11351 +            *
11352 +            * To illustrate it, suppose a BignumInt is 8 bits, and
11353 +            * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
11354 +            * our initial division will be 0xA123 / 0xA1, which
11355 +            * will give a quotient of 0x100 and a divide overflow.
11356 +            * However, the invariants in this division algorithm
11357 +            * are not violated, since the full number A1:23:... is
11358 +            * _less_ than the quotient prefix A1:B2:... and so the
11359 +            * following correction loop would have sorted it out.
11360 +            *
11361 +            * In this situation we set q to be the largest
11362 +            * quotient we _can_ stomach (0xFF, of course).
11363 +            */
11364 +           q = BIGNUM_INT_MASK;
11365 +       } else {
11366 +           /* Macro doesn't want an array subscript expression passed
11367 +            * into it (see definition), so use a temporary. */
11368 +           BignumInt tmplo = a[i];
11369 +           DIVMOD_WORD(q, r, h, tmplo, m0);
11370 +
11371 +           /* Refine our estimate of q by looking at
11372 +            h:a[i]:a[i+1] / m0:m1 */
11373 +           t = MUL_WORD(m1, q);
11374 +           if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
11375 +               q--;
11376 +               t -= m1;
11377 +               r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */
11378 +               if (r >= (BignumDblInt) m0 &&
11379 +                   t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
11380 +           }
11381 +       }
11382 +
11383 +       /* Subtract q * m from a[i...] */
11384 +       c = 0;
11385 +       for (k = mlen - 1; k >= 0; k--) {
11386 +           t = MUL_WORD(q, m[k]);
11387 +           t += c;
11388 +           c = (unsigned)(t >> BIGNUM_INT_BITS);
11389 +           if ((BignumInt) t > a[i + k])
11390 +               c++;
11391 +           a[i + k] -= (BignumInt) t;
11392 +       }
11393 +
11394 +       /* Add back m in case of borrow */
11395 +       if (c != h) {
11396 +           t = 0;
11397 +           for (k = mlen - 1; k >= 0; k--) {
11398 +               t += m[k];
11399 +               t += a[i + k];
11400 +               a[i + k] = (BignumInt) t;
11401 +               t = t >> BIGNUM_INT_BITS;
11402 +           }
11403 +           q--;
11404 +       }
11405 +       if (quot)
11406 +           internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
11407 +    }
11408 +}
11409 +
11410 +/*
11411 + * Compute p % mod.
11412 + * The most significant word of mod MUST be non-zero.
11413 + * We assume that the result array is the same size as the mod array.
11414 + * We optionally write out a quotient if `quotient' is non-NULL.
11415 + * We can avoid writing out the result if `result' is NULL.
11416 + */
11417 +void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)
11418 +{
11419 +    BignumInt *n, *m;
11420 +    int mshift;
11421 +    int plen, mlen, i, j;
11422 +
11423 +    /* Allocate m of size mlen, copy mod to m */
11424 +    /* We use big endian internally */
11425 +    mlen = mod[0];
11426 +    m = snewn(mem_ctx, mlen, BignumInt);
11427 +    //if (!m)
11428 +    //abort();                /* FIXME */
11429 +    for (j = 0; j < mlen; j++)
11430 +       m[j] = mod[mod[0] - j];
11431 +
11432 +    /* Shift m left to make msb bit set */
11433 +    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
11434 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11435 +           break;
11436 +    if (mshift) {
11437 +       for (i = 0; i < mlen - 1; i++)
11438 +           m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
11439 +       m[mlen - 1] = m[mlen - 1] << mshift;
11440 +    }
11441 +
11442 +    plen = p[0];
11443 +    /* Ensure plen > mlen */
11444 +    if (plen <= mlen)
11445 +       plen = mlen + 1;
11446 +
11447 +    /* Allocate n of size plen, copy p to n */
11448 +    n = snewn(mem_ctx, plen, BignumInt);
11449 +    //if (!n)
11450 +    //abort();                /* FIXME */
11451 +    for (j = 0; j < plen; j++)
11452 +       n[j] = 0;
11453 +    for (j = 1; j <= (int)p[0]; j++)
11454 +       n[plen - j] = p[j];
11455 +
11456 +    /* Main computation */
11457 +    internal_mod(n, plen, m, mlen, quotient, mshift);
11458 +
11459 +    /* Fixup result in case the modulus was shifted */
11460 +    if (mshift) {
11461 +       for (i = plen - mlen - 1; i < plen - 1; i++)
11462 +           n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
11463 +       n[plen - 1] = n[plen - 1] << mshift;
11464 +       internal_mod(n, plen, m, mlen, quotient, 0);
11465 +       for (i = plen - 1; i >= plen - mlen; i--)
11466 +           n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
11467 +    }
11468 +
11469 +    /* Copy result to buffer */
11470 +    if (result) {
11471 +       for (i = 1; i <= (int)result[0]; i++) {
11472 +           int j = plen - i;
11473 +           result[i] = j >= 0 ? n[j] : 0;
11474 +       }
11475 +    }
11476 +
11477 +    /* Free temporary arrays */
11478 +    for (i = 0; i < mlen; i++)
11479 +       m[i] = 0;
11480 +    sfree(mem_ctx, m);
11481 +    for (i = 0; i < plen; i++)
11482 +       n[i] = 0;
11483 +    sfree(mem_ctx, n);
11484 +}
11485 +
11486 +/*
11487 + * Simple remainder.
11488 + */
11489 +Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)
11490 +{
11491 +    Bignum r = newbn(mem_ctx, b[0]);
11492 +    bigdivmod(mem_ctx, a, b, r, NULL);
11493 +    return r;
11494 +}
11495 +
11496 +/*
11497 + * Compute (base ^ exp) % mod.
11498 + */
11499 +Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)
11500 +{
11501 +    BignumInt *a, *b, *n, *m;
11502 +    int mshift;
11503 +    int mlen, i, j;
11504 +    Bignum base, result;
11505 +
11506 +    /*
11507 +     * The most significant word of mod needs to be non-zero. It
11508 +     * should already be, but let's make sure.
11509 +     */
11510 +    //assert(mod[mod[0]] != 0);
11511 +
11512 +    /*
11513 +     * Make sure the base is smaller than the modulus, by reducing
11514 +     * it modulo the modulus if not.
11515 +     */
11516 +    base = bigmod(mem_ctx, base_in, mod);
11517 +
11518 +    /* Allocate m of size mlen, copy mod to m */
11519 +    /* We use big endian internally */
11520 +    mlen = mod[0];
11521 +    m = snewn(mem_ctx, mlen, BignumInt);
11522 +    //if (!m)
11523 +    //abort();                /* FIXME */
11524 +    for (j = 0; j < mlen; j++)
11525 +       m[j] = mod[mod[0] - j];
11526 +
11527 +    /* Shift m left to make msb bit set */
11528 +    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
11529 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11530 +           break;
11531 +    if (mshift) {
11532 +       for (i = 0; i < mlen - 1; i++)
11533 +           m[i] =
11534 +               (m[i] << mshift) | (m[i + 1] >>
11535 +                                   (BIGNUM_INT_BITS - mshift));
11536 +       m[mlen - 1] = m[mlen - 1] << mshift;
11537 +    }
11538 +
11539 +    /* Allocate n of size mlen, copy base to n */
11540 +    n = snewn(mem_ctx, mlen, BignumInt);
11541 +    //if (!n)
11542 +    //abort();                /* FIXME */
11543 +    i = mlen - base[0];
11544 +    for (j = 0; j < i; j++)
11545 +       n[j] = 0;
11546 +    for (j = 0; j < base[0]; j++)
11547 +       n[i + j] = base[base[0] - j];
11548 +
11549 +    /* Allocate a and b of size 2*mlen. Set a = 1 */
11550 +    a = snewn(mem_ctx, 2 * mlen, BignumInt);
11551 +    //if (!a)
11552 +    //abort();                /* FIXME */
11553 +    b = snewn(mem_ctx, 2 * mlen, BignumInt);
11554 +    //if (!b)
11555 +    //abort();                /* FIXME */
11556 +    for (i = 0; i < 2 * mlen; i++)
11557 +       a[i] = 0;
11558 +    a[2 * mlen - 1] = 1;
11559 +
11560 +    /* Skip leading zero bits of exp. */
11561 +    i = 0;
11562 +    j = BIGNUM_INT_BITS - 1;
11563 +    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
11564 +       j--;
11565 +       if (j < 0) {
11566 +           i++;
11567 +           j = BIGNUM_INT_BITS - 1;
11568 +       }
11569 +    }
11570 +
11571 +    /* Main computation */
11572 +    while (i < exp[0]) {
11573 +       while (j >= 0) {
11574 +           internal_mul(a + mlen, a + mlen, b, mlen);
11575 +           internal_mod(b, mlen * 2, m, mlen, NULL, 0);
11576 +           if ((exp[exp[0] - i] & (1 << j)) != 0) {
11577 +               internal_mul(b + mlen, n, a, mlen);
11578 +               internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11579 +           } else {
11580 +               BignumInt *t;
11581 +               t = a;
11582 +               a = b;
11583 +               b = t;
11584 +           }
11585 +           j--;
11586 +       }
11587 +       i++;
11588 +       j = BIGNUM_INT_BITS - 1;
11589 +    }
11590 +
11591 +    /* Fixup result in case the modulus was shifted */
11592 +    if (mshift) {
11593 +       for (i = mlen - 1; i < 2 * mlen - 1; i++)
11594 +           a[i] =
11595 +               (a[i] << mshift) | (a[i + 1] >>
11596 +                                   (BIGNUM_INT_BITS - mshift));
11597 +       a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
11598 +       internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11599 +       for (i = 2 * mlen - 1; i >= mlen; i--)
11600 +           a[i] =
11601 +               (a[i] >> mshift) | (a[i - 1] <<
11602 +                                   (BIGNUM_INT_BITS - mshift));
11603 +    }
11604 +
11605 +    /* Copy result to buffer */
11606 +    result = newbn(mem_ctx, mod[0]);
11607 +    for (i = 0; i < mlen; i++)
11608 +       result[result[0] - i] = a[i + mlen];
11609 +    while (result[0] > 1 && result[result[0]] == 0)
11610 +       result[0]--;
11611 +
11612 +    /* Free temporary arrays */
11613 +    for (i = 0; i < 2 * mlen; i++)
11614 +       a[i] = 0;
11615 +    sfree(mem_ctx, a);
11616 +    for (i = 0; i < 2 * mlen; i++)
11617 +       b[i] = 0;
11618 +    sfree(mem_ctx, b);
11619 +    for (i = 0; i < mlen; i++)
11620 +       m[i] = 0;
11621 +    sfree(mem_ctx, m);
11622 +    for (i = 0; i < mlen; i++)
11623 +       n[i] = 0;
11624 +    sfree(mem_ctx, n);
11625 +
11626 +    freebn(mem_ctx, base);
11627 +
11628 +    return result;
11629 +}
11630 +
11631 +
11632 +#ifdef UNITTEST
11633 +
11634 +static __u32 dh_p[] = {
11635 +       96,
11636 +       0xFFFFFFFF,
11637 +       0xFFFFFFFF,
11638 +       0xA93AD2CA,
11639 +       0x4B82D120,
11640 +       0xE0FD108E,
11641 +       0x43DB5BFC,
11642 +       0x74E5AB31,
11643 +       0x08E24FA0,
11644 +       0xBAD946E2,
11645 +       0x770988C0,
11646 +       0x7A615D6C,
11647 +       0xBBE11757,
11648 +       0x177B200C,
11649 +       0x521F2B18,
11650 +       0x3EC86A64,
11651 +       0xD8760273,
11652 +       0xD98A0864,
11653 +       0xF12FFA06,
11654 +       0x1AD2EE6B,
11655 +       0xCEE3D226,
11656 +       0x4A25619D,
11657 +       0x1E8C94E0,
11658 +       0xDB0933D7,
11659 +       0xABF5AE8C,
11660 +       0xA6E1E4C7,
11661 +       0xB3970F85,
11662 +       0x5D060C7D,
11663 +       0x8AEA7157,
11664 +       0x58DBEF0A,
11665 +       0xECFB8504,
11666 +       0xDF1CBA64,
11667 +       0xA85521AB,
11668 +       0x04507A33,
11669 +       0xAD33170D,
11670 +       0x8AAAC42D,
11671 +       0x15728E5A,
11672 +       0x98FA0510,
11673 +       0x15D22618,
11674 +       0xEA956AE5,
11675 +       0x3995497C,
11676 +       0x95581718,
11677 +       0xDE2BCBF6,
11678 +       0x6F4C52C9,
11679 +       0xB5C55DF0,
11680 +       0xEC07A28F,
11681 +       0x9B2783A2,
11682 +       0x180E8603,
11683 +       0xE39E772C,
11684 +       0x2E36CE3B,
11685 +       0x32905E46,
11686 +       0xCA18217C,
11687 +       0xF1746C08,
11688 +       0x4ABC9804,
11689 +       0x670C354E,
11690 +       0x7096966D,
11691 +       0x9ED52907,
11692 +       0x208552BB,
11693 +       0x1C62F356,
11694 +       0xDCA3AD96,
11695 +       0x83655D23,
11696 +       0xFD24CF5F,
11697 +       0x69163FA8,
11698 +       0x1C55D39A,
11699 +       0x98DA4836,
11700 +       0xA163BF05,
11701 +       0xC2007CB8,
11702 +       0xECE45B3D,
11703 +       0x49286651,
11704 +       0x7C4B1FE6,
11705 +       0xAE9F2411,
11706 +       0x5A899FA5,
11707 +       0xEE386BFB,
11708 +       0xF406B7ED,
11709 +       0x0BFF5CB6,
11710 +       0xA637ED6B,
11711 +       0xF44C42E9,
11712 +       0x625E7EC6,
11713 +       0xE485B576,
11714 +       0x6D51C245,
11715 +       0x4FE1356D,
11716 +       0xF25F1437,
11717 +       0x302B0A6D,
11718 +       0xCD3A431B,
11719 +       0xEF9519B3,
11720 +       0x8E3404DD,
11721 +       0x514A0879,
11722 +       0x3B139B22,
11723 +       0x020BBEA6,
11724 +       0x8A67CC74,
11725 +       0x29024E08,
11726 +       0x80DC1CD1,
11727 +       0xC4C6628B,
11728 +       0x2168C234,
11729 +       0xC90FDAA2,
11730 +       0xFFFFFFFF,
11731 +       0xFFFFFFFF,
11732 +};
11733 +
11734 +static __u32 dh_a[] = {
11735 +       8,
11736 +       0xdf367516,
11737 +       0x86459caa,
11738 +       0xe2d459a4,
11739 +       0xd910dae0,
11740 +       0x8a8b5e37,
11741 +       0x67ab31c6,
11742 +       0xf0b55ea9,
11743 +       0x440051d6,
11744 +};
11745 +
11746 +static __u32 dh_b[] = {
11747 +       8,
11748 +       0xded92656,
11749 +       0xe07a048a,
11750 +       0x6fa452cd,
11751 +       0x2df89d30,
11752 +       0xc75f1b0f,
11753 +       0x8ce3578f,
11754 +       0x7980a324,
11755 +       0x5daec786,
11756 +};
11757 +
11758 +static __u32 dh_g[] = {
11759 +       1,
11760 +       2,
11761 +};
11762 +
11763 +int main(void)
11764 +{
11765 +       int i;
11766 +       __u32 *k;
11767 +       k = dwc_modpow(NULL, dh_g, dh_a, dh_p);
11768 +
11769 +       printf("\n\n");
11770 +       for (i=0; i<k[0]; i++) {
11771 +               __u32 word32 = k[k[0] - i];
11772 +               __u16 l = word32 & 0xffff;
11773 +               __u16 m = (word32 & 0xffff0000) >> 16;
11774 +               printf("%04x %04x ", m, l);
11775 +               if (!((i + 1)%13)) printf("\n");
11776 +       }
11777 +       printf("\n\n");
11778 +
11779 +       if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
11780 +               printf("PASS\n\n");
11781 +       }
11782 +       else {
11783 +               printf("FAIL\n\n");
11784 +       }
11785 +
11786 +}
11787 +
11788 +#endif /* UNITTEST */
11789 +
11790 +#endif /* CONFIG_MACH_IPMATE */
11791 +
11792 +#endif /*DWC_CRYPTOLIB */
11793 --- /dev/null
11794 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
11795 @@ -0,0 +1,34 @@
11796 +/*
11797 + * dwc_modpow.h
11798 + * See dwc_modpow.c for license and changes
11799 + */
11800 +#ifndef _DWC_MODPOW_H
11801 +#define _DWC_MODPOW_H
11802 +
11803 +#ifdef __cplusplus
11804 +extern "C" {
11805 +#endif
11806 +
11807 +#include "dwc_os.h"
11808 +
11809 +/** @file
11810 + *
11811 + * This file defines the module exponentiation function which is only used
11812 + * internally by the DWC UWB modules for calculation of PKs during numeric
11813 + * association.  The routine is taken from the PUTTY, an open source terminal
11814 + * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.
11815 + *
11816 + */
11817 +
11818 +typedef uint32_t BignumInt;
11819 +typedef uint64_t BignumDblInt;
11820 +typedef BignumInt *Bignum;
11821 +
11822 +/* Compute modular exponentiaion */
11823 +extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);
11824 +
11825 +#ifdef __cplusplus
11826 +}
11827 +#endif
11828 +
11829 +#endif /* _LINUX_BIGNUM_H */
11830 --- /dev/null
11831 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
11832 @@ -0,0 +1,319 @@
11833 +#ifdef DWC_NOTIFYLIB
11834 +
11835 +#include "dwc_notifier.h"
11836 +#include "dwc_list.h"
11837 +
11838 +typedef struct dwc_observer {
11839 +       void *observer;
11840 +       dwc_notifier_callback_t callback;
11841 +       void *data;
11842 +       char *notification;
11843 +       DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
11844 +} observer_t;
11845 +
11846 +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
11847 +
11848 +typedef struct dwc_notifier {
11849 +       void *mem_ctx;
11850 +       void *object;
11851 +       struct observer_queue observers;
11852 +       DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
11853 +} notifier_t;
11854 +
11855 +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
11856 +
11857 +typedef struct manager {
11858 +       void *mem_ctx;
11859 +       void *wkq_ctx;
11860 +       dwc_workq_t *wq;
11861 +//     dwc_mutex_t *mutex;
11862 +       struct notifier_queue notifiers;
11863 +} manager_t;
11864 +
11865 +static manager_t *manager = NULL;
11866 +
11867 +static int create_manager(void *mem_ctx, void *wkq_ctx)
11868 +{
11869 +       manager = dwc_alloc(mem_ctx, sizeof(manager_t));
11870 +       if (!manager) {
11871 +               return -DWC_E_NO_MEMORY;
11872 +       }
11873 +
11874 +       DWC_CIRCLEQ_INIT(&manager->notifiers);
11875 +
11876 +       manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");
11877 +       if (!manager->wq) {
11878 +               return -DWC_E_NO_MEMORY;
11879 +       }
11880 +
11881 +       return 0;
11882 +}
11883 +
11884 +static void free_manager(void)
11885 +{
11886 +       dwc_workq_free(manager->wq);
11887 +
11888 +       /* All notifiers must have unregistered themselves before this module
11889 +        * can be removed.  Hitting this assertion indicates a programmer
11890 +        * error. */
11891 +       DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),
11892 +                  "Notification manager being freed before all notifiers have been removed");
11893 +       dwc_free(manager->mem_ctx, manager);
11894 +}
11895 +
11896 +#ifdef DEBUG
11897 +static void dump_manager(void)
11898 +{
11899 +       notifier_t *n;
11900 +       observer_t *o;
11901 +
11902 +       DWC_ASSERT(manager, "Notification manager not found");
11903 +
11904 +       DWC_DEBUG("List of all notifiers and observers:\n");
11905 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
11906 +               DWC_DEBUG("Notifier %p has observers:\n", n->object);
11907 +               DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
11908 +                       DWC_DEBUG("    %p watching %s\n", o->observer, o->notification);
11909 +               }
11910 +       }
11911 +}
11912 +#else
11913 +#define dump_manager(...)
11914 +#endif
11915 +
11916 +static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,
11917 +                                 dwc_notifier_callback_t callback, void *data)
11918 +{
11919 +       observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));
11920 +
11921 +       if (!new_observer) {
11922 +               return NULL;
11923 +       }
11924 +
11925 +       DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
11926 +       new_observer->observer = observer;
11927 +       new_observer->notification = notification;
11928 +       new_observer->callback = callback;
11929 +       new_observer->data = data;
11930 +       return new_observer;
11931 +}
11932 +
11933 +static void free_observer(void *mem_ctx, observer_t *observer)
11934 +{
11935 +       dwc_free(mem_ctx, observer);
11936 +}
11937 +
11938 +static notifier_t *alloc_notifier(void *mem_ctx, void *object)
11939 +{
11940 +       notifier_t *notifier;
11941 +
11942 +       if (!object) {
11943 +               return NULL;
11944 +       }
11945 +
11946 +       notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));
11947 +       if (!notifier) {
11948 +               return NULL;
11949 +       }
11950 +
11951 +       DWC_CIRCLEQ_INIT(&notifier->observers);
11952 +       DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
11953 +
11954 +       notifier->mem_ctx = mem_ctx;
11955 +       notifier->object = object;
11956 +       return notifier;
11957 +}
11958 +
11959 +static void free_notifier(notifier_t *notifier)
11960 +{
11961 +       observer_t *observer;
11962 +
11963 +       DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
11964 +               free_observer(notifier->mem_ctx, observer);
11965 +       }
11966 +
11967 +       dwc_free(notifier->mem_ctx, notifier);
11968 +}
11969 +
11970 +static notifier_t *find_notifier(void *object)
11971 +{
11972 +       notifier_t *notifier;
11973 +
11974 +       DWC_ASSERT(manager, "Notification manager not found");
11975 +
11976 +       if (!object) {
11977 +               return NULL;
11978 +       }
11979 +
11980 +       DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
11981 +               if (notifier->object == object) {
11982 +                       return notifier;
11983 +               }
11984 +       }
11985 +
11986 +       return NULL;
11987 +}
11988 +
11989 +int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)
11990 +{
11991 +       return create_manager(mem_ctx, wkq_ctx);
11992 +}
11993 +
11994 +void dwc_free_notification_manager(void)
11995 +{
11996 +       free_manager();
11997 +}
11998 +
11999 +dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)
12000 +{
12001 +       notifier_t *notifier;
12002 +
12003 +       DWC_ASSERT(manager, "Notification manager not found");
12004 +
12005 +       notifier = find_notifier(object);
12006 +       if (notifier) {
12007 +               DWC_ERROR("Notifier %p is already registered\n", object);
12008 +               return NULL;
12009 +       }
12010 +
12011 +       notifier = alloc_notifier(mem_ctx, object);
12012 +       if (!notifier) {
12013 +               return NULL;
12014 +       }
12015 +
12016 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
12017 +
12018 +       DWC_INFO("Notifier %p registered", object);
12019 +       dump_manager();
12020 +
12021 +       return notifier;
12022 +}
12023 +
12024 +void dwc_unregister_notifier(dwc_notifier_t *notifier)
12025 +{
12026 +       DWC_ASSERT(manager, "Notification manager not found");
12027 +
12028 +       if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
12029 +               observer_t *o;
12030 +
12031 +               DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);
12032 +               DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12033 +                       DWC_DEBUGC("    %p watching %s\n", o->observer, o->notification);
12034 +               }
12035 +
12036 +               DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers),
12037 +                          "Notifier %p has active observers when removing", notifier);
12038 +       }
12039 +
12040 +       DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
12041 +       free_notifier(notifier);
12042 +
12043 +       DWC_INFO("Notifier unregistered");
12044 +       dump_manager();
12045 +}
12046 +
12047 +/* Add an observer to observe the notifier for a particular state, event, or notification. */
12048 +int dwc_add_observer(void *observer, void *object, char *notification,
12049 +                    dwc_notifier_callback_t callback, void *data)
12050 +{
12051 +       notifier_t *notifier = find_notifier(object);
12052 +       observer_t *new_observer;
12053 +
12054 +       if (!notifier) {
12055 +               DWC_ERROR("Notifier %p is not found when adding observer\n", object);
12056 +               return -DWC_E_INVALID;
12057 +       }
12058 +
12059 +       new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);
12060 +       if (!new_observer) {
12061 +               return -DWC_E_NO_MEMORY;
12062 +       }
12063 +
12064 +       DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
12065 +
12066 +       DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
12067 +                observer, object, notification, callback, data);
12068 +
12069 +       dump_manager();
12070 +       return 0;
12071 +}
12072 +
12073 +int dwc_remove_observer(void *observer)
12074 +{
12075 +       notifier_t *n;
12076 +
12077 +       DWC_ASSERT(manager, "Notification manager not found");
12078 +
12079 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
12080 +               observer_t *o;
12081 +               observer_t *o2;
12082 +
12083 +               DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
12084 +                       if (o->observer == observer) {
12085 +                               DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
12086 +                               DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
12087 +                                        o->observer, n->object, o->notification);
12088 +                               free_observer(n->mem_ctx, o);
12089 +                       }
12090 +               }
12091 +       }
12092 +
12093 +       dump_manager();
12094 +       return 0;
12095 +}
12096 +
12097 +typedef struct callback_data {
12098 +       void *mem_ctx;
12099 +       dwc_notifier_callback_t cb;
12100 +       void *observer;
12101 +       void *data;
12102 +       void *object;
12103 +       char *notification;
12104 +       void *notification_data;
12105 +} cb_data_t;
12106 +
12107 +static void cb_task(void *data)
12108 +{
12109 +       cb_data_t *cb = (cb_data_t *)data;
12110 +
12111 +       cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
12112 +       dwc_free(cb->mem_ctx, cb);
12113 +}
12114 +
12115 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
12116 +{
12117 +       observer_t *o;
12118 +
12119 +       DWC_ASSERT(manager, "Notification manager not found");
12120 +
12121 +       DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12122 +               int len = DWC_STRLEN(notification);
12123 +
12124 +               if (DWC_STRLEN(o->notification) != len) {
12125 +                       continue;
12126 +               }
12127 +
12128 +               if (DWC_STRNCMP(o->notification, notification, len) == 0) {
12129 +                       cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));
12130 +
12131 +                       if (!cb_data) {
12132 +                               DWC_ERROR("Failed to allocate callback data\n");
12133 +                               return;
12134 +                       }
12135 +
12136 +                       cb_data->mem_ctx = notifier->mem_ctx;
12137 +                       cb_data->cb = o->callback;
12138 +                       cb_data->observer = o->observer;
12139 +                       cb_data->data = o->data;
12140 +                       cb_data->object = notifier->object;
12141 +                       cb_data->notification = notification;
12142 +                       cb_data->notification_data = notification_data;
12143 +                       DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);
12144 +                       DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
12145 +                                          "Notify callback from %p for Notification %s, to observer %p",
12146 +                                          cb_data->object, notification, cb_data->observer);
12147 +               }
12148 +       }
12149 +}
12150 +
12151 +#endif /* DWC_NOTIFYLIB */
12152 --- /dev/null
12153 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
12154 @@ -0,0 +1,122 @@
12155 +
12156 +#ifndef __DWC_NOTIFIER_H__
12157 +#define __DWC_NOTIFIER_H__
12158 +
12159 +#ifdef __cplusplus
12160 +extern "C" {
12161 +#endif
12162 +
12163 +#include "dwc_os.h"
12164 +
12165 +/** @file
12166 + *
12167 + * A simple implementation of the Observer pattern.  Any "module" can
12168 + * register as an observer or notifier.  The notion of "module" is abstract and
12169 + * can mean anything used to identify either an observer or notifier.  Usually
12170 + * it will be a pointer to a data structure which contains some state, ie an
12171 + * object.
12172 + *
12173 + * Before any notifiers can be added, the global notification manager must be
12174 + * brought up with dwc_alloc_notification_manager().
12175 + * dwc_free_notification_manager() will bring it down and free all resources.
12176 + * These would typically be called upon module load and unload.  The
12177 + * notification manager is a single global instance that handles all registered
12178 + * observable modules and observers so this should be done only once.
12179 + *
12180 + * A module can be observable by using Notifications to publicize some general
12181 + * information about it's state or operation.  It does not care who listens, or
12182 + * even if anyone listens, or what they do with the information.  The observable
12183 + * modules do not need to know any information about it's observers or their
12184 + * interface, or their state or data.
12185 + *
12186 + * Any module can register to emit Notifications.  It should publish a list of
12187 + * notifications that it can emit and their behavior, such as when they will get
12188 + * triggered, and what information will be provided to the observer.  Then it
12189 + * should register itself as an observable module. See dwc_register_notifier().
12190 + *
12191 + * Any module can observe any observable, registered module, provided it has a
12192 + * handle to the other module and knows what notifications to observe.  See
12193 + * dwc_add_observer().
12194 + *
12195 + * A function of type dwc_notifier_callback_t is called whenever a notification
12196 + * is triggered with one or more observers observing it.  This function is
12197 + * called in it's own process so it may sleep or block if needed.  It is
12198 + * guaranteed to be called sometime after the notification has occurred and will
12199 + * be called once per each time the notification is triggered.  It will NOT be
12200 + * called in the same process context used to trigger the notification.
12201 + *
12202 + * @section Limitiations
12203 + *
12204 + * Keep in mind that Notifications that can be triggered in rapid sucession may
12205 + * schedule too many processes too handle.  Be aware of this limitation when
12206 + * designing to use notifications, and only add notifications for appropriate
12207 + * observable information.
12208 + *
12209 + * Also Notification callbacks are not synchronous.  If you need to synchronize
12210 + * the behavior between module/observer you must use other means.  And perhaps
12211 + * that will mean Notifications are not the proper solution.
12212 + */
12213 +
12214 +struct dwc_notifier;
12215 +typedef struct dwc_notifier dwc_notifier_t;
12216 +
12217 +/** The callback function must be of this type.
12218 + *
12219 + * @param object This is the object that is being observed.
12220 + * @param notification This is the notification that was triggered.
12221 + * @param observer This is the observer
12222 + * @param notification_data This is notification-specific data that the notifier
12223 + * has included in this notification.  The value of this should be published in
12224 + * the documentation of the observable module with the notifications.
12225 + * @param user_data This is any custom data that the observer provided when
12226 + * adding itself as an observer to the notification. */
12227 +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
12228 +                                       void *notification_data, void *user_data);
12229 +
12230 +/** Brings up the notification manager. */
12231 +extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
12232 +/** Brings down the notification manager. */
12233 +extern void dwc_free_notification_manager(void);
12234 +
12235 +/** This function registers an observable module.  A dwc_notifier_t object is
12236 + * returned to the observable module.  This is an opaque object that is used by
12237 + * the observable module to trigger notifications.  This object should only be
12238 + * accessible to functions that are authorized to trigger notifications for this
12239 + * module.  Observers do not need this object. */
12240 +extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
12241 +
12242 +/** This function unregisters an observable module.  All observers have to be
12243 + * removed prior to unregistration. */
12244 +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
12245 +
12246 +/** Add a module as an observer to the observable module.  The observable module
12247 + * needs to have previously registered with the notification manager.
12248 + *
12249 + * @param observer The observer module
12250 + * @param object The module to observe
12251 + * @param notification The notification to observe
12252 + * @param callback The callback function to call
12253 + * @param user_data Any additional user data to pass into the callback function */
12254 +extern int dwc_add_observer(void *observer, void *object, char *notification,
12255 +                           dwc_notifier_callback_t callback, void *user_data);
12256 +
12257 +/** Removes the specified observer from all notifications that it is currently
12258 + * observing. */
12259 +extern int dwc_remove_observer(void *observer);
12260 +
12261 +/** This function triggers a Notification.  It should be called by the
12262 + * observable module, or any module or library which the observable module
12263 + * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.
12264 + *
12265 + * dwc_notify is a non-blocking function.  Callbacks are scheduled called in
12266 + * their own process context for each trigger.  Callbacks can be blocking.
12267 + * dwc_notify can be called from interrupt context if needed.
12268 + *
12269 + */
12270 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
12271 +
12272 +#ifdef __cplusplus
12273 +}
12274 +#endif
12275 +
12276 +#endif /* __DWC_NOTIFIER_H__ */
12277 --- /dev/null
12278 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
12279 @@ -0,0 +1,1274 @@
12280 +/* =========================================================================
12281 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
12282 + * $Revision: #14 $
12283 + * $Date: 2010/11/04 $
12284 + * $Change: 1621695 $
12285 + *
12286 + * Synopsys Portability Library Software and documentation
12287 + * (hereinafter, "Software") is an Unsupported proprietary work of
12288 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
12289 + * between Synopsys and you.
12290 + *
12291 + * The Software IS NOT an item of Licensed Software or Licensed Product
12292 + * under any End User Software License Agreement or Agreement for
12293 + * Licensed Product with Synopsys or any supplement thereto. You are
12294 + * permitted to use and redistribute this Software in source and binary
12295 + * forms, with or without modification, provided that redistributions
12296 + * of source code must retain this notice. You may not view, use,
12297 + * disclose, copy or distribute this file or any information contained
12298 + * herein except pursuant to this license grant from Synopsys. If you
12299 + * do not agree with this notice, including the disclaimer below, then
12300 + * you are not authorized to use the Software.
12301 + *
12302 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
12303 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12304 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12305 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
12306 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
12307 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
12308 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
12309 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
12310 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12311 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
12312 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12313 + * DAMAGE.
12314 + * ========================================================================= */
12315 +#ifndef _DWC_OS_H_
12316 +#define _DWC_OS_H_
12317 +
12318 +#ifdef __cplusplus
12319 +extern "C" {
12320 +#endif
12321 +
12322 +/** @file
12323 + *
12324 + * DWC portability library, low level os-wrapper functions
12325 + *
12326 + */
12327 +
12328 +/* These basic types need to be defined by some OS header file or custom header
12329 + * file for your specific target architecture.
12330 + *
12331 + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
12332 + *
12333 + * Any custom or alternate header file must be added and enabled here.
12334 + */
12335 +
12336 +#ifdef DWC_LINUX
12337 +# include <linux/types.h>
12338 +# ifdef CONFIG_DEBUG_MUTEXES
12339 +#  include <linux/mutex.h>
12340 +# endif
12341 +# include <linux/spinlock.h>
12342 +# include <linux/errno.h>
12343 +# include <stdarg.h>
12344 +#endif
12345 +
12346 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12347 +# include <os_dep.h>
12348 +#endif
12349 +
12350 +
12351 +/** @name Primitive Types and Values */
12352 +
12353 +/** We define a boolean type for consistency.  Can be either YES or NO */
12354 +typedef uint8_t dwc_bool_t;
12355 +#define YES  1
12356 +#define NO   0
12357 +
12358 +#ifdef DWC_LINUX
12359 +
12360 +/** @name Error Codes */
12361 +#define DWC_E_INVALID          EINVAL
12362 +#define DWC_E_NO_MEMORY                ENOMEM
12363 +#define DWC_E_NO_DEVICE                ENODEV
12364 +#define DWC_E_NOT_SUPPORTED    EOPNOTSUPP
12365 +#define DWC_E_TIMEOUT          ETIMEDOUT
12366 +#define DWC_E_BUSY             EBUSY
12367 +#define DWC_E_AGAIN            EAGAIN
12368 +#define DWC_E_RESTART          ERESTART
12369 +#define DWC_E_ABORT            ECONNABORTED
12370 +#define DWC_E_SHUTDOWN         ESHUTDOWN
12371 +#define DWC_E_NO_DATA          ENODATA
12372 +#define DWC_E_DISCONNECT       ECONNRESET
12373 +#define DWC_E_UNKNOWN          EINVAL
12374 +#define DWC_E_NO_STREAM_RES    ENOSR
12375 +#define DWC_E_COMMUNICATION    ECOMM
12376 +#define DWC_E_OVERFLOW         EOVERFLOW
12377 +#define DWC_E_PROTOCOL         EPROTO
12378 +#define DWC_E_IN_PROGRESS      EINPROGRESS
12379 +#define DWC_E_PIPE             EPIPE
12380 +#define DWC_E_IO               EIO
12381 +#define DWC_E_NO_SPACE         ENOSPC
12382 +
12383 +#else
12384 +
12385 +/** @name Error Codes */
12386 +#define DWC_E_INVALID          1001
12387 +#define DWC_E_NO_MEMORY                1002
12388 +#define DWC_E_NO_DEVICE                1003
12389 +#define DWC_E_NOT_SUPPORTED    1004
12390 +#define DWC_E_TIMEOUT          1005
12391 +#define DWC_E_BUSY             1006
12392 +#define DWC_E_AGAIN            1007
12393 +#define DWC_E_RESTART          1008
12394 +#define DWC_E_ABORT            1009
12395 +#define DWC_E_SHUTDOWN         1010
12396 +#define DWC_E_NO_DATA          1011
12397 +#define DWC_E_DISCONNECT       2000
12398 +#define DWC_E_UNKNOWN          3000
12399 +#define DWC_E_NO_STREAM_RES    4001
12400 +#define DWC_E_COMMUNICATION    4002
12401 +#define DWC_E_OVERFLOW         4003
12402 +#define DWC_E_PROTOCOL         4004
12403 +#define DWC_E_IN_PROGRESS      4005
12404 +#define DWC_E_PIPE             4006
12405 +#define DWC_E_IO               4007
12406 +#define DWC_E_NO_SPACE         4008
12407 +
12408 +#endif
12409 +
12410 +
12411 +/** @name Tracing/Logging Functions
12412 + *
12413 + * These function provide the capability to add tracing, debugging, and error
12414 + * messages, as well exceptions as assertions.  The WUDEV uses these
12415 + * extensively.  These could be logged to the main console, the serial port, an
12416 + * internal buffer, etc.  These functions could also be no-op if they are too
12417 + * expensive on your system.  By default undefining the DEBUG macro already
12418 + * no-ops some of these functions. */
12419 +
12420 +/** Returns non-zero if in interrupt context. */
12421 +extern dwc_bool_t DWC_IN_IRQ(void);
12422 +#define dwc_in_irq DWC_IN_IRQ
12423 +
12424 +/** Returns "IRQ" if DWC_IN_IRQ is true. */
12425 +static inline char *dwc_irq(void) {
12426 +       return DWC_IN_IRQ() ? "IRQ" : "";
12427 +}
12428 +
12429 +/** Returns non-zero if in bottom-half context. */
12430 +extern dwc_bool_t DWC_IN_BH(void);
12431 +#define dwc_in_bh DWC_IN_BH
12432 +
12433 +/** Returns "BH" if DWC_IN_BH is true. */
12434 +static inline char *dwc_bh(void) {
12435 +       return DWC_IN_BH() ? "BH" : "";
12436 +}
12437 +
12438 +/**
12439 + * A vprintf() clone.  Just call vprintf if you've got it.
12440 + */
12441 +extern void DWC_VPRINTF(char *format, va_list args);
12442 +#define dwc_vprintf DWC_VPRINTF
12443 +
12444 +/**
12445 + * A vsnprintf() clone.  Just call vprintf if you've got it.
12446 + */
12447 +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
12448 +#define dwc_vsnprintf DWC_VSNPRINTF
12449 +
12450 +/**
12451 + * printf() clone.  Just call printf if you've go it.
12452 + */
12453 +extern void DWC_PRINTF(char *format, ...)
12454 +/* This provides compiler level static checking of the parameters if you're
12455 + * using GCC. */
12456 +#ifdef __GNUC__
12457 +       __attribute__ ((format(printf, 1, 2)));
12458 +#else
12459 +       ;
12460 +#endif
12461 +#define dwc_printf DWC_PRINTF
12462 +
12463 +/**
12464 + * sprintf() clone.  Just call sprintf if you've got it.
12465 + */
12466 +extern int DWC_SPRINTF(char *string, char *format, ...)
12467 +#ifdef __GNUC__
12468 +       __attribute__ ((format(printf, 2, 3)));
12469 +#else
12470 +       ;
12471 +#endif
12472 +#define dwc_sprintf DWC_SPRINTF
12473 +
12474 +/**
12475 + * snprintf() clone.  Just call snprintf if you've got it.
12476 + */
12477 +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
12478 +#ifdef __GNUC__
12479 +       __attribute__ ((format(printf, 3, 4)));
12480 +#else
12481 +       ;
12482 +#endif
12483 +#define dwc_snprintf DWC_SNPRINTF
12484 +
12485 +/**
12486 + * Prints a WARNING message.  On systems that don't differentiate between
12487 + * warnings and regular log messages, just print it.  Indicates that something
12488 + * may be wrong with the driver.  Works like printf().
12489 + *
12490 + * Use the DWC_WARN macro to call this function.
12491 + */
12492 +extern void __DWC_WARN(char *format, ...)
12493 +#ifdef __GNUC__
12494 +       __attribute__ ((format(printf, 1, 2)));
12495 +#else
12496 +       ;
12497 +#endif
12498 +
12499 +/**
12500 + * Prints an error message.  On systems that don't differentiate between errors
12501 + * and regular log messages, just print it.  Indicates that something went wrong
12502 + * with the driver.  Works like printf().
12503 + *
12504 + * Use the DWC_ERROR macro to call this function.
12505 + */
12506 +extern void __DWC_ERROR(char *format, ...)
12507 +#ifdef __GNUC__
12508 +       __attribute__ ((format(printf, 1, 2)));
12509 +#else
12510 +       ;
12511 +#endif
12512 +
12513 +/**
12514 + * Prints an exception error message and takes some user-defined action such as
12515 + * print out a backtrace or trigger a breakpoint.  Indicates that something went
12516 + * abnormally wrong with the driver such as programmer error, or other
12517 + * exceptional condition.  It should not be ignored so even on systems without
12518 + * printing capability, some action should be taken to notify the developer of
12519 + * it.  Works like printf().
12520 + */
12521 +extern void DWC_EXCEPTION(char *format, ...)
12522 +#ifdef __GNUC__
12523 +       __attribute__ ((format(printf, 1, 2)));
12524 +#else
12525 +       ;
12526 +#endif
12527 +#define dwc_exception DWC_EXCEPTION
12528 +
12529 +#ifndef DWC_OTG_DEBUG_LEV
12530 +#define DWC_OTG_DEBUG_LEV 0
12531 +#endif
12532 +
12533 +#ifdef DEBUG
12534 +/**
12535 + * Prints out a debug message.  Used for logging/trace messages.
12536 + *
12537 + * Use the DWC_DEBUG macro to call this function
12538 + */
12539 +extern void __DWC_DEBUG(char *format, ...)
12540 +#ifdef __GNUC__
12541 +       __attribute__ ((format(printf, 1, 2)));
12542 +#else
12543 +       ;
12544 +#endif
12545 +#else
12546 +#define __DWC_DEBUG printk
12547 +#endif
12548 +
12549 +/**
12550 + * Prints out a Debug message.
12551 + */
12552 +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
12553 +                                                __func__, dwc_irq(), ## _args)
12554 +#define dwc_debug DWC_DEBUG
12555 +/**
12556 + * Prints out a Debug message if enabled at compile time.
12557 + */
12558 +#if DWC_OTG_DEBUG_LEV > 0
12559 +#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
12560 +#else
12561 +#define DWC_DEBUGC(_format, _args...)
12562 +#endif
12563 +#define dwc_debugc DWC_DEBUGC
12564 +/**
12565 + * Prints out an informative message.
12566 + */
12567 +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
12568 +                                              dwc_irq(), ## _args)
12569 +#define dwc_info DWC_INFO
12570 +/**
12571 + * Prints out an informative message if enabled at compile time.
12572 + */
12573 +#if DWC_OTG_DEBUG_LEV > 1
12574 +#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
12575 +#else
12576 +#define DWC_INFOC(_format, _args...)
12577 +#endif
12578 +#define dwc_infoc DWC_INFOC
12579 +/**
12580 + * Prints out a warning message.
12581 + */
12582 +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
12583 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12584 +#define dwc_warn DWC_WARN
12585 +/**
12586 + * Prints out an error message.
12587 + */
12588 +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
12589 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12590 +#define dwc_error DWC_ERROR
12591 +
12592 +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
12593 +                                               dwc_irq(), __func__, __LINE__, ## _args)
12594 +#define dwc_proto_error DWC_PROTO_ERROR
12595 +
12596 +#ifdef DEBUG
12597 +/** Prints out a exception error message if the _expr expression fails.  Disabled
12598 + * if DEBUG is not enabled. */
12599 +#define DWC_ASSERT(_expr, _format, _args...) do { \
12600 +       if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
12601 +                                     __FILE__, __LINE__, ## _args); } \
12602 +       } while (0)
12603 +#else
12604 +#define DWC_ASSERT(_x...)
12605 +#endif
12606 +#define dwc_assert DWC_ASSERT
12607 +
12608 +
12609 +/** @name Byte Ordering
12610 + * The following functions are for conversions between processor's byte ordering
12611 + * and specific ordering you want.
12612 + */
12613 +
12614 +/** Converts 32 bit data in CPU byte ordering to little endian. */
12615 +extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
12616 +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
12617 +
12618 +/** Converts 32 bit data in CPU byte orderint to big endian. */
12619 +extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
12620 +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
12621 +
12622 +/** Converts 32 bit little endian data to CPU byte ordering. */
12623 +extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
12624 +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
12625 +
12626 +/** Converts 32 bit big endian data to CPU byte ordering. */
12627 +extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
12628 +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
12629 +
12630 +/** Converts 16 bit data in CPU byte ordering to little endian. */
12631 +extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
12632 +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
12633 +
12634 +/** Converts 16 bit data in CPU byte orderint to big endian. */
12635 +extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
12636 +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
12637 +
12638 +/** Converts 16 bit little endian data to CPU byte ordering. */
12639 +extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
12640 +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
12641 +
12642 +/** Converts 16 bit bi endian data to CPU byte ordering. */
12643 +extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
12644 +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
12645 +
12646 +
12647 +/** @name Register Read/Write
12648 + *
12649 + * The following six functions should be implemented to read/write registers of
12650 + * 32-bit and 64-bit sizes.  All modules use this to read/write register values.
12651 + * The reg value is a pointer to the register calculated from the void *base
12652 + * variable passed into the driver when it is started.  */
12653 +
12654 +#ifdef DWC_LINUX
12655 +/* Linux doesn't need any extra parameters for register read/write, so we
12656 + * just throw away the IO context parameter.
12657 + */
12658 +/** Reads the content of a 32-bit register. */
12659 +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
12660 +#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
12661 +
12662 +/** Reads the content of a 64-bit register. */
12663 +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
12664 +#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
12665 +
12666 +/** Writes to a 32-bit register. */
12667 +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
12668 +#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
12669 +
12670 +/** Writes to a 64-bit register. */
12671 +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
12672 +#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
12673 +
12674 +/**
12675 + * Modify bit values in a register.  Using the
12676 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12677 + */
12678 +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12679 +#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
12680 +extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12681 +#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
12682 +
12683 +#endif /* DWC_LINUX */
12684 +
12685 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12686 +typedef struct dwc_ioctx {
12687 +       struct device *dev;
12688 +       bus_space_tag_t iot;
12689 +       bus_space_handle_t ioh;
12690 +} dwc_ioctx_t;
12691 +
12692 +/** BSD needs two extra parameters for register read/write, so we pass
12693 + * them in using the IO context parameter.
12694 + */
12695 +/** Reads the content of a 32-bit register. */
12696 +extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
12697 +#define dwc_read_reg32 DWC_READ_REG32
12698 +
12699 +/** Reads the content of a 64-bit register. */
12700 +extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
12701 +#define dwc_read_reg64 DWC_READ_REG64
12702 +
12703 +/** Writes to a 32-bit register. */
12704 +extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
12705 +#define dwc_write_reg32 DWC_WRITE_REG32
12706 +
12707 +/** Writes to a 64-bit register. */
12708 +extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
12709 +#define dwc_write_reg64 DWC_WRITE_REG64
12710 +
12711 +/**
12712 + * Modify bit values in a register.  Using the
12713 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12714 + */
12715 +extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12716 +#define dwc_modify_reg32 DWC_MODIFY_REG32
12717 +extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12718 +#define dwc_modify_reg64 DWC_MODIFY_REG64
12719 +
12720 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12721 +
12722 +/** @cond */
12723 +
12724 +/** @name Some convenience MACROS used internally.  Define DWC_DEBUG_REGS to log the
12725 + * register writes. */
12726 +
12727 +#ifdef DWC_LINUX
12728 +
12729 +# ifdef DWC_DEBUG_REGS
12730 +
12731 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12732 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12733 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12734 +} \
12735 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12736 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12737 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12738 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12739 +}
12740 +
12741 +#define dwc_define_read_write_reg(_reg,_container_type) \
12742 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12743 +       return DWC_READ_REG32(&container->regs->_reg); \
12744 +} \
12745 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12746 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12747 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12748 +}
12749 +
12750 +# else /* DWC_DEBUG_REGS */
12751 +
12752 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12753 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12754 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12755 +} \
12756 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12757 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12758 +}
12759 +
12760 +#define dwc_define_read_write_reg(_reg,_container_type) \
12761 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12762 +       return DWC_READ_REG32(&container->regs->_reg); \
12763 +} \
12764 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12765 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12766 +}
12767 +
12768 +# endif        /* DWC_DEBUG_REGS */
12769 +
12770 +#endif /* DWC_LINUX */
12771 +
12772 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12773 +
12774 +# ifdef DWC_DEBUG_REGS
12775 +
12776 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12777 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12778 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12779 +} \
12780 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12781 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12782 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12783 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12784 +}
12785 +
12786 +#define dwc_define_read_write_reg(_reg,_container_type) \
12787 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12788 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12789 +} \
12790 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12791 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12792 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12793 +}
12794 +
12795 +# else /* DWC_DEBUG_REGS */
12796 +
12797 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12798 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12799 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12800 +} \
12801 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12802 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12803 +}
12804 +
12805 +#define dwc_define_read_write_reg(_reg,_container_type) \
12806 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12807 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12808 +} \
12809 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12810 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12811 +}
12812 +
12813 +# endif        /* DWC_DEBUG_REGS */
12814 +
12815 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12816 +
12817 +/** @endcond */
12818 +
12819 +
12820 +#ifdef DWC_CRYPTOLIB
12821 +/** @name Crypto Functions
12822 + *
12823 + * These are the low-level cryptographic functions used by the driver. */
12824 +
12825 +/** Perform AES CBC */
12826 +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
12827 +#define dwc_aes_cbc DWC_AES_CBC
12828 +
12829 +/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */
12830 +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
12831 +#define dwc_random_bytes DWC_RANDOM_BYTES
12832 +
12833 +/** Perform the SHA-256 hash function */
12834 +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
12835 +#define dwc_sha256 DWC_SHA256
12836 +
12837 +/** Calculated the HMAC-SHA256 */
12838 +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
12839 +#define dwc_hmac_sha256 DWC_HMAC_SHA256
12840 +
12841 +#endif /* DWC_CRYPTOLIB */
12842 +
12843 +
12844 +/** @name Memory Allocation
12845 + *
12846 + * These function provide access to memory allocation.  There are only 2 DMA
12847 + * functions and 3 Regular memory functions that need to be implemented.  None
12848 + * of the memory debugging routines need to be implemented.  The allocation
12849 + * routines all ZERO the contents of the memory.
12850 + *
12851 + * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
12852 + * This checks for memory leaks, keeping track of alloc/free pairs.  It also
12853 + * keeps track of how much memory the driver is using at any given time. */
12854 +
12855 +#define DWC_PAGE_SIZE 4096
12856 +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
12857 +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
12858 +
12859 +#define DWC_INVALID_DMA_ADDR 0x0
12860 +
12861 +#ifdef DWC_LINUX
12862 +/** Type for a DMA address */
12863 +typedef dma_addr_t dwc_dma_t;
12864 +#endif
12865 +
12866 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12867 +typedef bus_addr_t dwc_dma_t;
12868 +#endif
12869 +
12870 +#ifdef DWC_FREEBSD
12871 +typedef struct dwc_dmactx {
12872 +       struct device *dev;
12873 +       bus_dma_tag_t dma_tag;
12874 +       bus_dmamap_t dma_map;
12875 +       bus_addr_t dma_paddr;
12876 +       void *dma_vaddr;
12877 +} dwc_dmactx_t;
12878 +#endif
12879 +
12880 +#ifdef DWC_NETBSD
12881 +typedef struct dwc_dmactx {
12882 +       struct device *dev;
12883 +       bus_dma_tag_t dma_tag;
12884 +       bus_dmamap_t dma_map;
12885 +       bus_dma_segment_t segs[1];
12886 +       int nsegs;
12887 +       bus_addr_t dma_paddr;
12888 +       void *dma_vaddr;
12889 +} dwc_dmactx_t;
12890 +#endif
12891 +
12892 +/* @todo these functions will be added in the future */
12893 +#if 0
12894 +/**
12895 + * Creates a DMA pool from which you can allocate DMA buffers.  Buffers
12896 + * allocated from this pool will be guaranteed to meet the size, alignment, and
12897 + * boundary requirements specified.
12898 + *
12899 + * @param[in] size Specifies the size of the buffers that will be allocated from
12900 + * this pool.
12901 + * @param[in] align Specifies the byte alignment requirements of the buffers
12902 + * allocated from this pool.  Must be a power of 2.
12903 + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
12904 + * this pool must not cross.
12905 + *
12906 + * @returns A pointer to an internal opaque structure which is not to be
12907 + * accessed outside of these library functions.  Use this handle to specify
12908 + * which pools to allocate/free DMA buffers from and also to destroy the pool,
12909 + * when you are done with it.
12910 + */
12911 +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
12912 +
12913 +/**
12914 + * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.
12915 + */
12916 +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
12917 +
12918 +/**
12919 + * Allocate a buffer from the specified DMA pool and zeros its contents.
12920 + */
12921 +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
12922 +
12923 +/**
12924 + * Free a previously allocated buffer from the DMA pool.
12925 + */
12926 +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
12927 +#endif
12928 +
12929 +/** Allocates a DMA capable buffer and zeroes its contents. */
12930 +extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
12931 +
12932 +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
12933 +extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
12934 +
12935 +/** Frees a previously allocated buffer. */
12936 +extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
12937 +
12938 +/** Allocates a block of memory and zeroes its contents. */
12939 +extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
12940 +
12941 +/** Allocates a block of memory and zeroes its contents, in an atomic manner
12942 + * which can be used inside interrupt context.  The size should be sufficiently
12943 + * small, a few KB at most, such that failures are not likely to occur.  Can just call
12944 + * __DWC_ALLOC if it is atomic. */
12945 +extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
12946 +
12947 +/** Frees a previously allocated buffer. */
12948 +extern void __DWC_FREE(void *mem_ctx, void *addr);
12949 +
12950 +#ifndef DWC_DEBUG_MEMORY
12951 +
12952 +#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
12953 +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
12954 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
12955 +
12956 +# ifdef DWC_LINUX
12957 +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)
12958 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)
12959 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)
12960 +# endif
12961 +
12962 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12963 +#define DWC_DMA_ALLOC __DWC_DMA_ALLOC
12964 +#define DWC_DMA_FREE __DWC_DMA_FREE
12965 +# endif
12966 +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
12967 +
12968 +#else  /* DWC_DEBUG_MEMORY */
12969 +
12970 +extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
12971 +extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
12972 +extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
12973 +extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
12974 +                                char const *func, int line);
12975 +extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
12976 +                               char const *func, int line);
12977 +extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
12978 +                              dwc_dma_t dma_addr, char const *func, int line);
12979 +
12980 +extern int dwc_memory_debug_start(void *mem_ctx);
12981 +extern void dwc_memory_debug_stop(void);
12982 +extern void dwc_memory_debug_report(void);
12983 +
12984 +#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
12985 +#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
12986 +                                                       __func__, __LINE__)
12987 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
12988 +
12989 +# ifdef DWC_LINUX
12990 +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \
12991 +                                               _dma_, __func__, __LINE__)
12992 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \
12993 +                                               _dma_, __func__, __LINE__)
12994 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \
12995 +                                               _virt_, _dma_, __func__, __LINE__)
12996 +# endif
12997 +
12998 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12999 +#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
13000 +                                               _dma_, __func__, __LINE__)
13001 +#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
13002 +                                                _virt_, _dma_, __func__, __LINE__)
13003 +# endif
13004 +
13005 +#endif /* DWC_DEBUG_MEMORY */
13006 +
13007 +#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
13008 +#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
13009 +#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
13010 +
13011 +#ifdef DWC_LINUX
13012 +/* Linux doesn't need any extra parameters for DMA buffer allocation, so we
13013 + * just throw away the DMA context parameter.
13014 + */
13015 +#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
13016 +#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
13017 +#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
13018 +#endif
13019 +
13020 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13021 +/** BSD needs several extra parameters for DMA buffer allocation, so we pass
13022 + * them in using the DMA context parameter.
13023 + */
13024 +#define dwc_dma_alloc DWC_DMA_ALLOC
13025 +#define dwc_dma_free DWC_DMA_FREE
13026 +#endif
13027 +
13028 +
13029 +/** @name Memory and String Processing */
13030 +
13031 +/** memset() clone */
13032 +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
13033 +#define dwc_memset DWC_MEMSET
13034 +
13035 +/** memcpy() clone */
13036 +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
13037 +#define dwc_memcpy DWC_MEMCPY
13038 +
13039 +/** memmove() clone */
13040 +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
13041 +#define dwc_memmove DWC_MEMMOVE
13042 +
13043 +/** memcmp() clone */
13044 +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
13045 +#define dwc_memcmp DWC_MEMCMP
13046 +
13047 +/** strcmp() clone */
13048 +extern int DWC_STRCMP(void *s1, void *s2);
13049 +#define dwc_strcmp DWC_STRCMP
13050 +
13051 +/** strncmp() clone */
13052 +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
13053 +#define dwc_strncmp DWC_STRNCMP
13054 +
13055 +/** strlen() clone, for NULL terminated ASCII strings */
13056 +extern int DWC_STRLEN(char const *str);
13057 +#define dwc_strlen DWC_STRLEN
13058 +
13059 +/** strcpy() clone, for NULL terminated ASCII strings */
13060 +extern char *DWC_STRCPY(char *to, const char *from);
13061 +#define dwc_strcpy DWC_STRCPY
13062 +
13063 +/** strdup() clone.  If you wish to use memory allocation debugging, this
13064 + * implementation of strdup should use the DWC_* memory routines instead of
13065 + * calling a predefined strdup.  Otherwise the memory allocated by this routine
13066 + * will not be seen by the debugging routines. */
13067 +extern char *DWC_STRDUP(char const *str);
13068 +#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
13069 +
13070 +/** NOT an atoi() clone.  Read the description carefully.  Returns an integer
13071 + * converted from the string str in base 10 unless the string begins with a "0x"
13072 + * in which case it is base 16.  String must be a NULL terminated sequence of
13073 + * ASCII characters and may optionally begin with whitespace, a + or -, and a
13074 + * "0x" prefix if base 16.  The remaining characters must be valid digits for
13075 + * the number and end with a NULL character.  If any invalid characters are
13076 + * encountered or it returns with a negative error code and the results of the
13077 + * conversion are undefined.  On sucess it returns 0.  Overflow conditions are
13078 + * undefined.  An example implementation using atoi() can be referenced from the
13079 + * Linux implementation. */
13080 +extern int DWC_ATOI(const char *str, int32_t *value);
13081 +#define dwc_atoi DWC_ATOI
13082 +
13083 +/** Same as above but for unsigned. */
13084 +extern int DWC_ATOUI(const char *str, uint32_t *value);
13085 +#define dwc_atoui DWC_ATOUI
13086 +
13087 +#ifdef DWC_UTFLIB
13088 +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
13089 +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
13090 +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
13091 +#endif
13092 +
13093 +
13094 +/** @name Wait queues
13095 + *
13096 + * Wait queues provide a means of synchronizing between threads or processes.  A
13097 + * process can block on a waitq if some condition is not true, waiting for it to
13098 + * become true.  When the waitq is triggered all waiting process will get
13099 + * unblocked and the condition will be check again.  Waitqs should be triggered
13100 + * every time a condition can potentially change.*/
13101 +struct dwc_waitq;
13102 +
13103 +/** Type for a waitq */
13104 +typedef struct dwc_waitq dwc_waitq_t;
13105 +
13106 +/** The type of waitq condition callback function.  This is called every time
13107 + * condition is evaluated. */
13108 +typedef int (*dwc_waitq_condition_t)(void *data);
13109 +
13110 +/** Allocate a waitq */
13111 +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
13112 +#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
13113 +
13114 +/** Free a waitq */
13115 +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
13116 +#define dwc_waitq_free DWC_WAITQ_FREE
13117 +
13118 +/** Check the condition and if it is false, block on the waitq.  When unblocked, check the
13119 + * condition again.  The function returns when the condition becomes true.  The return value
13120 + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
13121 +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
13122 +#define dwc_waitq_wait DWC_WAITQ_WAIT
13123 +
13124 +/** Check the condition and if it is false, block on the waitq.  When unblocked,
13125 + * check the condition again.  The function returns when the condition become
13126 + * true or the timeout has passed.  The return value is 0 on condition true or
13127 + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
13128 + * error. */
13129 +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
13130 +                                     void *data, int32_t msecs);
13131 +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
13132 +
13133 +/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition
13134 + * has potentially changed. */
13135 +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
13136 +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
13137 +
13138 +/** Unblock all processes waiting on the waitq with an ABORTED result. */
13139 +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
13140 +#define dwc_waitq_abort DWC_WAITQ_ABORT
13141 +
13142 +
13143 +/** @name Threads
13144 + *
13145 + * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP
13146 + * whenever it is woken up, and then return.  The DWC_THREAD_STOP function
13147 + * returns the value from the thread.
13148 + */
13149 +
13150 +struct dwc_thread;
13151 +
13152 +/** Type for a thread */
13153 +typedef struct dwc_thread dwc_thread_t;
13154 +
13155 +/** The thread function */
13156 +typedef int (*dwc_thread_function_t)(void *data);
13157 +
13158 +/** Create a thread and start it running the thread_function.  Returns a handle
13159 + * to the thread */
13160 +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
13161 +#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
13162 +
13163 +/** Stops a thread.  Return the value returned by the thread.  Or will return
13164 + * DWC_ABORT if the thread never started. */
13165 +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
13166 +#define dwc_thread_stop DWC_THREAD_STOP
13167 +
13168 +/** Signifies to the thread that it must stop. */
13169 +#ifdef DWC_LINUX
13170 +/* Linux doesn't need any parameters for kthread_should_stop() */
13171 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
13172 +#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
13173 +
13174 +/* No thread_exit function in Linux */
13175 +#define dwc_thread_exit(_thrd_)
13176 +#endif
13177 +
13178 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13179 +/** BSD needs the thread pointer for kthread_suspend_check() */
13180 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
13181 +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
13182 +
13183 +/** The thread must call this to exit. */
13184 +extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
13185 +#define dwc_thread_exit DWC_THREAD_EXIT
13186 +#endif
13187 +
13188 +
13189 +/** @name Work queues
13190 + *
13191 + * Workqs are used to queue a callback function to be called at some later time,
13192 + * in another thread. */
13193 +struct dwc_workq;
13194 +
13195 +/** Type for a workq */
13196 +typedef struct dwc_workq dwc_workq_t;
13197 +
13198 +/** The type of the callback function to be called. */
13199 +typedef void (*dwc_work_callback_t)(void *data);
13200 +
13201 +/** Allocate a workq */
13202 +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
13203 +#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
13204 +
13205 +/** Free a workq.  All work must be completed before being freed. */
13206 +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
13207 +#define dwc_workq_free DWC_WORKQ_FREE
13208 +
13209 +/** Schedule a callback on the workq, passing in data.  The function will be
13210 + * scheduled at some later time. */
13211 +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
13212 +                              void *data, char *format, ...)
13213 +#ifdef __GNUC__
13214 +       __attribute__ ((format(printf, 4, 5)));
13215 +#else
13216 +       ;
13217 +#endif
13218 +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
13219 +
13220 +/** Schedule a callback on the workq, that will be called until at least
13221 + * given number miliseconds have passed. */
13222 +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
13223 +                                      void *data, uint32_t time, char *format, ...)
13224 +#ifdef __GNUC__
13225 +       __attribute__ ((format(printf, 5, 6)));
13226 +#else
13227 +       ;
13228 +#endif
13229 +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
13230 +
13231 +/** The number of processes in the workq */
13232 +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
13233 +#define dwc_workq_pending DWC_WORKQ_PENDING
13234 +
13235 +/** Blocks until all the work in the workq is complete or timed out.  Returns <
13236 + * 0 on timeout. */
13237 +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
13238 +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
13239 +
13240 +
13241 +/** @name Tasklets
13242 + *
13243 + */
13244 +struct dwc_tasklet;
13245 +
13246 +/** Type for a tasklet */
13247 +typedef struct dwc_tasklet dwc_tasklet_t;
13248 +
13249 +/** The type of the callback function to be called */
13250 +typedef void (*dwc_tasklet_callback_t)(void *data);
13251 +
13252 +/** Allocates a tasklet */
13253 +extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
13254 +#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
13255 +
13256 +/** Frees a tasklet */
13257 +extern void DWC_TASK_FREE(dwc_tasklet_t *task);
13258 +#define dwc_task_free DWC_TASK_FREE
13259 +
13260 +/** Schedules a tasklet to run */
13261 +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
13262 +#define dwc_task_schedule DWC_TASK_SCHEDULE
13263 +
13264 +
13265 +/** @name Timer
13266 + *
13267 + * Callbacks must be small and atomic.
13268 + */
13269 +struct dwc_timer;
13270 +
13271 +/** Type for a timer */
13272 +typedef struct dwc_timer dwc_timer_t;
13273 +
13274 +/** The type of the callback function to be called */
13275 +typedef void (*dwc_timer_callback_t)(void *data);
13276 +
13277 +/** Allocates a timer */
13278 +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
13279 +#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
13280 +
13281 +/** Frees a timer */
13282 +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
13283 +#define dwc_timer_free DWC_TIMER_FREE
13284 +
13285 +/** Schedules the timer to run at time ms from now.  And will repeat at every
13286 + * repeat_interval msec therafter
13287 + *
13288 + * Modifies a timer that is still awaiting execution to a new expiration time.
13289 + * The mod_time is added to the old time.  */
13290 +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
13291 +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
13292 +
13293 +/** Disables the timer from execution. */
13294 +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
13295 +#define dwc_timer_cancel DWC_TIMER_CANCEL
13296 +
13297 +
13298 +/** @name Spinlocks
13299 + *
13300 + * These locks are used when the work between the lock/unlock is atomic and
13301 + * short.  Interrupts are also disabled during the lock/unlock and thus they are
13302 + * suitable to lock between interrupt/non-interrupt context.  They also lock
13303 + * between processes if you have multiple CPUs or Preemption.  If you don't have
13304 + * multiple CPUS or Preemption, then the you can simply implement the
13305 + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because
13306 + * the work between the lock/unlock is atomic, the process context will never
13307 + * change, and so you never have to lock between processes.  */
13308 +
13309 +struct dwc_spinlock;
13310 +
13311 +/** Type for a spinlock */
13312 +typedef struct dwc_spinlock dwc_spinlock_t;
13313 +
13314 +/** Type for the 'flags' argument to spinlock funtions */
13315 +typedef unsigned long dwc_irqflags_t;
13316 +
13317 +/** Returns an initialized lock variable.  This function should allocate and
13318 + * initialize the OS-specific data structure used for locking.  This data
13319 + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
13320 + * be freed by the DWC_FREE_LOCK when it is no longer used.
13321 + *
13322 + * For Linux Spinlock Debugging make it macro because the debugging routines use
13323 + * the symbol name to determine recursive locking. Using a wrapper function
13324 + * makes it falsely think recursive locking occurs. */
13325 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK)
13326 +#define DWC_SPINLOCK_ALLOC_LINUX_DEBUG(lock) ({ \
13327 +       lock = DWC_ALLOC(sizeof(spinlock_t)); \
13328 +       if (lock) { \
13329 +               spin_lock_init((spinlock_t *)lock); \
13330 +       } \
13331 +})
13332 +#else
13333 +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
13334 +#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
13335 +#endif
13336 +
13337 +/** Frees an initialized lock variable. */
13338 +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
13339 +#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
13340 +
13341 +/** Disables interrupts and blocks until it acquires the lock.
13342 + *
13343 + * @param lock Pointer to the spinlock.
13344 + * @param flags Unsigned long for irq flags storage.
13345 + */
13346 +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
13347 +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
13348 +
13349 +/** Re-enables the interrupt and releases the lock.
13350 + *
13351 + * @param lock Pointer to the spinlock.
13352 + * @param flags Unsigned long for irq flags storage.  Must be the same as was
13353 + * passed into DWC_LOCK.
13354 + */
13355 +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
13356 +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
13357 +
13358 +/** Blocks until it acquires the lock.
13359 + *
13360 + * @param lock Pointer to the spinlock.
13361 + */
13362 +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
13363 +#define dwc_spinlock DWC_SPINLOCK
13364 +
13365 +/** Releases the lock.
13366 + *
13367 + * @param lock Pointer to the spinlock.
13368 + */
13369 +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
13370 +#define dwc_spinunlock DWC_SPINUNLOCK
13371 +
13372 +
13373 +/** @name Mutexes
13374 + *
13375 + * Unlike spinlocks Mutexes lock only between processes and the work between the
13376 + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
13377 + */
13378 +
13379 +struct dwc_mutex;
13380 +
13381 +/** Type for a mutex */
13382 +typedef struct dwc_mutex dwc_mutex_t;
13383 +
13384 +/* For Linux Mutex Debugging make it inline because the debugging routines use
13385 + * the symbol to determine recursive locking.  This makes it falsely think
13386 + * recursive locking occurs. */
13387 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13388 +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
13389 +       __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
13390 +       mutex_init((struct mutex *)__mutexp); \
13391 +})
13392 +#endif
13393 +
13394 +/** Allocate a mutex */
13395 +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
13396 +#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
13397 +
13398 +/* For memory leak debugging when using Linux Mutex Debugging */
13399 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13400 +#define DWC_MUTEX_FREE(__mutexp) do { \
13401 +       mutex_destroy((struct mutex *)__mutexp); \
13402 +       DWC_FREE(__mutexp); \
13403 +} while(0)
13404 +#else
13405 +/** Free a mutex */
13406 +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
13407 +#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
13408 +#endif
13409 +
13410 +/** Lock a mutex */
13411 +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
13412 +#define dwc_mutex_lock DWC_MUTEX_LOCK
13413 +
13414 +/** Non-blocking lock returns 1 on successful lock. */
13415 +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
13416 +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
13417 +
13418 +/** Unlock a mutex */
13419 +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
13420 +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
13421 +
13422 +
13423 +/** @name Time */
13424 +
13425 +/** Microsecond delay.
13426 + *
13427 + * @param usecs  Microseconds to delay.
13428 + */
13429 +extern void DWC_UDELAY(uint32_t usecs);
13430 +#define dwc_udelay DWC_UDELAY
13431 +
13432 +/** Millisecond delay.
13433 + *
13434 + * @param msecs  Milliseconds to delay.
13435 + */
13436 +extern void DWC_MDELAY(uint32_t msecs);
13437 +#define dwc_mdelay DWC_MDELAY
13438 +
13439 +/** Non-busy waiting.
13440 + * Sleeps for specified number of milliseconds.
13441 + *
13442 + * @param msecs Milliseconds to sleep.
13443 + */
13444 +extern void DWC_MSLEEP(uint32_t msecs);
13445 +#define dwc_msleep DWC_MSLEEP
13446 +
13447 +/**
13448 + * Returns number of milliseconds since boot.
13449 + */
13450 +extern uint32_t DWC_TIME(void);
13451 +#define dwc_time DWC_TIME
13452 +
13453 +
13454 +
13455 +
13456 +/* @mainpage DWC Portability and Common Library
13457 + *
13458 + * This is the documentation for the DWC Portability and Common Library.
13459 + *
13460 + * @section intro Introduction
13461 + *
13462 + * The DWC Portability library consists of wrapper calls and data structures to
13463 + * all low-level functions which are typically provided by the OS.  The WUDEV
13464 + * driver uses only these functions.  In order to port the WUDEV driver, only
13465 + * the functions in this library need to be re-implemented, with the same
13466 + * behavior as documented here.
13467 + *
13468 + * The Common library consists of higher level functions, which rely only on
13469 + * calling the functions from the DWC Portability library.  These common
13470 + * routines are shared across modules.  Some of the common libraries need to be
13471 + * used directly by the driver programmer when porting WUDEV.  Such as the
13472 + * parameter and notification libraries.
13473 + *
13474 + * @section low Portability Library OS Wrapper Functions
13475 + *
13476 + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
13477 + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of
13478 + * these functions are included in the dwc_os.h file.
13479 + *
13480 + * There are many functions here covering a wide array of OS services.  Please
13481 + * see dwc_os.h for details, and implementation notes for each function.
13482 + *
13483 + * @section common Common Library Functions
13484 + *
13485 + * Any function starting with dwc and in all lowercase is a common library
13486 + * routine.  These functions have a portable implementation and do not need to
13487 + * be reimplemented when porting.  The common routines can be used by any
13488 + * driver, and some must be used by the end user to control the drivers.  For
13489 + * example, you must use the Parameter common library in order to set the
13490 + * parameters in the WUDEV module.
13491 + *
13492 + * The common libraries consist of the following:
13493 + *
13494 + * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h
13495 + * - Parameters - Used internally and can be used by end-user.  See dwc_params.h
13496 + * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h
13497 + * - Lists - Used internally and can be used by end-user.  See dwc_list.h
13498 + * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h
13499 + * - Modpow - Used internally only.  See dwc_modpow.h
13500 + * - DH - Used internally only.  See dwc_dh.h
13501 + * - Crypto - Used internally only.  See dwc_crypto.h
13502 + *
13503 + *
13504 + * @section prereq Prerequistes For dwc_os.h
13505 + * @subsection types Data Types
13506 + *
13507 + * The dwc_os.h file assumes that several low-level data types are pre defined for the
13508 + * compilation environment.  These data types are:
13509 + *
13510 + * - uint8_t - unsigned 8-bit data type
13511 + * - int8_t - signed 8-bit data type
13512 + * - uint16_t - unsigned 16-bit data type
13513 + * - int16_t - signed 16-bit data type
13514 + * - uint32_t - unsigned 32-bit data type
13515 + * - int32_t - signed 32-bit data type
13516 + * - uint64_t - unsigned 64-bit data type
13517 + * - int64_t - signed 64-bit data type
13518 + *
13519 + * Ensure that these are defined before using dwc_os.h.  The easiest way to do
13520 + * that is to modify the top of the file to include the appropriate header.
13521 + * This is already done for the Linux environment.  If the DWC_LINUX macro is
13522 + * defined, the correct header will be added.  A standard header <stdint.h> is
13523 + * also used for environments where standard C headers are available.
13524 + *
13525 + * @subsection stdarg Variable Arguments
13526 + *
13527 + * Variable arguments are provided by a standard C header <stdarg.h>.  it is
13528 + * available in Both the Linux and ANSI C enviornment.  An equivalent must be
13529 + * provided in your enviornment in order to use dwc_os.h with the debug and
13530 + * tracing message functionality.
13531 + *
13532 + * @subsection thread Threading
13533 + *
13534 + * WUDEV Core must be run on an operating system that provides for multiple
13535 + * threads/processes.  Threading can be implemented in many ways, even in
13536 + * embedded systems without an operating system.  At the bare minimum, the
13537 + * system should be able to start any number of processes at any time to handle
13538 + * special work.  It need not be a pre-emptive system.  Process context can
13539 + * change upon a call to a blocking function.  The hardware interrupt context
13540 + * that calls the module's ISR() function must be differentiable from process
13541 + * context, even if your processes are impemented via a hardware interrupt.
13542 + * Further locking mechanism between process must exist (or be implemented), and
13543 + * process context must have a way to disable interrupts for a period of time to
13544 + * lock them out.  If all of this exists, the functions in dwc_os.h related to
13545 + * threading should be able to be implemented with the defined behavior.
13546 + *
13547 + */
13548 +
13549 +#ifdef __cplusplus
13550 +}
13551 +#endif
13552 +
13553 +#endif /* _DWC_OS_H_ */
13554 --- /dev/null
13555 +++ b/drivers/usb/host/dwc_common_port/usb.h
13556 @@ -0,0 +1,946 @@
13557 +/*
13558 + * Copyright (c) 1998 The NetBSD Foundation, Inc.
13559 + * All rights reserved.
13560 + *
13561 + * This code is derived from software contributed to The NetBSD Foundation
13562 + * by Lennart Augustsson (lennart@augustsson.net) at
13563 + * Carlstedt Research & Technology.
13564 + *
13565 + * Redistribution and use in source and binary forms, with or without
13566 + * modification, are permitted provided that the following conditions
13567 + * are met:
13568 + * 1. Redistributions of source code must retain the above copyright
13569 + *    notice, this list of conditions and the following disclaimer.
13570 + * 2. Redistributions in binary form must reproduce the above copyright
13571 + *    notice, this list of conditions and the following disclaimer in the
13572 + *    documentation and/or other materials provided with the distribution.
13573 + * 3. All advertising materials mentioning features or use of this software
13574 + *    must display the following acknowledgement:
13575 + *        This product includes software developed by the NetBSD
13576 + *        Foundation, Inc. and its contributors.
13577 + * 4. Neither the name of The NetBSD Foundation nor the names of its
13578 + *    contributors may be used to endorse or promote products derived
13579 + *    from this software without specific prior written permission.
13580 + *
13581 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
13582 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13583 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13584 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
13585 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13586 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13587 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13588 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13589 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13590 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13591 + * POSSIBILITY OF SUCH DAMAGE.
13592 + */
13593 +
13594 +/* Modified by Synopsys, Inc, 12/12/2007 */
13595 +
13596 +
13597 +#ifndef _USB_H_
13598 +#define _USB_H_
13599 +
13600 +#ifdef __cplusplus
13601 +extern "C" {
13602 +#endif
13603 +
13604 +/*
13605 + * The USB records contain some unaligned little-endian word
13606 + * components.  The U[SG]ETW macros take care of both the alignment
13607 + * and endian problem and should always be used to access non-byte
13608 + * values.
13609 + */
13610 +typedef u_int8_t uByte;
13611 +typedef u_int8_t uWord[2];
13612 +typedef u_int8_t uDWord[4];
13613 +
13614 +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
13615 +#define UCONSTW(x)     { (x) & 0xff, ((x) >> 8) & 0xff }
13616 +#define UCONSTDW(x)    { (x) & 0xff, ((x) >> 8) & 0xff, \
13617 +                         ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
13618 +
13619 +#if 1
13620 +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
13621 +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
13622 +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
13623 +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
13624 +                    (w)[1] = (u_int8_t)((v) >> 8), \
13625 +                    (w)[2] = (u_int8_t)((v) >> 16), \
13626 +                    (w)[3] = (u_int8_t)((v) >> 24))
13627 +#else
13628 +/*
13629 + * On little-endian machines that can handle unanliged accesses
13630 + * (e.g. i386) these macros can be replaced by the following.
13631 + */
13632 +#define UGETW(w) (*(u_int16_t *)(w))
13633 +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
13634 +#define UGETDW(w) (*(u_int32_t *)(w))
13635 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
13636 +#endif
13637 +
13638 +/*
13639 + * Macros for accessing UAS IU fields, which are big-endian
13640 + */
13641 +#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
13642 +#define IUCONSTW(x)    { ((x) >> 8) & 0xff, (x) & 0xff }
13643 +#define IUCONSTDW(x)   { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
13644 +                       ((x) >> 8) & 0xff, (x) & 0xff }
13645 +#define IUGETW(w) (((w)[0] << 8) | (w)[1])
13646 +#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
13647 +#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
13648 +#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
13649 +                     (w)[1] = (u_int8_t)((v) >> 16), \
13650 +                     (w)[2] = (u_int8_t)((v) >> 8), \
13651 +                     (w)[3] = (u_int8_t)(v))
13652 +
13653 +#define UPACKED __attribute__((__packed__))
13654 +
13655 +typedef struct {
13656 +       uByte           bmRequestType;
13657 +       uByte           bRequest;
13658 +       uWord           wValue;
13659 +       uWord           wIndex;
13660 +       uWord           wLength;
13661 +} UPACKED usb_device_request_t;
13662 +
13663 +#define UT_GET_DIR(a) ((a) & 0x80)
13664 +#define UT_WRITE               0x00
13665 +#define UT_READ                        0x80
13666 +
13667 +#define UT_GET_TYPE(a) ((a) & 0x60)
13668 +#define UT_STANDARD            0x00
13669 +#define UT_CLASS               0x20
13670 +#define UT_VENDOR              0x40
13671 +
13672 +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
13673 +#define UT_DEVICE              0x00
13674 +#define UT_INTERFACE           0x01
13675 +#define UT_ENDPOINT            0x02
13676 +#define UT_OTHER               0x03
13677 +
13678 +#define UT_READ_DEVICE         (UT_READ  | UT_STANDARD | UT_DEVICE)
13679 +#define UT_READ_INTERFACE      (UT_READ  | UT_STANDARD | UT_INTERFACE)
13680 +#define UT_READ_ENDPOINT       (UT_READ  | UT_STANDARD | UT_ENDPOINT)
13681 +#define UT_WRITE_DEVICE                (UT_WRITE | UT_STANDARD | UT_DEVICE)
13682 +#define UT_WRITE_INTERFACE     (UT_WRITE | UT_STANDARD | UT_INTERFACE)
13683 +#define UT_WRITE_ENDPOINT      (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
13684 +#define UT_READ_CLASS_DEVICE   (UT_READ  | UT_CLASS | UT_DEVICE)
13685 +#define UT_READ_CLASS_INTERFACE        (UT_READ  | UT_CLASS | UT_INTERFACE)
13686 +#define UT_READ_CLASS_OTHER    (UT_READ  | UT_CLASS | UT_OTHER)
13687 +#define UT_READ_CLASS_ENDPOINT (UT_READ  | UT_CLASS | UT_ENDPOINT)
13688 +#define UT_WRITE_CLASS_DEVICE  (UT_WRITE | UT_CLASS | UT_DEVICE)
13689 +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
13690 +#define UT_WRITE_CLASS_OTHER   (UT_WRITE | UT_CLASS | UT_OTHER)
13691 +#define UT_WRITE_CLASS_ENDPOINT        (UT_WRITE | UT_CLASS | UT_ENDPOINT)
13692 +#define UT_READ_VENDOR_DEVICE  (UT_READ  | UT_VENDOR | UT_DEVICE)
13693 +#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
13694 +#define UT_READ_VENDOR_OTHER   (UT_READ  | UT_VENDOR | UT_OTHER)
13695 +#define UT_READ_VENDOR_ENDPOINT        (UT_READ  | UT_VENDOR | UT_ENDPOINT)
13696 +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
13697 +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
13698 +#define UT_WRITE_VENDOR_OTHER  (UT_WRITE | UT_VENDOR | UT_OTHER)
13699 +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
13700 +
13701 +/* Requests */
13702 +#define UR_GET_STATUS          0x00
13703 +#define  USTAT_STANDARD_STATUS  0x00
13704 +#define  WUSTAT_WUSB_FEATURE    0x01
13705 +#define  WUSTAT_CHANNEL_INFO    0x02
13706 +#define  WUSTAT_RECEIVED_DATA   0x03
13707 +#define  WUSTAT_MAS_AVAILABILITY 0x04
13708 +#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05
13709 +#define UR_CLEAR_FEATURE       0x01
13710 +#define UR_SET_FEATURE         0x03
13711 +#define UR_SET_AND_TEST_FEATURE 0x0c
13712 +#define UR_SET_ADDRESS         0x05
13713 +#define UR_GET_DESCRIPTOR      0x06
13714 +#define  UDESC_DEVICE          0x01
13715 +#define  UDESC_CONFIG          0x02
13716 +#define  UDESC_STRING          0x03
13717 +#define  UDESC_INTERFACE       0x04
13718 +#define  UDESC_ENDPOINT                0x05
13719 +#define  UDESC_SS_USB_COMPANION        0x30
13720 +#define  UDESC_DEVICE_QUALIFIER        0x06
13721 +#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07
13722 +#define  UDESC_INTERFACE_POWER 0x08
13723 +#define  UDESC_OTG             0x09
13724 +#define  WUDESC_SECURITY       0x0c
13725 +#define  WUDESC_KEY            0x0d
13726 +#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
13727 +#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
13728 +#define    WUD_KEY_TYPE_ASSOC    0x01
13729 +#define    WUD_KEY_TYPE_GTK      0x02
13730 +#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
13731 +#define    WUD_KEY_ORIGIN_HOST   0x00
13732 +#define    WUD_KEY_ORIGIN_DEVICE 0x01
13733 +#define  WUDESC_ENCRYPTION_TYPE        0x0e
13734 +#define  WUDESC_BOS            0x0f
13735 +#define  WUDESC_DEVICE_CAPABILITY 0x10
13736 +#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
13737 +#define  UDESC_BOS             0x0f
13738 +#define  UDESC_DEVICE_CAPABILITY 0x10
13739 +#define  UDESC_CS_DEVICE       0x21    /* class specific */
13740 +#define  UDESC_CS_CONFIG       0x22
13741 +#define  UDESC_CS_STRING       0x23
13742 +#define  UDESC_CS_INTERFACE    0x24
13743 +#define  UDESC_CS_ENDPOINT     0x25
13744 +#define  UDESC_HUB             0x29
13745 +#define UR_SET_DESCRIPTOR      0x07
13746 +#define UR_GET_CONFIG          0x08
13747 +#define UR_SET_CONFIG          0x09
13748 +#define UR_GET_INTERFACE       0x0a
13749 +#define UR_SET_INTERFACE       0x0b
13750 +#define UR_SYNCH_FRAME         0x0c
13751 +#define WUR_SET_ENCRYPTION      0x0d
13752 +#define WUR_GET_ENCRYPTION     0x0e
13753 +#define WUR_SET_HANDSHAKE      0x0f
13754 +#define WUR_GET_HANDSHAKE      0x10
13755 +#define WUR_SET_CONNECTION     0x11
13756 +#define WUR_SET_SECURITY_DATA  0x12
13757 +#define WUR_GET_SECURITY_DATA  0x13
13758 +#define WUR_SET_WUSB_DATA      0x14
13759 +#define  WUDATA_DRPIE_INFO     0x01
13760 +#define  WUDATA_TRANSMIT_DATA  0x02
13761 +#define  WUDATA_TRANSMIT_PARAMS        0x03
13762 +#define  WUDATA_RECEIVE_PARAMS 0x04
13763 +#define  WUDATA_TRANSMIT_POWER 0x05
13764 +#define WUR_LOOPBACK_DATA_WRITE        0x15
13765 +#define WUR_LOOPBACK_DATA_READ 0x16
13766 +#define WUR_SET_INTERFACE_DS   0x17
13767 +
13768 +/* Feature numbers */
13769 +#define UF_ENDPOINT_HALT       0
13770 +#define UF_DEVICE_REMOTE_WAKEUP        1
13771 +#define UF_TEST_MODE           2
13772 +#define UF_DEVICE_B_HNP_ENABLE 3
13773 +#define UF_DEVICE_A_HNP_SUPPORT        4
13774 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
13775 +#define WUF_WUSB               3
13776 +#define  WUF_TX_DRPIE          0x0
13777 +#define  WUF_DEV_XMIT_PACKET   0x1
13778 +#define  WUF_COUNT_PACKETS     0x2
13779 +#define  WUF_CAPTURE_PACKETS   0x3
13780 +#define UF_FUNCTION_SUSPEND    0
13781 +#define UF_U1_ENABLE           48
13782 +#define UF_U2_ENABLE           49
13783 +#define UF_LTM_ENABLE          50
13784 +
13785 +/* Class requests from the USB 2.0 hub spec, table 11-15 */
13786 +#define UCR_CLEAR_HUB_FEATURE          (0x2000 | UR_CLEAR_FEATURE)
13787 +#define UCR_CLEAR_PORT_FEATURE         (0x2300 | UR_CLEAR_FEATURE)
13788 +#define UCR_GET_HUB_DESCRIPTOR         (0xa000 | UR_GET_DESCRIPTOR)
13789 +#define UCR_GET_HUB_STATUS             (0xa000 | UR_GET_STATUS)
13790 +#define UCR_GET_PORT_STATUS            (0xa300 | UR_GET_STATUS)
13791 +#define UCR_SET_HUB_FEATURE            (0x2000 | UR_SET_FEATURE)
13792 +#define UCR_SET_PORT_FEATURE           (0x2300 | UR_SET_FEATURE)
13793 +#define UCR_SET_AND_TEST_PORT_FEATURE  (0xa300 | UR_SET_AND_TEST_FEATURE)
13794 +
13795 +#ifdef _MSC_VER
13796 +#include <pshpack1.h>
13797 +#endif
13798 +
13799 +typedef struct {
13800 +       uByte           bLength;
13801 +       uByte           bDescriptorType;
13802 +       uByte           bDescriptorSubtype;
13803 +} UPACKED usb_descriptor_t;
13804 +
13805 +typedef struct {
13806 +       uByte           bLength;
13807 +       uByte           bDescriptorType;
13808 +} UPACKED usb_descriptor_header_t;
13809 +
13810 +typedef struct {
13811 +       uByte           bLength;
13812 +       uByte           bDescriptorType;
13813 +       uWord           bcdUSB;
13814 +#define UD_USB_2_0             0x0200
13815 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
13816 +       uByte           bDeviceClass;
13817 +       uByte           bDeviceSubClass;
13818 +       uByte           bDeviceProtocol;
13819 +       uByte           bMaxPacketSize;
13820 +       /* The fields below are not part of the initial descriptor. */
13821 +       uWord           idVendor;
13822 +       uWord           idProduct;
13823 +       uWord           bcdDevice;
13824 +       uByte           iManufacturer;
13825 +       uByte           iProduct;
13826 +       uByte           iSerialNumber;
13827 +       uByte           bNumConfigurations;
13828 +} UPACKED usb_device_descriptor_t;
13829 +#define USB_DEVICE_DESCRIPTOR_SIZE 18
13830 +
13831 +typedef struct {
13832 +       uByte           bLength;
13833 +       uByte           bDescriptorType;
13834 +       uWord           wTotalLength;
13835 +       uByte           bNumInterface;
13836 +       uByte           bConfigurationValue;
13837 +       uByte           iConfiguration;
13838 +#define UC_ATT_ONE             (1 << 7)        /* must be set */
13839 +#define UC_ATT_SELFPOWER       (1 << 6)        /* self powered */
13840 +#define UC_ATT_WAKEUP          (1 << 5)        /* can wakeup */
13841 +#define UC_ATT_BATTERY         (1 << 4)        /* battery powered */
13842 +       uByte           bmAttributes;
13843 +#define UC_BUS_POWERED         0x80
13844 +#define UC_SELF_POWERED                0x40
13845 +#define UC_REMOTE_WAKEUP       0x20
13846 +       uByte           bMaxPower; /* max current in 2 mA units */
13847 +#define UC_POWER_FACTOR 2
13848 +} UPACKED usb_config_descriptor_t;
13849 +#define USB_CONFIG_DESCRIPTOR_SIZE 9
13850 +
13851 +typedef struct {
13852 +       uByte           bLength;
13853 +       uByte           bDescriptorType;
13854 +       uByte           bInterfaceNumber;
13855 +       uByte           bAlternateSetting;
13856 +       uByte           bNumEndpoints;
13857 +       uByte           bInterfaceClass;
13858 +       uByte           bInterfaceSubClass;
13859 +       uByte           bInterfaceProtocol;
13860 +       uByte           iInterface;
13861 +} UPACKED usb_interface_descriptor_t;
13862 +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
13863 +
13864 +typedef struct {
13865 +       uByte           bLength;
13866 +       uByte           bDescriptorType;
13867 +       uByte           bEndpointAddress;
13868 +#define UE_GET_DIR(a)  ((a) & 0x80)
13869 +#define UE_SET_DIR(a,d)        ((a) | (((d)&1) << 7))
13870 +#define UE_DIR_IN      0x80
13871 +#define UE_DIR_OUT     0x00
13872 +#define UE_ADDR                0x0f
13873 +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
13874 +       uByte           bmAttributes;
13875 +#define UE_XFERTYPE    0x03
13876 +#define  UE_CONTROL    0x00
13877 +#define  UE_ISOCHRONOUS        0x01
13878 +#define  UE_BULK       0x02
13879 +#define  UE_INTERRUPT  0x03
13880 +#define UE_GET_XFERTYPE(a)     ((a) & UE_XFERTYPE)
13881 +#define UE_ISO_TYPE    0x0c
13882 +#define  UE_ISO_ASYNC  0x04
13883 +#define  UE_ISO_ADAPT  0x08
13884 +#define  UE_ISO_SYNC   0x0c
13885 +#define UE_GET_ISO_TYPE(a)     ((a) & UE_ISO_TYPE)
13886 +       uWord           wMaxPacketSize;
13887 +       uByte           bInterval;
13888 +} UPACKED usb_endpoint_descriptor_t;
13889 +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
13890 +
13891 +typedef struct ss_endpoint_companion_descriptor {
13892 +       uByte bLength;
13893 +       uByte bDescriptorType;
13894 +       uByte bMaxBurst;
13895 +#define USSE_GET_MAX_STREAMS(a)                ((a) & 0x1f)
13896 +#define USSE_SET_MAX_STREAMS(a, b)     ((a) | ((b) & 0x1f))
13897 +#define USSE_GET_MAX_PACKET_NUM(a)     ((a) & 0x03)
13898 +#define USSE_SET_MAX_PACKET_NUM(a, b)  ((a) | ((b) & 0x03))
13899 +       uByte bmAttributes;
13900 +       uWord wBytesPerInterval;
13901 +} UPACKED ss_endpoint_companion_descriptor_t;
13902 +#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
13903 +
13904 +typedef struct {
13905 +       uByte           bLength;
13906 +       uByte           bDescriptorType;
13907 +       uWord           bString[127];
13908 +} UPACKED usb_string_descriptor_t;
13909 +#define USB_MAX_STRING_LEN 128
13910 +#define USB_LANGUAGE_TABLE 0   /* # of the string language id table */
13911 +
13912 +/* Hub specific request */
13913 +#define UR_GET_BUS_STATE       0x02
13914 +#define UR_CLEAR_TT_BUFFER     0x08
13915 +#define UR_RESET_TT            0x09
13916 +#define UR_GET_TT_STATE                0x0a
13917 +#define UR_STOP_TT             0x0b
13918 +
13919 +/* Hub features */
13920 +#define UHF_C_HUB_LOCAL_POWER  0
13921 +#define UHF_C_HUB_OVER_CURRENT 1
13922 +#define UHF_PORT_CONNECTION    0
13923 +#define UHF_PORT_ENABLE                1
13924 +#define UHF_PORT_SUSPEND       2
13925 +#define UHF_PORT_OVER_CURRENT  3
13926 +#define UHF_PORT_RESET         4
13927 +#define UHF_PORT_L1            5
13928 +#define UHF_PORT_POWER         8
13929 +#define UHF_PORT_LOW_SPEED     9
13930 +#define UHF_PORT_HIGH_SPEED    10
13931 +#define UHF_C_PORT_CONNECTION  16
13932 +#define UHF_C_PORT_ENABLE      17
13933 +#define UHF_C_PORT_SUSPEND     18
13934 +#define UHF_C_PORT_OVER_CURRENT        19
13935 +#define UHF_C_PORT_RESET       20
13936 +#define UHF_C_PORT_L1          23
13937 +#define UHF_PORT_TEST          21
13938 +#define UHF_PORT_INDICATOR     22
13939 +
13940 +typedef struct {
13941 +       uByte           bDescLength;
13942 +       uByte           bDescriptorType;
13943 +       uByte           bNbrPorts;
13944 +       uWord           wHubCharacteristics;
13945 +#define UHD_PWR                        0x0003
13946 +#define  UHD_PWR_GANGED                0x0000
13947 +#define  UHD_PWR_INDIVIDUAL    0x0001
13948 +#define  UHD_PWR_NO_SWITCH     0x0002
13949 +#define UHD_COMPOUND           0x0004
13950 +#define UHD_OC                 0x0018
13951 +#define  UHD_OC_GLOBAL         0x0000
13952 +#define  UHD_OC_INDIVIDUAL     0x0008
13953 +#define  UHD_OC_NONE           0x0010
13954 +#define UHD_TT_THINK           0x0060
13955 +#define  UHD_TT_THINK_8                0x0000
13956 +#define  UHD_TT_THINK_16       0x0020
13957 +#define  UHD_TT_THINK_24       0x0040
13958 +#define  UHD_TT_THINK_32       0x0060
13959 +#define UHD_PORT_IND           0x0080
13960 +       uByte           bPwrOn2PwrGood; /* delay in 2 ms units */
13961 +#define UHD_PWRON_FACTOR 2
13962 +       uByte           bHubContrCurrent;
13963 +       uByte           DeviceRemovable[32]; /* max 255 ports */
13964 +#define UHD_NOT_REMOV(desc, i) \
13965 +    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
13966 +       /* deprecated */ uByte          PortPowerCtrlMask[1];
13967 +} UPACKED usb_hub_descriptor_t;
13968 +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
13969 +
13970 +typedef struct {
13971 +       uByte           bLength;
13972 +       uByte           bDescriptorType;
13973 +       uWord           bcdUSB;
13974 +       uByte           bDeviceClass;
13975 +       uByte           bDeviceSubClass;
13976 +       uByte           bDeviceProtocol;
13977 +       uByte           bMaxPacketSize0;
13978 +       uByte           bNumConfigurations;
13979 +       uByte           bReserved;
13980 +} UPACKED usb_device_qualifier_t;
13981 +#define USB_DEVICE_QUALIFIER_SIZE 10
13982 +
13983 +typedef struct {
13984 +       uByte           bLength;
13985 +       uByte           bDescriptorType;
13986 +       uByte           bmAttributes;
13987 +#define UOTG_SRP       0x01
13988 +#define UOTG_HNP       0x02
13989 +} UPACKED usb_otg_descriptor_t;
13990 +
13991 +/* OTG feature selectors */
13992 +#define UOTG_B_HNP_ENABLE      3
13993 +#define UOTG_A_HNP_SUPPORT     4
13994 +#define UOTG_A_ALT_HNP_SUPPORT 5
13995 +
13996 +typedef struct {
13997 +       uWord           wStatus;
13998 +/* Device status flags */
13999 +#define UDS_SELF_POWERED               0x0001
14000 +#define UDS_REMOTE_WAKEUP              0x0002
14001 +/* Endpoint status flags */
14002 +#define UES_HALT                       0x0001
14003 +} UPACKED usb_status_t;
14004 +
14005 +typedef struct {
14006 +       uWord           wHubStatus;
14007 +#define UHS_LOCAL_POWER                        0x0001
14008 +#define UHS_OVER_CURRENT               0x0002
14009 +       uWord           wHubChange;
14010 +} UPACKED usb_hub_status_t;
14011 +
14012 +typedef struct {
14013 +       uWord           wPortStatus;
14014 +#define UPS_CURRENT_CONNECT_STATUS     0x0001
14015 +#define UPS_PORT_ENABLED               0x0002
14016 +#define UPS_SUSPEND                    0x0004
14017 +#define UPS_OVERCURRENT_INDICATOR      0x0008
14018 +#define UPS_RESET                      0x0010
14019 +#define UPS_PORT_POWER                 0x0100
14020 +#define UPS_LOW_SPEED                  0x0200
14021 +#define UPS_HIGH_SPEED                 0x0400
14022 +#define UPS_PORT_TEST                  0x0800
14023 +#define UPS_PORT_INDICATOR             0x1000
14024 +       uWord           wPortChange;
14025 +#define UPS_C_CONNECT_STATUS           0x0001
14026 +#define UPS_C_PORT_ENABLED             0x0002
14027 +#define UPS_C_SUSPEND                  0x0004
14028 +#define UPS_C_OVERCURRENT_INDICATOR    0x0008
14029 +#define UPS_C_PORT_RESET               0x0010
14030 +} UPACKED usb_port_status_t;
14031 +
14032 +#ifdef _MSC_VER
14033 +#include <poppack.h>
14034 +#endif
14035 +
14036 +/* Device class codes */
14037 +#define UDCLASS_IN_INTERFACE   0x00
14038 +#define UDCLASS_COMM           0x02
14039 +#define UDCLASS_HUB            0x09
14040 +#define  UDSUBCLASS_HUB                0x00
14041 +#define  UDPROTO_FSHUB         0x00
14042 +#define  UDPROTO_HSHUBSTT      0x01
14043 +#define  UDPROTO_HSHUBMTT      0x02
14044 +#define UDCLASS_DIAGNOSTIC     0xdc
14045 +#define UDCLASS_WIRELESS       0xe0
14046 +#define  UDSUBCLASS_RF         0x01
14047 +#define   UDPROTO_BLUETOOTH    0x01
14048 +#define UDCLASS_VENDOR         0xff
14049 +
14050 +/* Interface class codes */
14051 +#define UICLASS_UNSPEC         0x00
14052 +
14053 +#define UICLASS_AUDIO          0x01
14054 +#define  UISUBCLASS_AUDIOCONTROL       1
14055 +#define  UISUBCLASS_AUDIOSTREAM                2
14056 +#define  UISUBCLASS_MIDISTREAM         3
14057 +
14058 +#define UICLASS_CDC            0x02 /* communication */
14059 +#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL  1
14060 +#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL     2
14061 +#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL    3
14062 +#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
14063 +#define  UISUBCLASS_CAPI_CONTROLMODEL          5
14064 +#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
14065 +#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
14066 +#define   UIPROTO_CDC_AT                       1
14067 +
14068 +#define UICLASS_HID            0x03
14069 +#define  UISUBCLASS_BOOT       1
14070 +#define  UIPROTO_BOOT_KEYBOARD 1
14071 +
14072 +#define UICLASS_PHYSICAL       0x05
14073 +
14074 +#define UICLASS_IMAGE          0x06
14075 +
14076 +#define UICLASS_PRINTER                0x07
14077 +#define  UISUBCLASS_PRINTER    1
14078 +#define  UIPROTO_PRINTER_UNI   1
14079 +#define  UIPROTO_PRINTER_BI    2
14080 +#define  UIPROTO_PRINTER_1284  3
14081 +
14082 +#define UICLASS_MASS           0x08
14083 +#define  UISUBCLASS_RBC                1
14084 +#define  UISUBCLASS_SFF8020I   2
14085 +#define  UISUBCLASS_QIC157     3
14086 +#define  UISUBCLASS_UFI                4
14087 +#define  UISUBCLASS_SFF8070I   5
14088 +#define  UISUBCLASS_SCSI       6
14089 +#define  UIPROTO_MASS_CBI_I    0
14090 +#define  UIPROTO_MASS_CBI      1
14091 +#define  UIPROTO_MASS_BBB_OLD  2       /* Not in the spec anymore */
14092 +#define  UIPROTO_MASS_BBB      80      /* 'P' for the Iomega Zip drive */
14093 +
14094 +#define UICLASS_HUB            0x09
14095 +#define  UISUBCLASS_HUB                0
14096 +#define  UIPROTO_FSHUB         0
14097 +#define  UIPROTO_HSHUBSTT      0 /* Yes, same as previous */
14098 +#define  UIPROTO_HSHUBMTT      1
14099 +
14100 +#define UICLASS_CDC_DATA       0x0a
14101 +#define  UISUBCLASS_DATA               0
14102 +#define   UIPROTO_DATA_ISDNBRI         0x30    /* Physical iface */
14103 +#define   UIPROTO_DATA_HDLC            0x31    /* HDLC */
14104 +#define   UIPROTO_DATA_TRANSPARENT     0x32    /* Transparent */
14105 +#define   UIPROTO_DATA_Q921M           0x50    /* Management for Q921 */
14106 +#define   UIPROTO_DATA_Q921            0x51    /* Data for Q921 */
14107 +#define   UIPROTO_DATA_Q921TM          0x52    /* TEI multiplexer for Q921 */
14108 +#define   UIPROTO_DATA_V42BIS          0x90    /* Data compression */
14109 +#define   UIPROTO_DATA_Q931            0x91    /* Euro-ISDN */
14110 +#define   UIPROTO_DATA_V120            0x92    /* V.24 rate adaption */
14111 +#define   UIPROTO_DATA_CAPI            0x93    /* CAPI 2.0 commands */
14112 +#define   UIPROTO_DATA_HOST_BASED      0xfd    /* Host based driver */
14113 +#define   UIPROTO_DATA_PUF             0xfe    /* see Prot. Unit Func. Desc.*/
14114 +#define   UIPROTO_DATA_VENDOR          0xff    /* Vendor specific */
14115 +
14116 +#define UICLASS_SMARTCARD      0x0b
14117 +
14118 +/*#define UICLASS_FIRM_UPD     0x0c*/
14119 +
14120 +#define UICLASS_SECURITY       0x0d
14121 +
14122 +#define UICLASS_DIAGNOSTIC     0xdc
14123 +
14124 +#define UICLASS_WIRELESS       0xe0
14125 +#define  UISUBCLASS_RF                 0x01
14126 +#define   UIPROTO_BLUETOOTH            0x01
14127 +
14128 +#define UICLASS_APPL_SPEC      0xfe
14129 +#define  UISUBCLASS_FIRMWARE_DOWNLOAD  1
14130 +#define  UISUBCLASS_IRDA               2
14131 +#define  UIPROTO_IRDA                  0
14132 +
14133 +#define UICLASS_VENDOR         0xff
14134 +
14135 +#define USB_HUB_MAX_DEPTH 5
14136 +
14137 +/*
14138 + * Minimum time a device needs to be powered down to go through
14139 + * a power cycle.  XXX Are these time in the spec?
14140 + */
14141 +#define USB_POWER_DOWN_TIME    200 /* ms */
14142 +#define USB_PORT_POWER_DOWN_TIME       100 /* ms */
14143 +
14144 +#if 0
14145 +/* These are the values from the spec. */
14146 +#define USB_PORT_RESET_DELAY   10  /* ms */
14147 +#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
14148 +#define USB_PORT_RESET_RECOVERY        10  /* ms */
14149 +#define USB_PORT_POWERUP_DELAY 100 /* ms */
14150 +#define USB_SET_ADDRESS_SETTLE 2   /* ms */
14151 +#define USB_RESUME_DELAY       (20*5)  /* ms */
14152 +#define USB_RESUME_WAIT                10  /* ms */
14153 +#define USB_RESUME_RECOVERY    10  /* ms */
14154 +#define USB_EXTRA_POWER_UP_TIME        0   /* ms */
14155 +#else
14156 +/* Allow for marginal (i.e. non-conforming) devices. */
14157 +#define USB_PORT_RESET_DELAY   50  /* ms */
14158 +#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
14159 +#define USB_PORT_RESET_RECOVERY        250  /* ms */
14160 +#define USB_PORT_POWERUP_DELAY 300 /* ms */
14161 +#define USB_SET_ADDRESS_SETTLE 10  /* ms */
14162 +#define USB_RESUME_DELAY       (50*5)  /* ms */
14163 +#define USB_RESUME_WAIT                50  /* ms */
14164 +#define USB_RESUME_RECOVERY    50  /* ms */
14165 +#define USB_EXTRA_POWER_UP_TIME        20  /* ms */
14166 +#endif
14167 +
14168 +#define USB_MIN_POWER          100 /* mA */
14169 +#define USB_MAX_POWER          500 /* mA */
14170 +
14171 +#define USB_BUS_RESET_DELAY    100 /* ms XXX?*/
14172 +
14173 +#define USB_UNCONFIG_NO 0
14174 +#define USB_UNCONFIG_INDEX (-1)
14175 +
14176 +/*** ioctl() related stuff ***/
14177 +
14178 +struct usb_ctl_request {
14179 +       int     ucr_addr;
14180 +       usb_device_request_t ucr_request;
14181 +       void    *ucr_data;
14182 +       int     ucr_flags;
14183 +#define USBD_SHORT_XFER_OK     0x04    /* allow short reads */
14184 +       int     ucr_actlen;             /* actual length transferred */
14185 +};
14186 +
14187 +struct usb_alt_interface {
14188 +       int     uai_config_index;
14189 +       int     uai_interface_index;
14190 +       int     uai_alt_no;
14191 +};
14192 +
14193 +#define USB_CURRENT_CONFIG_INDEX (-1)
14194 +#define USB_CURRENT_ALT_INDEX (-1)
14195 +
14196 +struct usb_config_desc {
14197 +       int     ucd_config_index;
14198 +       usb_config_descriptor_t ucd_desc;
14199 +};
14200 +
14201 +struct usb_interface_desc {
14202 +       int     uid_config_index;
14203 +       int     uid_interface_index;
14204 +       int     uid_alt_index;
14205 +       usb_interface_descriptor_t uid_desc;
14206 +};
14207 +
14208 +struct usb_endpoint_desc {
14209 +       int     ued_config_index;
14210 +       int     ued_interface_index;
14211 +       int     ued_alt_index;
14212 +       int     ued_endpoint_index;
14213 +       usb_endpoint_descriptor_t ued_desc;
14214 +};
14215 +
14216 +struct usb_full_desc {
14217 +       int     ufd_config_index;
14218 +       u_int   ufd_size;
14219 +       u_char  *ufd_data;
14220 +};
14221 +
14222 +struct usb_string_desc {
14223 +       int     usd_string_index;
14224 +       int     usd_language_id;
14225 +       usb_string_descriptor_t usd_desc;
14226 +};
14227 +
14228 +struct usb_ctl_report_desc {
14229 +       int     ucrd_size;
14230 +       u_char  ucrd_data[1024];        /* filled data size will vary */
14231 +};
14232 +
14233 +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
14234 +
14235 +#define USB_MAX_DEVNAMES 4
14236 +#define USB_MAX_DEVNAMELEN 16
14237 +struct usb_device_info {
14238 +       u_int8_t        udi_bus;
14239 +       u_int8_t        udi_addr;       /* device address */
14240 +       usb_event_cookie_t udi_cookie;
14241 +       char            udi_product[USB_MAX_STRING_LEN];
14242 +       char            udi_vendor[USB_MAX_STRING_LEN];
14243 +       char            udi_release[8];
14244 +       u_int16_t       udi_productNo;
14245 +       u_int16_t       udi_vendorNo;
14246 +       u_int16_t       udi_releaseNo;
14247 +       u_int8_t        udi_class;
14248 +       u_int8_t        udi_subclass;
14249 +       u_int8_t        udi_protocol;
14250 +       u_int8_t        udi_config;
14251 +       u_int8_t        udi_speed;
14252 +#define USB_SPEED_UNKNOWN      0
14253 +#define USB_SPEED_LOW          1
14254 +#define USB_SPEED_FULL         2
14255 +#define USB_SPEED_HIGH         3
14256 +#define USB_SPEED_VARIABLE     4
14257 +#define USB_SPEED_SUPER                5
14258 +       int             udi_power;      /* power consumption in mA, 0 if selfpowered */
14259 +       int             udi_nports;
14260 +       char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
14261 +       u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
14262 +#define USB_PORT_ENABLED 0xff
14263 +#define USB_PORT_SUSPENDED 0xfe
14264 +#define USB_PORT_POWERED 0xfd
14265 +#define USB_PORT_DISABLED 0xfc
14266 +};
14267 +
14268 +struct usb_ctl_report {
14269 +       int     ucr_report;
14270 +       u_char  ucr_data[1024]; /* filled data size will vary */
14271 +};
14272 +
14273 +struct usb_device_stats {
14274 +       u_long  uds_requests[4];        /* indexed by transfer type UE_* */
14275 +};
14276 +
14277 +#define WUSB_MIN_IE                    0x80
14278 +#define WUSB_WCTA_IE                   0x80
14279 +#define WUSB_WCONNECTACK_IE            0x81
14280 +#define WUSB_WHOSTINFO_IE              0x82
14281 +#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
14282 +#define   WUHI_CA_RECONN               0x00
14283 +#define   WUHI_CA_LIMITED              0x01
14284 +#define   WUHI_CA_ALL                  0x03
14285 +#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
14286 +#define WUSB_WCHCHANGEANNOUNCE_IE      0x83
14287 +#define WUSB_WDEV_DISCONNECT_IE                0x84
14288 +#define WUSB_WHOST_DISCONNECT_IE       0x85
14289 +#define WUSB_WRELEASE_CHANNEL_IE       0x86
14290 +#define WUSB_WWORK_IE                  0x87
14291 +#define WUSB_WCHANNEL_STOP_IE          0x88
14292 +#define WUSB_WDEV_KEEPALIVE_IE         0x89
14293 +#define WUSB_WISOCH_DISCARD_IE         0x8A
14294 +#define WUSB_WRESETDEVICE_IE           0x8B
14295 +#define WUSB_WXMIT_PACKET_ADJUST_IE    0x8C
14296 +#define WUSB_MAX_IE                    0x8C
14297 +
14298 +/* Device Notification Types */
14299 +
14300 +#define WUSB_DN_MIN                    0x01
14301 +#define WUSB_DN_CONNECT                        0x01
14302 +# define WUSB_DA_OLDCONN       0x00
14303 +# define WUSB_DA_NEWCONN       0x01
14304 +# define WUSB_DA_SELF_BEACON   0x02
14305 +# define WUSB_DA_DIR_BEACON    0x04
14306 +# define WUSB_DA_NO_BEACON     0x06
14307 +#define WUSB_DN_DISCONNECT             0x02
14308 +#define WUSB_DN_EPRDY                  0x03
14309 +#define WUSB_DN_MASAVAILCHANGED                0x04
14310 +#define WUSB_DN_REMOTEWAKEUP           0x05
14311 +#define WUSB_DN_SLEEP                  0x06
14312 +#define WUSB_DN_ALIVE                  0x07
14313 +#define WUSB_DN_MAX                    0x07
14314 +
14315 +#ifdef _MSC_VER
14316 +#include <pshpack1.h>
14317 +#endif
14318 +
14319 +/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
14320 +typedef struct wusb_hndshk_data {
14321 +       uByte bMessageNumber;
14322 +       uByte bStatus;
14323 +       uByte tTKID[3];
14324 +       uByte bReserved;
14325 +       uByte CDID[16];
14326 +       uByte Nonce[16];
14327 +       uByte MIC[8];
14328 +} UPACKED wusb_hndshk_data_t;
14329 +#define WUSB_HANDSHAKE_LEN_FOR_MIC     38
14330 +
14331 +/* WUSB Connection Context */
14332 +typedef struct wusb_conn_context {
14333 +       uByte CHID [16];
14334 +       uByte CDID [16];
14335 +       uByte CK [16];
14336 +} UPACKED wusb_conn_context_t;
14337 +
14338 +/* WUSB Security Descriptor */
14339 +typedef struct wusb_security_desc {
14340 +       uByte bLength;
14341 +       uByte bDescriptorType;
14342 +       uWord wTotalLength;
14343 +       uByte bNumEncryptionTypes;
14344 +} UPACKED wusb_security_desc_t;
14345 +
14346 +/* WUSB Encryption Type Descriptor */
14347 +typedef struct wusb_encrypt_type_desc {
14348 +       uByte bLength;
14349 +       uByte bDescriptorType;
14350 +
14351 +       uByte bEncryptionType;
14352 +#define WUETD_UNSECURE         0
14353 +#define WUETD_WIRED            1
14354 +#define WUETD_CCM_1            2
14355 +#define WUETD_RSA_1            3
14356 +
14357 +       uByte bEncryptionValue;
14358 +       uByte bAuthKeyIndex;
14359 +} UPACKED wusb_encrypt_type_desc_t;
14360 +
14361 +/* WUSB Key Descriptor */
14362 +typedef struct wusb_key_desc {
14363 +       uByte bLength;
14364 +       uByte bDescriptorType;
14365 +       uByte tTKID[3];
14366 +       uByte bReserved;
14367 +       uByte KeyData[1];       /* variable length */
14368 +} UPACKED wusb_key_desc_t;
14369 +
14370 +/* WUSB BOS Descriptor (Binary device Object Store) */
14371 +typedef struct wusb_bos_desc {
14372 +       uByte bLength;
14373 +       uByte bDescriptorType;
14374 +       uWord wTotalLength;
14375 +       uByte bNumDeviceCaps;
14376 +} UPACKED wusb_bos_desc_t;
14377 +
14378 +#define USB_DEVICE_CAPABILITY_20_EXTENSION     0x02
14379 +typedef struct usb_dev_cap_20_ext_desc {
14380 +       uByte bLength;
14381 +       uByte bDescriptorType;
14382 +       uByte bDevCapabilityType;
14383 +#define USB_20_EXT_LPM                         0x02
14384 +       uDWord bmAttributes;
14385 +} UPACKED usb_dev_cap_20_ext_desc_t;
14386 +
14387 +#define USB_DEVICE_CAPABILITY_SS_USB           0x03
14388 +typedef struct usb_dev_cap_ss_usb {
14389 +       uByte bLength;
14390 +       uByte bDescriptorType;
14391 +       uByte bDevCapabilityType;
14392 +#define USB_DC_SS_USB_LTM_CAPABLE              0x02
14393 +       uByte bmAttributes;
14394 +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW                0x01
14395 +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL       0x02
14396 +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH       0x04
14397 +#define USB_DC_SS_USB_SPEED_SUPPORT_SS         0x08
14398 +       uWord wSpeedsSupported;
14399 +       uByte bFunctionalitySupport;
14400 +       uByte bU1DevExitLat;
14401 +       uWord wU2DevExitLat;
14402 +} UPACKED usb_dev_cap_ss_usb_t;
14403 +
14404 +#define USB_DEVICE_CAPABILITY_CONTAINER_ID     0x04
14405 +typedef struct usb_dev_cap_container_id {
14406 +       uByte bLength;
14407 +       uByte bDescriptorType;
14408 +       uByte bDevCapabilityType;
14409 +       uByte bReserved;
14410 +       uByte containerID[16];
14411 +} UPACKED usb_dev_cap_container_id_t;
14412 +
14413 +/* Device Capability Type Codes */
14414 +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
14415 +
14416 +/* Device Capability Descriptor */
14417 +typedef struct wusb_dev_cap_desc {
14418 +       uByte bLength;
14419 +       uByte bDescriptorType;
14420 +       uByte bDevCapabilityType;
14421 +       uByte caps[1];  /* Variable length */
14422 +} UPACKED wusb_dev_cap_desc_t;
14423 +
14424 +/* Device Capability Descriptor */
14425 +typedef struct wusb_dev_cap_uwb_desc {
14426 +       uByte bLength;
14427 +       uByte bDescriptorType;
14428 +       uByte bDevCapabilityType;
14429 +       uByte bmAttributes;
14430 +       uWord wPHYRates;        /* Bitmap */
14431 +       uByte bmTFITXPowerInfo;
14432 +       uByte bmFFITXPowerInfo;
14433 +       uWord bmBandGroup;
14434 +       uByte bReserved;
14435 +} UPACKED wusb_dev_cap_uwb_desc_t;
14436 +
14437 +/* Wireless USB Endpoint Companion Descriptor */
14438 +typedef struct wusb_endpoint_companion_desc {
14439 +       uByte bLength;
14440 +       uByte bDescriptorType;
14441 +       uByte bMaxBurst;
14442 +       uByte bMaxSequence;
14443 +       uWord wMaxStreamDelay;
14444 +       uWord wOverTheAirPacketSize;
14445 +       uByte bOverTheAirInterval;
14446 +       uByte bmCompAttributes;
14447 +} UPACKED wusb_endpoint_companion_desc_t;
14448 +
14449 +/* Wireless USB Numeric Association M1 Data Structure */
14450 +typedef struct wusb_m1_data {
14451 +       uByte version;
14452 +       uWord langId;
14453 +       uByte deviceFriendlyNameLength;
14454 +       uByte sha_256_m3[32];
14455 +       uByte deviceFriendlyName[256];
14456 +} UPACKED wusb_m1_data_t;
14457 +
14458 +typedef struct wusb_m2_data {
14459 +       uByte version;
14460 +       uWord langId;
14461 +       uByte hostFriendlyNameLength;
14462 +       uByte pkh[384];
14463 +       uByte hostFriendlyName[256];
14464 +} UPACKED wusb_m2_data_t;
14465 +
14466 +typedef struct wusb_m3_data {
14467 +       uByte pkd[384];
14468 +       uByte nd;
14469 +} UPACKED wusb_m3_data_t;
14470 +
14471 +typedef struct wusb_m4_data {
14472 +       uDWord _attributeTypeIdAndLength_1;
14473 +       uWord  associationTypeId;
14474 +
14475 +       uDWord _attributeTypeIdAndLength_2;
14476 +       uWord  associationSubTypeId;
14477 +
14478 +       uDWord _attributeTypeIdAndLength_3;
14479 +       uDWord length;
14480 +
14481 +       uDWord _attributeTypeIdAndLength_4;
14482 +       uDWord associationStatus;
14483 +
14484 +       uDWord _attributeTypeIdAndLength_5;
14485 +       uByte  chid[16];
14486 +
14487 +       uDWord _attributeTypeIdAndLength_6;
14488 +       uByte  cdid[16];
14489 +
14490 +       uDWord _attributeTypeIdAndLength_7;
14491 +       uByte  bandGroups[2];
14492 +} UPACKED wusb_m4_data_t;
14493 +
14494 +#ifdef _MSC_VER
14495 +#include <poppack.h>
14496 +#endif
14497 +
14498 +#ifdef __cplusplus
14499 +}
14500 +#endif
14501 +
14502 +#endif /* _USB_H_ */
14503 --- /dev/null
14504 +++ b/drivers/usb/host/dwc_otg/Makefile
14505 @@ -0,0 +1,80 @@
14506 +#
14507 +# Makefile for DWC_otg Highspeed USB controller driver
14508 +#
14509 +
14510 +ifneq ($(KERNELRELEASE),)
14511 +
14512 +# Use the BUS_INTERFACE variable to compile the software for either
14513 +# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.
14514 +ifeq ($(BUS_INTERFACE),)
14515 +#      BUS_INTERFACE = -DPCI_INTERFACE
14516 +#      BUS_INTERFACE = -DLM_INTERFACE
14517 +        BUS_INTERFACE = -DPLATFORM_INTERFACE
14518 +endif
14519 +
14520 +#ccflags-y     += -DDEBUG
14521 +#ccflags-y     += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
14522 +
14523 +# Use one of the following flags to compile the software in host-only or
14524 +# device-only mode.
14525 +#ccflags-y        += -DDWC_HOST_ONLY
14526 +#ccflags-y        += -DDWC_DEVICE_ONLY
14527 +
14528 +ccflags-y      += -Dlinux -DDWC_HS_ELECT_TST
14529 +#ccflags-y     += -DDWC_EN_ISOC
14530 +ccflags-y      += -I$(obj)/../dwc_common_port
14531 +#ccflags-y     += -I$(PORTLIB)
14532 +ccflags-y      += -DDWC_LINUX
14533 +ccflags-y      += $(CFI)
14534 +ccflags-y      += $(BUS_INTERFACE)
14535 +#ccflags-y     += -DDWC_DEV_SRPCAP
14536 +
14537 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
14538 +
14539 +dwc_otg-objs   := dwc_otg_driver.o dwc_otg_attr.o
14540 +dwc_otg-objs   += dwc_otg_cil.o dwc_otg_cil_intr.o
14541 +dwc_otg-objs   += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
14542 +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
14543 +dwc_otg-objs   += dwc_otg_adp.o
14544 +ifneq ($(CFI),)
14545 +dwc_otg-objs   += dwc_otg_cfi.o
14546 +endif
14547 +
14548 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
14549 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
14550 +
14551 +ifneq ($(kernrel3),2.6.20)
14552 +ccflags-y += $(CPPFLAGS)
14553 +endif
14554 +
14555 +else
14556 +
14557 +PWD            := $(shell pwd)
14558 +PORTLIB                := $(PWD)/../dwc_common_port
14559 +
14560 +# Command paths
14561 +CTAGS          := $(CTAGS)
14562 +DOXYGEN                := $(DOXYGEN)
14563 +
14564 +default: portlib
14565 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14566 +
14567 +install: default
14568 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
14569 +       $(MAKE) -C$(KDIR) M=$(PWD) modules_install
14570 +
14571 +portlib:
14572 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14573 +       cp $(PORTLIB)/Module.symvers $(PWD)/
14574 +
14575 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
14576 +       $(DOXYGEN) doc/doxygen.cfg
14577 +
14578 +tags:  $(wildcard *.[hc])
14579 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
14580 +
14581 +
14582 +clean:
14583 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
14584 +
14585 +endif
14586 --- /dev/null
14587 +++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14588 @@ -0,0 +1,224 @@
14589 +# Doxyfile 1.3.9.1
14590 +
14591 +#---------------------------------------------------------------------------
14592 +# Project related configuration options
14593 +#---------------------------------------------------------------------------
14594 +PROJECT_NAME           = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"
14595 +PROJECT_NUMBER         = v3.00a
14596 +OUTPUT_DIRECTORY       = ./doc/
14597 +CREATE_SUBDIRS         = NO
14598 +OUTPUT_LANGUAGE        = English
14599 +BRIEF_MEMBER_DESC      = YES
14600 +REPEAT_BRIEF           = YES
14601 +ABBREVIATE_BRIEF       = "The $name class" \
14602 +                         "The $name widget" \
14603 +                         "The $name file" \
14604 +                         is \
14605 +                         provides \
14606 +                         specifies \
14607 +                         contains \
14608 +                         represents \
14609 +                         a \
14610 +                         an \
14611 +                         the
14612 +ALWAYS_DETAILED_SEC    = NO
14613 +INLINE_INHERITED_MEMB  = NO
14614 +FULL_PATH_NAMES        = NO
14615 +STRIP_FROM_PATH        =
14616 +STRIP_FROM_INC_PATH    =
14617 +SHORT_NAMES            = NO
14618 +JAVADOC_AUTOBRIEF      = YES
14619 +MULTILINE_CPP_IS_BRIEF = NO
14620 +INHERIT_DOCS           = YES
14621 +DISTRIBUTE_GROUP_DOC   = NO
14622 +TAB_SIZE               = 8
14623 +ALIASES                =
14624 +OPTIMIZE_OUTPUT_FOR_C  = YES
14625 +OPTIMIZE_OUTPUT_JAVA   = NO
14626 +SUBGROUPING            = YES
14627 +#---------------------------------------------------------------------------
14628 +# Build related configuration options
14629 +#---------------------------------------------------------------------------
14630 +EXTRACT_ALL            = NO
14631 +EXTRACT_PRIVATE        = YES
14632 +EXTRACT_STATIC         = YES
14633 +EXTRACT_LOCAL_CLASSES  = YES
14634 +EXTRACT_LOCAL_METHODS  = NO
14635 +HIDE_UNDOC_MEMBERS     = NO
14636 +HIDE_UNDOC_CLASSES     = NO
14637 +HIDE_FRIEND_COMPOUNDS  = NO
14638 +HIDE_IN_BODY_DOCS      = NO
14639 +INTERNAL_DOCS          = NO
14640 +CASE_SENSE_NAMES       = NO
14641 +HIDE_SCOPE_NAMES       = NO
14642 +SHOW_INCLUDE_FILES     = YES
14643 +INLINE_INFO            = YES
14644 +SORT_MEMBER_DOCS       = NO
14645 +SORT_BRIEF_DOCS        = NO
14646 +SORT_BY_SCOPE_NAME     = NO
14647 +GENERATE_TODOLIST      = YES
14648 +GENERATE_TESTLIST      = YES
14649 +GENERATE_BUGLIST       = YES
14650 +GENERATE_DEPRECATEDLIST= YES
14651 +ENABLED_SECTIONS       =
14652 +MAX_INITIALIZER_LINES  = 30
14653 +SHOW_USED_FILES        = YES
14654 +SHOW_DIRECTORIES       = YES
14655 +#---------------------------------------------------------------------------
14656 +# configuration options related to warning and progress messages
14657 +#---------------------------------------------------------------------------
14658 +QUIET                  = YES
14659 +WARNINGS               = YES
14660 +WARN_IF_UNDOCUMENTED   = NO
14661 +WARN_IF_DOC_ERROR      = YES
14662 +WARN_FORMAT            = "$file:$line: $text"
14663 +WARN_LOGFILE           =
14664 +#---------------------------------------------------------------------------
14665 +# configuration options related to the input files
14666 +#---------------------------------------------------------------------------
14667 +INPUT                  = .
14668 +FILE_PATTERNS          = *.c \
14669 +                         *.h \
14670 +                         ./linux/*.c \
14671 +                         ./linux/*.h
14672 +RECURSIVE              = NO
14673 +EXCLUDE                = ./test/ \
14674 +                         ./dwc_otg/.AppleDouble/
14675 +EXCLUDE_SYMLINKS       = YES
14676 +EXCLUDE_PATTERNS       = *.mod.*
14677 +EXAMPLE_PATH           =
14678 +EXAMPLE_PATTERNS       = *
14679 +EXAMPLE_RECURSIVE      = NO
14680 +IMAGE_PATH             =
14681 +INPUT_FILTER           =
14682 +FILTER_PATTERNS        =
14683 +FILTER_SOURCE_FILES    = NO
14684 +#---------------------------------------------------------------------------
14685 +# configuration options related to source browsing
14686 +#---------------------------------------------------------------------------
14687 +SOURCE_BROWSER         = YES
14688 +INLINE_SOURCES         = NO
14689 +STRIP_CODE_COMMENTS    = YES
14690 +REFERENCED_BY_RELATION = NO
14691 +REFERENCES_RELATION    = NO
14692 +VERBATIM_HEADERS       = NO
14693 +#---------------------------------------------------------------------------
14694 +# configuration options related to the alphabetical class index
14695 +#---------------------------------------------------------------------------
14696 +ALPHABETICAL_INDEX     = NO
14697 +COLS_IN_ALPHA_INDEX    = 5
14698 +IGNORE_PREFIX          =
14699 +#---------------------------------------------------------------------------
14700 +# configuration options related to the HTML output
14701 +#---------------------------------------------------------------------------
14702 +GENERATE_HTML          = YES
14703 +HTML_OUTPUT            = html
14704 +HTML_FILE_EXTENSION    = .html
14705 +HTML_HEADER            =
14706 +HTML_FOOTER            =
14707 +HTML_STYLESHEET        =
14708 +HTML_ALIGN_MEMBERS     = YES
14709 +GENERATE_HTMLHELP      = NO
14710 +CHM_FILE               =
14711 +HHC_LOCATION           =
14712 +GENERATE_CHI           = NO
14713 +BINARY_TOC             = NO
14714 +TOC_EXPAND             = NO
14715 +DISABLE_INDEX          = NO
14716 +ENUM_VALUES_PER_LINE   = 4
14717 +GENERATE_TREEVIEW      = YES
14718 +TREEVIEW_WIDTH         = 250
14719 +#---------------------------------------------------------------------------
14720 +# configuration options related to the LaTeX output
14721 +#---------------------------------------------------------------------------
14722 +GENERATE_LATEX         = NO
14723 +LATEX_OUTPUT           = latex
14724 +LATEX_CMD_NAME         = latex
14725 +MAKEINDEX_CMD_NAME     = makeindex
14726 +COMPACT_LATEX          = NO
14727 +PAPER_TYPE             = a4wide
14728 +EXTRA_PACKAGES         =
14729 +LATEX_HEADER           =
14730 +PDF_HYPERLINKS         = NO
14731 +USE_PDFLATEX           = NO
14732 +LATEX_BATCHMODE        = NO
14733 +LATEX_HIDE_INDICES     = NO
14734 +#---------------------------------------------------------------------------
14735 +# configuration options related to the RTF output
14736 +#---------------------------------------------------------------------------
14737 +GENERATE_RTF           = NO
14738 +RTF_OUTPUT             = rtf
14739 +COMPACT_RTF            = NO
14740 +RTF_HYPERLINKS         = NO
14741 +RTF_STYLESHEET_FILE    =
14742 +RTF_EXTENSIONS_FILE    =
14743 +#---------------------------------------------------------------------------
14744 +# configuration options related to the man page output
14745 +#---------------------------------------------------------------------------
14746 +GENERATE_MAN           = NO
14747 +MAN_OUTPUT             = man
14748 +MAN_EXTENSION          = .3
14749 +MAN_LINKS              = NO
14750 +#---------------------------------------------------------------------------
14751 +# configuration options related to the XML output
14752 +#---------------------------------------------------------------------------
14753 +GENERATE_XML           = NO
14754 +XML_OUTPUT             = xml
14755 +XML_SCHEMA             =
14756 +XML_DTD                =
14757 +XML_PROGRAMLISTING     = YES
14758 +#---------------------------------------------------------------------------
14759 +# configuration options for the AutoGen Definitions output
14760 +#---------------------------------------------------------------------------
14761 +GENERATE_AUTOGEN_DEF   = NO
14762 +#---------------------------------------------------------------------------
14763 +# configuration options related to the Perl module output
14764 +#---------------------------------------------------------------------------
14765 +GENERATE_PERLMOD       = NO
14766 +PERLMOD_LATEX          = NO
14767 +PERLMOD_PRETTY         = YES
14768 +PERLMOD_MAKEVAR_PREFIX =
14769 +#---------------------------------------------------------------------------
14770 +# Configuration options related to the preprocessor
14771 +#---------------------------------------------------------------------------
14772 +ENABLE_PREPROCESSING   = YES
14773 +MACRO_EXPANSION        = YES
14774 +EXPAND_ONLY_PREDEF     = YES
14775 +SEARCH_INCLUDES        = YES
14776 +INCLUDE_PATH           =
14777 +INCLUDE_FILE_PATTERNS  =
14778 +PREDEFINED             = DEVICE_ATTR DWC_EN_ISOC
14779 +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
14780 +SKIP_FUNCTION_MACROS   = NO
14781 +#---------------------------------------------------------------------------
14782 +# Configuration::additions related to external references
14783 +#---------------------------------------------------------------------------
14784 +TAGFILES               =
14785 +GENERATE_TAGFILE       =
14786 +ALLEXTERNALS           = NO
14787 +EXTERNAL_GROUPS        = YES
14788 +PERL_PATH              = /usr/bin/perl
14789 +#---------------------------------------------------------------------------
14790 +# Configuration options related to the dot tool
14791 +#---------------------------------------------------------------------------
14792 +CLASS_DIAGRAMS         = YES
14793 +HIDE_UNDOC_RELATIONS   = YES
14794 +HAVE_DOT               = NO
14795 +CLASS_GRAPH            = YES
14796 +COLLABORATION_GRAPH    = YES
14797 +UML_LOOK               = NO
14798 +TEMPLATE_RELATIONS     = NO
14799 +INCLUDE_GRAPH          = YES
14800 +INCLUDED_BY_GRAPH      = YES
14801 +CALL_GRAPH             = NO
14802 +GRAPHICAL_HIERARCHY    = YES
14803 +DOT_IMAGE_FORMAT       = png
14804 +DOT_PATH               =
14805 +DOTFILE_DIRS           =
14806 +MAX_DOT_GRAPH_DEPTH    = 1000
14807 +GENERATE_LEGEND        = YES
14808 +DOT_CLEANUP            = YES
14809 +#---------------------------------------------------------------------------
14810 +# Configuration::additions related to the search engine
14811 +#---------------------------------------------------------------------------
14812 +SEARCHENGINE           = NO
14813 --- /dev/null
14814 +++ b/drivers/usb/host/dwc_otg/dummy_audio.c
14815 @@ -0,0 +1,1575 @@
14816 +/*
14817 + * zero.c -- Gadget Zero, for USB development
14818 + *
14819 + * Copyright (C) 2003-2004 David Brownell
14820 + * All rights reserved.
14821 + *
14822 + * Redistribution and use in source and binary forms, with or without
14823 + * modification, are permitted provided that the following conditions
14824 + * are met:
14825 + * 1. Redistributions of source code must retain the above copyright
14826 + *    notice, this list of conditions, and the following disclaimer,
14827 + *    without modification.
14828 + * 2. Redistributions in binary form must reproduce the above copyright
14829 + *    notice, this list of conditions and the following disclaimer in the
14830 + *    documentation and/or other materials provided with the distribution.
14831 + * 3. The names of the above-listed copyright holders may not be used
14832 + *    to endorse or promote products derived from this software without
14833 + *    specific prior written permission.
14834 + *
14835 + * ALTERNATIVELY, this software may be distributed under the terms of the
14836 + * GNU General Public License ("GPL") as published by the Free Software
14837 + * Foundation, either version 2 of that License or (at your option) any
14838 + * later version.
14839 + *
14840 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
14841 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14842 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14843 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14844 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14845 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14846 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14847 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14848 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14849 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14850 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14851 + */
14852 +
14853 +
14854 +/*
14855 + * Gadget Zero only needs two bulk endpoints, and is an example of how you
14856 + * can write a hardware-agnostic gadget driver running inside a USB device.
14857 + *
14858 + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
14859 + * affect most of the driver.
14860 + *
14861 + * Use it with the Linux host/master side "usbtest" driver to get a basic
14862 + * functional test of your device-side usb stack, or with "usb-skeleton".
14863 + *
14864 + * It supports two similar configurations.  One sinks whatever the usb host
14865 + * writes, and in return sources zeroes.  The other loops whatever the host
14866 + * writes back, so the host can read it.  Module options include:
14867 + *
14868 + *   buflen=N          default N=4096, buffer size used
14869 + *   qlen=N            default N=32, how many buffers in the loopback queue
14870 + *   loopdefault       default false, list loopback config first
14871 + *
14872 + * Many drivers will only have one configuration, letting them be much
14873 + * simpler if they also don't support high speed operation (like this
14874 + * driver does).
14875 + */
14876 +
14877 +#include <linux/config.h>
14878 +#include <linux/module.h>
14879 +#include <linux/kernel.h>
14880 +#include <linux/delay.h>
14881 +#include <linux/ioport.h>
14882 +#include <linux/sched.h>
14883 +#include <linux/slab.h>
14884 +#include <linux/smp_lock.h>
14885 +#include <linux/errno.h>
14886 +#include <linux/init.h>
14887 +#include <linux/timer.h>
14888 +#include <linux/list.h>
14889 +#include <linux/interrupt.h>
14890 +#include <linux/uts.h>
14891 +#include <linux/version.h>
14892 +#include <linux/device.h>
14893 +#include <linux/moduleparam.h>
14894 +#include <linux/proc_fs.h>
14895 +
14896 +#include <asm/byteorder.h>
14897 +#include <asm/io.h>
14898 +#include <asm/irq.h>
14899 +#include <asm/system.h>
14900 +#include <asm/unaligned.h>
14901 +
14902 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
14903 +# include <linux/usb/ch9.h>
14904 +#else
14905 +# include <linux/usb_ch9.h>
14906 +#endif
14907 +
14908 +#include <linux/usb_gadget.h>
14909 +
14910 +
14911 +/*-------------------------------------------------------------------------*/
14912 +/*-------------------------------------------------------------------------*/
14913 +
14914 +
14915 +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
14916 +{
14917 +       int     count = 0;
14918 +       u8      c;
14919 +       u16     uchar;
14920 +
14921 +       /* this insists on correct encodings, though not minimal ones.
14922 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
14923 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
14924 +        */
14925 +       while (len != 0 && (c = (u8) *s++) != 0) {
14926 +               if (unlikely(c & 0x80)) {
14927 +                       // 2-byte sequence:
14928 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
14929 +                       if ((c & 0xe0) == 0xc0) {
14930 +                               uchar = (c & 0x1f) << 6;
14931 +
14932 +                               c = (u8) *s++;
14933 +                               if ((c & 0xc0) != 0xc0)
14934 +                                       goto fail;
14935 +                               c &= 0x3f;
14936 +                               uchar |= c;
14937 +
14938 +                       // 3-byte sequence (most CJKV characters):
14939 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
14940 +                       } else if ((c & 0xf0) == 0xe0) {
14941 +                               uchar = (c & 0x0f) << 12;
14942 +
14943 +                               c = (u8) *s++;
14944 +                               if ((c & 0xc0) != 0xc0)
14945 +                                       goto fail;
14946 +                               c &= 0x3f;
14947 +                               uchar |= c << 6;
14948 +
14949 +                               c = (u8) *s++;
14950 +                               if ((c & 0xc0) != 0xc0)
14951 +                                       goto fail;
14952 +                               c &= 0x3f;
14953 +                               uchar |= c;
14954 +
14955 +                               /* no bogus surrogates */
14956 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
14957 +                                       goto fail;
14958 +
14959 +                       // 4-byte sequence (surrogate pairs, currently rare):
14960 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
14961 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
14962 +                       // (uuuuu = wwww + 1)
14963 +                       // FIXME accept the surrogate code points (only)
14964 +
14965 +                       } else
14966 +                               goto fail;
14967 +               } else
14968 +                       uchar = c;
14969 +               put_unaligned (cpu_to_le16 (uchar), cp++);
14970 +               count++;
14971 +               len--;
14972 +       }
14973 +       return count;
14974 +fail:
14975 +       return -1;
14976 +}
14977 +
14978 +
14979 +/**
14980 + * usb_gadget_get_string - fill out a string descriptor
14981 + * @table: of c strings encoded using UTF-8
14982 + * @id: string id, from low byte of wValue in get string descriptor
14983 + * @buf: at least 256 bytes
14984 + *
14985 + * Finds the UTF-8 string matching the ID, and converts it into a
14986 + * string descriptor in utf16-le.
14987 + * Returns length of descriptor (always even) or negative errno
14988 + *
14989 + * If your driver needs stings in multiple languages, you'll probably
14990 + * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
14991 + * using this routine after choosing which set of UTF-8 strings to use.
14992 + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
14993 + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
14994 + * characters (which are also widely used in C strings).
14995 + */
14996 +int
14997 +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
14998 +{
14999 +       struct usb_string       *s;
15000 +       int                     len;
15001 +
15002 +       /* descriptor 0 has the language id */
15003 +       if (id == 0) {
15004 +               buf [0] = 4;
15005 +               buf [1] = USB_DT_STRING;
15006 +               buf [2] = (u8) table->language;
15007 +               buf [3] = (u8) (table->language >> 8);
15008 +               return 4;
15009 +       }
15010 +       for (s = table->strings; s && s->s; s++)
15011 +               if (s->id == id)
15012 +                       break;
15013 +
15014 +       /* unrecognized: stall. */
15015 +       if (!s || !s->s)
15016 +               return -EINVAL;
15017 +
15018 +       /* string descriptors have length, tag, then UTF16-LE text */
15019 +       len = min ((size_t) 126, strlen (s->s));
15020 +       memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
15021 +       len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
15022 +       if (len < 0)
15023 +               return -EINVAL;
15024 +       buf [0] = (len + 1) * 2;
15025 +       buf [1] = USB_DT_STRING;
15026 +       return buf [0];
15027 +}
15028 +
15029 +
15030 +/*-------------------------------------------------------------------------*/
15031 +/*-------------------------------------------------------------------------*/
15032 +
15033 +
15034 +/**
15035 + * usb_descriptor_fillbuf - fill buffer with descriptors
15036 + * @buf: Buffer to be filled
15037 + * @buflen: Size of buf
15038 + * @src: Array of descriptor pointers, terminated by null pointer.
15039 + *
15040 + * Copies descriptors into the buffer, returning the length or a
15041 + * negative error code if they can't all be copied.  Useful when
15042 + * assembling descriptors for an associated set of interfaces used
15043 + * as part of configuring a composite device; or in other cases where
15044 + * sets of descriptors need to be marshaled.
15045 + */
15046 +int
15047 +usb_descriptor_fillbuf(void *buf, unsigned buflen,
15048 +               const struct usb_descriptor_header **src)
15049 +{
15050 +       u8      *dest = buf;
15051 +
15052 +       if (!src)
15053 +               return -EINVAL;
15054 +
15055 +       /* fill buffer from src[] until null descriptor ptr */
15056 +       for (; 0 != *src; src++) {
15057 +               unsigned                len = (*src)->bLength;
15058 +
15059 +               if (len > buflen)
15060 +                       return -EINVAL;
15061 +               memcpy(dest, *src, len);
15062 +               buflen -= len;
15063 +               dest += len;
15064 +       }
15065 +       return dest - (u8 *)buf;
15066 +}
15067 +
15068 +
15069 +/**
15070 + * usb_gadget_config_buf - builts a complete configuration descriptor
15071 + * @config: Header for the descriptor, including characteristics such
15072 + *     as power requirements and number of interfaces.
15073 + * @desc: Null-terminated vector of pointers to the descriptors (interface,
15074 + *     endpoint, etc) defining all functions in this device configuration.
15075 + * @buf: Buffer for the resulting configuration descriptor.
15076 + * @length: Length of buffer.  If this is not big enough to hold the
15077 + *     entire configuration descriptor, an error code will be returned.
15078 + *
15079 + * This copies descriptors into the response buffer, building a descriptor
15080 + * for that configuration.  It returns the buffer length or a negative
15081 + * status code.  The config.wTotalLength field is set to match the length
15082 + * of the result, but other descriptor fields (including power usage and
15083 + * interface count) must be set by the caller.
15084 + *
15085 + * Gadget drivers could use this when constructing a config descriptor
15086 + * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
15087 + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
15088 + */
15089 +int usb_gadget_config_buf(
15090 +       const struct usb_config_descriptor      *config,
15091 +       void                                    *buf,
15092 +       unsigned                                length,
15093 +       const struct usb_descriptor_header      **desc
15094 +)
15095 +{
15096 +       struct usb_config_descriptor            *cp = buf;
15097 +       int                                     len;
15098 +
15099 +       /* config descriptor first */
15100 +       if (length < USB_DT_CONFIG_SIZE || !desc)
15101 +               return -EINVAL;
15102 +       *cp = *config;
15103 +
15104 +       /* then interface/endpoint/class/vendor/... */
15105 +       len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
15106 +                       length - USB_DT_CONFIG_SIZE, desc);
15107 +       if (len < 0)
15108 +               return len;
15109 +       len += USB_DT_CONFIG_SIZE;
15110 +       if (len > 0xffff)
15111 +               return -EINVAL;
15112 +
15113 +       /* patch up the config descriptor */
15114 +       cp->bLength = USB_DT_CONFIG_SIZE;
15115 +       cp->bDescriptorType = USB_DT_CONFIG;
15116 +       cp->wTotalLength = cpu_to_le16(len);
15117 +       cp->bmAttributes |= USB_CONFIG_ATT_ONE;
15118 +       return len;
15119 +}
15120 +
15121 +/*-------------------------------------------------------------------------*/
15122 +/*-------------------------------------------------------------------------*/
15123 +
15124 +
15125 +#define RBUF_LEN (1024*1024)
15126 +static int rbuf_start;
15127 +static int rbuf_len;
15128 +static __u8 rbuf[RBUF_LEN];
15129 +
15130 +/*-------------------------------------------------------------------------*/
15131 +
15132 +#define DRIVER_VERSION         "St Patrick's Day 2004"
15133 +
15134 +static const char shortname [] = "zero";
15135 +static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";
15136 +
15137 +static const char source_sink [] = "source and sink data";
15138 +static const char loopback [] = "loop input to output";
15139 +
15140 +/*-------------------------------------------------------------------------*/
15141 +
15142 +/*
15143 + * driver assumes self-powered hardware, and
15144 + * has no way for users to trigger remote wakeup.
15145 + *
15146 + * this version autoconfigures as much as possible,
15147 + * which is reasonable for most "bulk-only" drivers.
15148 + */
15149 +static const char *EP_IN_NAME;         /* source */
15150 +static const char *EP_OUT_NAME;                /* sink */
15151 +
15152 +/*-------------------------------------------------------------------------*/
15153 +
15154 +/* big enough to hold our biggest descriptor */
15155 +#define USB_BUFSIZ     512
15156 +
15157 +struct zero_dev {
15158 +       spinlock_t              lock;
15159 +       struct usb_gadget       *gadget;
15160 +       struct usb_request      *req;           /* for control responses */
15161 +
15162 +       /* when configured, we have one of two configs:
15163 +        * - source data (in to host) and sink it (out from host)
15164 +        * - or loop it back (out from host back in to host)
15165 +        */
15166 +       u8                      config;
15167 +       struct usb_ep           *in_ep, *out_ep;
15168 +
15169 +       /* autoresume timer */
15170 +       struct timer_list       resume;
15171 +};
15172 +
15173 +#define xprintk(d,level,fmt,args...) \
15174 +       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
15175 +
15176 +#ifdef DEBUG
15177 +#define DBG(dev,fmt,args...) \
15178 +       xprintk(dev , KERN_DEBUG , fmt , ## args)
15179 +#else
15180 +#define DBG(dev,fmt,args...) \
15181 +       do { } while (0)
15182 +#endif /* DEBUG */
15183 +
15184 +#ifdef VERBOSE
15185 +#define VDBG   DBG
15186 +#else
15187 +#define VDBG(dev,fmt,args...) \
15188 +       do { } while (0)
15189 +#endif /* VERBOSE */
15190 +
15191 +#define ERROR(dev,fmt,args...) \
15192 +       xprintk(dev , KERN_ERR , fmt , ## args)
15193 +#define WARN(dev,fmt,args...) \
15194 +       xprintk(dev , KERN_WARNING , fmt , ## args)
15195 +#define INFO(dev,fmt,args...) \
15196 +       xprintk(dev , KERN_INFO , fmt , ## args)
15197 +
15198 +/*-------------------------------------------------------------------------*/
15199 +
15200 +static unsigned buflen = 4096;
15201 +static unsigned qlen = 32;
15202 +static unsigned pattern = 0;
15203 +
15204 +module_param (buflen, uint, S_IRUGO|S_IWUSR);
15205 +module_param (qlen, uint, S_IRUGO|S_IWUSR);
15206 +module_param (pattern, uint, S_IRUGO|S_IWUSR);
15207 +
15208 +/*
15209 + * if it's nonzero, autoresume says how many seconds to wait
15210 + * before trying to wake up the host after suspend.
15211 + */
15212 +static unsigned autoresume = 0;
15213 +module_param (autoresume, uint, 0);
15214 +
15215 +/*
15216 + * Normally the "loopback" configuration is second (index 1) so
15217 + * it's not the default.  Here's where to change that order, to
15218 + * work better with hosts where config changes are problematic.
15219 + * Or controllers (like superh) that only support one config.
15220 + */
15221 +static int loopdefault = 0;
15222 +
15223 +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
15224 +
15225 +/*-------------------------------------------------------------------------*/
15226 +
15227 +/* Thanks to NetChip Technologies for donating this product ID.
15228 + *
15229 + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
15230 + * Instead:  allocate your own, using normal USB-IF procedures.
15231 + */
15232 +#ifndef        CONFIG_USB_ZERO_HNPTEST
15233 +#define DRIVER_VENDOR_NUM      0x0525          /* NetChip */
15234 +#define DRIVER_PRODUCT_NUM     0xa4a0          /* Linux-USB "Gadget Zero" */
15235 +#else
15236 +#define DRIVER_VENDOR_NUM      0x1a0a          /* OTG test device IDs */
15237 +#define DRIVER_PRODUCT_NUM     0xbadd
15238 +#endif
15239 +
15240 +/*-------------------------------------------------------------------------*/
15241 +
15242 +/*
15243 + * DESCRIPTORS ... most are static, but strings and (full)
15244 + * configuration descriptors are built on demand.
15245 + */
15246 +
15247 +/*
15248 +#define STRING_MANUFACTURER            25
15249 +#define STRING_PRODUCT                 42
15250 +#define STRING_SERIAL                  101
15251 +*/
15252 +#define STRING_MANUFACTURER            1
15253 +#define STRING_PRODUCT                 2
15254 +#define STRING_SERIAL                  3
15255 +
15256 +#define STRING_SOURCE_SINK             250
15257 +#define STRING_LOOPBACK                        251
15258 +
15259 +/*
15260 + * This device advertises two configurations; these numbers work
15261 + * on a pxa250 as well as more flexible hardware.
15262 + */
15263 +#define        CONFIG_SOURCE_SINK      3
15264 +#define        CONFIG_LOOPBACK         2
15265 +
15266 +/*
15267 +static struct usb_device_descriptor
15268 +device_desc = {
15269 +       .bLength =              sizeof device_desc,
15270 +       .bDescriptorType =      USB_DT_DEVICE,
15271 +
15272 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15273 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15274 +
15275 +       .idVendor =             __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
15276 +       .idProduct =            __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
15277 +       .iManufacturer =        STRING_MANUFACTURER,
15278 +       .iProduct =             STRING_PRODUCT,
15279 +       .iSerialNumber =        STRING_SERIAL,
15280 +       .bNumConfigurations =   2,
15281 +};
15282 +*/
15283 +static struct usb_device_descriptor
15284 +device_desc = {
15285 +       .bLength =              sizeof device_desc,
15286 +       .bDescriptorType =      USB_DT_DEVICE,
15287 +       .bcdUSB =               __constant_cpu_to_le16 (0x0100),
15288 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
15289 +       .bDeviceSubClass =      0,
15290 +       .bDeviceProtocol =      0,
15291 +       .bMaxPacketSize0 =      64,
15292 +       .bcdDevice =            __constant_cpu_to_le16 (0x0100),
15293 +       .idVendor =             __constant_cpu_to_le16 (0x0499),
15294 +       .idProduct =            __constant_cpu_to_le16 (0x3002),
15295 +       .iManufacturer =        STRING_MANUFACTURER,
15296 +       .iProduct =             STRING_PRODUCT,
15297 +       .iSerialNumber =        STRING_SERIAL,
15298 +       .bNumConfigurations =   1,
15299 +};
15300 +
15301 +static struct usb_config_descriptor
15302 +z_config = {
15303 +       .bLength =              sizeof z_config,
15304 +       .bDescriptorType =      USB_DT_CONFIG,
15305 +
15306 +       /* compute wTotalLength on the fly */
15307 +       .bNumInterfaces =       2,
15308 +       .bConfigurationValue =  1,
15309 +       .iConfiguration =       0,
15310 +       .bmAttributes =         0x40,
15311 +       .bMaxPower =            0,      /* self-powered */
15312 +};
15313 +
15314 +
15315 +static struct usb_otg_descriptor
15316 +otg_descriptor = {
15317 +       .bLength =              sizeof otg_descriptor,
15318 +       .bDescriptorType =      USB_DT_OTG,
15319 +
15320 +       .bmAttributes =         USB_OTG_SRP,
15321 +};
15322 +
15323 +/* one interface in each configuration */
15324 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15325 +
15326 +/*
15327 + * usb 2.0 devices need to expose both high speed and full speed
15328 + * descriptors, unless they only run at full speed.
15329 + *
15330 + * that means alternate endpoint descriptors (bigger packets)
15331 + * and a "device qualifier" ... plus more construction options
15332 + * for the config descriptor.
15333 + */
15334 +
15335 +static struct usb_qualifier_descriptor
15336 +dev_qualifier = {
15337 +       .bLength =              sizeof dev_qualifier,
15338 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
15339 +
15340 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15341 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15342 +
15343 +       .bNumConfigurations =   2,
15344 +};
15345 +
15346 +
15347 +struct usb_cs_as_general_descriptor {
15348 +       __u8  bLength;
15349 +       __u8  bDescriptorType;
15350 +
15351 +       __u8  bDescriptorSubType;
15352 +       __u8  bTerminalLink;
15353 +       __u8  bDelay;
15354 +       __u16  wFormatTag;
15355 +} __attribute__ ((packed));
15356 +
15357 +struct usb_cs_as_format_descriptor {
15358 +       __u8  bLength;
15359 +       __u8  bDescriptorType;
15360 +
15361 +       __u8  bDescriptorSubType;
15362 +       __u8  bFormatType;
15363 +       __u8  bNrChannels;
15364 +       __u8  bSubframeSize;
15365 +       __u8  bBitResolution;
15366 +       __u8  bSamfreqType;
15367 +       __u8  tLowerSamFreq[3];
15368 +       __u8  tUpperSamFreq[3];
15369 +} __attribute__ ((packed));
15370 +
15371 +static const struct usb_interface_descriptor
15372 +z_audio_control_if_desc = {
15373 +       .bLength =              sizeof z_audio_control_if_desc,
15374 +       .bDescriptorType =      USB_DT_INTERFACE,
15375 +       .bInterfaceNumber = 0,
15376 +       .bAlternateSetting = 0,
15377 +       .bNumEndpoints = 0,
15378 +       .bInterfaceClass = USB_CLASS_AUDIO,
15379 +       .bInterfaceSubClass = 0x1,
15380 +       .bInterfaceProtocol = 0,
15381 +       .iInterface = 0,
15382 +};
15383 +
15384 +static const struct usb_interface_descriptor
15385 +z_audio_if_desc = {
15386 +       .bLength =              sizeof z_audio_if_desc,
15387 +       .bDescriptorType =      USB_DT_INTERFACE,
15388 +       .bInterfaceNumber = 1,
15389 +       .bAlternateSetting = 0,
15390 +       .bNumEndpoints = 0,
15391 +       .bInterfaceClass = USB_CLASS_AUDIO,
15392 +       .bInterfaceSubClass = 0x2,
15393 +       .bInterfaceProtocol = 0,
15394 +       .iInterface = 0,
15395 +};
15396 +
15397 +static const struct usb_interface_descriptor
15398 +z_audio_if_desc2 = {
15399 +       .bLength =              sizeof z_audio_if_desc,
15400 +       .bDescriptorType =      USB_DT_INTERFACE,
15401 +       .bInterfaceNumber = 1,
15402 +       .bAlternateSetting = 1,
15403 +       .bNumEndpoints = 1,
15404 +       .bInterfaceClass = USB_CLASS_AUDIO,
15405 +       .bInterfaceSubClass = 0x2,
15406 +       .bInterfaceProtocol = 0,
15407 +       .iInterface = 0,
15408 +};
15409 +
15410 +static const struct usb_cs_as_general_descriptor
15411 +z_audio_cs_as_if_desc = {
15412 +       .bLength = 7,
15413 +       .bDescriptorType = 0x24,
15414 +
15415 +       .bDescriptorSubType = 0x01,
15416 +       .bTerminalLink = 0x01,
15417 +       .bDelay = 0x0,
15418 +       .wFormatTag = __constant_cpu_to_le16 (0x0001)
15419 +};
15420 +
15421 +
15422 +static const struct usb_cs_as_format_descriptor
15423 +z_audio_cs_as_format_desc = {
15424 +       .bLength = 0xe,
15425 +       .bDescriptorType = 0x24,
15426 +
15427 +       .bDescriptorSubType = 2,
15428 +       .bFormatType = 1,
15429 +       .bNrChannels = 1,
15430 +       .bSubframeSize = 1,
15431 +       .bBitResolution = 8,
15432 +       .bSamfreqType = 0,
15433 +       .tLowerSamFreq = {0x7e, 0x13, 0x00},
15434 +       .tUpperSamFreq = {0xe2, 0xd6, 0x00},
15435 +};
15436 +
15437 +static const struct usb_endpoint_descriptor
15438 +z_iso_ep = {
15439 +       .bLength = 0x09,
15440 +       .bDescriptorType = 0x05,
15441 +       .bEndpointAddress = 0x04,
15442 +       .bmAttributes = 0x09,
15443 +       .wMaxPacketSize = 0x0038,
15444 +       .bInterval = 0x01,
15445 +       .bRefresh = 0x00,
15446 +       .bSynchAddress = 0x00,
15447 +};
15448 +
15449 +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15450 +
15451 +// 9 bytes
15452 +static char z_ac_interface_header_desc[] =
15453 +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
15454 +
15455 +// 12 bytes
15456 +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
15457 +                    0x03, 0x00, 0x00, 0x00};
15458 +// 13 bytes
15459 +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00,
15460 +                    0x02, 0x00, 0x02, 0x00, 0x00};
15461 +// 9 bytes
15462 +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02,
15463 +                    0x00};
15464 +
15465 +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,
15466 +                     0x00};
15467 +
15468 +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15469 +
15470 +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00,
15471 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15472 +
15473 +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15474 +                     0x00};
15475 +
15476 +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15477 +
15478 +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
15479 +                     0x00};
15480 +
15481 +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15482 +
15483 +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
15484 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15485 +
15486 +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15487 +                     0x00};
15488 +
15489 +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15490 +
15491 +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
15492 +                      0x00};
15493 +
15494 +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15495 +
15496 +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
15497 +                      0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15498 +
15499 +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
15500 +                      0x00};
15501 +
15502 +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15503 +
15504 +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00,
15505 +                      0x00};
15506 +
15507 +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15508 +
15509 +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00,
15510 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15511 +
15512 +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
15513 +                      0x00};
15514 +
15515 +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15516 +
15517 +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
15518 +                      0x00};
15519 +
15520 +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15521 +
15522 +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00,
15523 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15524 +
15525 +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
15526 +                      0x00};
15527 +
15528 +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15529 +
15530 +
15531 +
15532 +static const struct usb_descriptor_header *z_function [] = {
15533 +       (struct usb_descriptor_header *) &z_audio_control_if_desc,
15534 +       (struct usb_descriptor_header *) &z_ac_interface_header_desc,
15535 +       (struct usb_descriptor_header *) &z_0,
15536 +       (struct usb_descriptor_header *) &z_1,
15537 +       (struct usb_descriptor_header *) &z_2,
15538 +       (struct usb_descriptor_header *) &z_audio_if_desc,
15539 +       (struct usb_descriptor_header *) &z_audio_if_desc2,
15540 +       (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
15541 +       (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
15542 +       (struct usb_descriptor_header *) &z_iso_ep,
15543 +       (struct usb_descriptor_header *) &z_iso_ep2,
15544 +       (struct usb_descriptor_header *) &za_0,
15545 +       (struct usb_descriptor_header *) &za_1,
15546 +       (struct usb_descriptor_header *) &za_2,
15547 +       (struct usb_descriptor_header *) &za_3,
15548 +       (struct usb_descriptor_header *) &za_4,
15549 +       (struct usb_descriptor_header *) &za_5,
15550 +       (struct usb_descriptor_header *) &za_6,
15551 +       (struct usb_descriptor_header *) &za_7,
15552 +       (struct usb_descriptor_header *) &za_8,
15553 +       (struct usb_descriptor_header *) &za_9,
15554 +       (struct usb_descriptor_header *) &za_10,
15555 +       (struct usb_descriptor_header *) &za_11,
15556 +       (struct usb_descriptor_header *) &za_12,
15557 +       (struct usb_descriptor_header *) &za_13,
15558 +       (struct usb_descriptor_header *) &za_14,
15559 +       (struct usb_descriptor_header *) &za_15,
15560 +       (struct usb_descriptor_header *) &za_16,
15561 +       (struct usb_descriptor_header *) &za_17,
15562 +       (struct usb_descriptor_header *) &za_18,
15563 +       (struct usb_descriptor_header *) &za_19,
15564 +       (struct usb_descriptor_header *) &za_20,
15565 +       (struct usb_descriptor_header *) &za_21,
15566 +       (struct usb_descriptor_header *) &za_22,
15567 +       (struct usb_descriptor_header *) &za_23,
15568 +       (struct usb_descriptor_header *) &za_24,
15569 +       NULL,
15570 +};
15571 +
15572 +/* maxpacket and other transfer characteristics vary by speed. */
15573 +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
15574 +
15575 +#else
15576 +
15577 +/* if there's no high speed support, maxpacket doesn't change. */
15578 +#define ep_desc(g,hs,fs) fs
15579 +
15580 +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
15581 +
15582 +static char                            manufacturer [40];
15583 +//static char                          serial [40];
15584 +static char                            serial [] = "Ser 00 em";
15585 +
15586 +/* static strings, in UTF-8 */
15587 +static struct usb_string               strings [] = {
15588 +       { STRING_MANUFACTURER, manufacturer, },
15589 +       { STRING_PRODUCT, longname, },
15590 +       { STRING_SERIAL, serial, },
15591 +       { STRING_LOOPBACK, loopback, },
15592 +       { STRING_SOURCE_SINK, source_sink, },
15593 +       {  }                    /* end of list */
15594 +};
15595 +
15596 +static struct usb_gadget_strings       stringtab = {
15597 +       .language       = 0x0409,       /* en-us */
15598 +       .strings        = strings,
15599 +};
15600 +
15601 +/*
15602 + * config descriptors are also handcrafted.  these must agree with code
15603 + * that sets configurations, and with code managing interfaces and their
15604 + * altsettings.  other complexity may come from:
15605 + *
15606 + *  - high speed support, including "other speed config" rules
15607 + *  - multiple configurations
15608 + *  - interfaces with alternate settings
15609 + *  - embedded class or vendor-specific descriptors
15610 + *
15611 + * this handles high speed, and has a second config that could as easily
15612 + * have been an alternate interface setting (on most hardware).
15613 + *
15614 + * NOTE:  to demonstrate (and test) more USB capabilities, this driver
15615 + * should include an altsetting to test interrupt transfers, including
15616 + * high bandwidth modes at high speed.  (Maybe work like Intel's test
15617 + * device?)
15618 + */
15619 +static int
15620 +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
15621 +{
15622 +       int len;
15623 +       const struct usb_descriptor_header **function;
15624 +
15625 +       function = z_function;
15626 +       len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
15627 +       if (len < 0)
15628 +               return len;
15629 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
15630 +       return len;
15631 +}
15632 +
15633 +/*-------------------------------------------------------------------------*/
15634 +
15635 +static struct usb_request *
15636 +alloc_ep_req (struct usb_ep *ep, unsigned length)
15637 +{
15638 +       struct usb_request      *req;
15639 +
15640 +       req = usb_ep_alloc_request (ep, GFP_ATOMIC);
15641 +       if (req) {
15642 +               req->length = length;
15643 +               req->buf = usb_ep_alloc_buffer (ep, length,
15644 +                               &req->dma, GFP_ATOMIC);
15645 +               if (!req->buf) {
15646 +                       usb_ep_free_request (ep, req);
15647 +                       req = NULL;
15648 +               }
15649 +       }
15650 +       return req;
15651 +}
15652 +
15653 +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
15654 +{
15655 +       if (req->buf)
15656 +               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
15657 +       usb_ep_free_request (ep, req);
15658 +}
15659 +
15660 +/*-------------------------------------------------------------------------*/
15661 +
15662 +/* optionally require specific source/sink data patterns  */
15663 +
15664 +static int
15665 +check_read_data (
15666 +       struct zero_dev         *dev,
15667 +       struct usb_ep           *ep,
15668 +       struct usb_request      *req
15669 +)
15670 +{
15671 +       unsigned        i;
15672 +       u8              *buf = req->buf;
15673 +
15674 +       for (i = 0; i < req->actual; i++, buf++) {
15675 +               switch (pattern) {
15676 +               /* all-zeroes has no synchronization issues */
15677 +               case 0:
15678 +                       if (*buf == 0)
15679 +                               continue;
15680 +                       break;
15681 +               /* mod63 stays in sync with short-terminated transfers,
15682 +                * or otherwise when host and gadget agree on how large
15683 +                * each usb transfer request should be.  resync is done
15684 +                * with set_interface or set_config.
15685 +                */
15686 +               case 1:
15687 +                       if (*buf == (u8)(i % 63))
15688 +                               continue;
15689 +                       break;
15690 +               }
15691 +               ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
15692 +               usb_ep_set_halt (ep);
15693 +               return -EINVAL;
15694 +       }
15695 +       return 0;
15696 +}
15697 +
15698 +/*-------------------------------------------------------------------------*/
15699 +
15700 +static void zero_reset_config (struct zero_dev *dev)
15701 +{
15702 +       if (dev->config == 0)
15703 +               return;
15704 +
15705 +       DBG (dev, "reset config\n");
15706 +
15707 +       /* just disable endpoints, forcing completion of pending i/o.
15708 +        * all our completion handlers free their requests in this case.
15709 +        */
15710 +       if (dev->in_ep) {
15711 +               usb_ep_disable (dev->in_ep);
15712 +               dev->in_ep = NULL;
15713 +       }
15714 +       if (dev->out_ep) {
15715 +               usb_ep_disable (dev->out_ep);
15716 +               dev->out_ep = NULL;
15717 +       }
15718 +       dev->config = 0;
15719 +       del_timer (&dev->resume);
15720 +}
15721 +
15722 +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
15723 +
15724 +static void
15725 +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
15726 +{
15727 +       struct zero_dev *dev = ep->driver_data;
15728 +       int             status = req->status;
15729 +       int i, j;
15730 +
15731 +       switch (status) {
15732 +
15733 +       case 0:                         /* normal completion? */
15734 +               //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
15735 +               for (i=0, j=rbuf_start; i<req->actual; i++) {
15736 +                       //printk ("%02x ", ((__u8*)req->buf)[i]);
15737 +                       rbuf[j] = ((__u8*)req->buf)[i];
15738 +                       j++;
15739 +                       if (j >= RBUF_LEN) j=0;
15740 +               }
15741 +               rbuf_start = j;
15742 +               //printk ("\n\n");
15743 +
15744 +               if (rbuf_len < RBUF_LEN) {
15745 +                       rbuf_len += req->actual;
15746 +                       if (rbuf_len > RBUF_LEN) {
15747 +                               rbuf_len = RBUF_LEN;
15748 +                       }
15749 +               }
15750 +
15751 +               break;
15752 +
15753 +       /* this endpoint is normally active while we're configured */
15754 +       case -ECONNABORTED:             /* hardware forced ep reset */
15755 +       case -ECONNRESET:               /* request dequeued */
15756 +       case -ESHUTDOWN:                /* disconnect from host */
15757 +               VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
15758 +                               req->actual, req->length);
15759 +               if (ep == dev->out_ep)
15760 +                       check_read_data (dev, ep, req);
15761 +               free_ep_req (ep, req);
15762 +               return;
15763 +
15764 +       case -EOVERFLOW:                /* buffer overrun on read means that
15765 +                                        * we didn't provide a big enough
15766 +                                        * buffer.
15767 +                                        */
15768 +       default:
15769 +#if 1
15770 +               DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
15771 +                               status, req->actual, req->length);
15772 +#endif
15773 +       case -EREMOTEIO:                /* short read */
15774 +               break;
15775 +       }
15776 +
15777 +       status = usb_ep_queue (ep, req, GFP_ATOMIC);
15778 +       if (status) {
15779 +               ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
15780 +                               ep->name, req->length, status);
15781 +               usb_ep_set_halt (ep);
15782 +               /* FIXME recover later ... somehow */
15783 +       }
15784 +}
15785 +
15786 +static struct usb_request *
15787 +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
15788 +{
15789 +       struct usb_request      *req;
15790 +       int                     status;
15791 +
15792 +       req = alloc_ep_req (ep, 512);
15793 +       if (!req)
15794 +               return NULL;
15795 +
15796 +       req->complete = zero_isoc_complete;
15797 +
15798 +       status = usb_ep_queue (ep, req, gfp_flags);
15799 +       if (status) {
15800 +               struct zero_dev *dev = ep->driver_data;
15801 +
15802 +               ERROR (dev, "start %s --> %d\n", ep->name, status);
15803 +               free_ep_req (ep, req);
15804 +               req = NULL;
15805 +       }
15806 +
15807 +       return req;
15808 +}
15809 +
15810 +/* change our operational config.  this code must agree with the code
15811 + * that returns config descriptors, and altsetting code.
15812 + *
15813 + * it's also responsible for power management interactions. some
15814 + * configurations might not work with our current power sources.
15815 + *
15816 + * note that some device controller hardware will constrain what this
15817 + * code can do, perhaps by disallowing more than one configuration or
15818 + * by limiting configuration choices (like the pxa2xx).
15819 + */
15820 +static int
15821 +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
15822 +{
15823 +       int                     result = 0;
15824 +       struct usb_gadget       *gadget = dev->gadget;
15825 +       const struct usb_endpoint_descriptor    *d;
15826 +       struct usb_ep           *ep;
15827 +
15828 +       if (number == dev->config)
15829 +               return 0;
15830 +
15831 +       zero_reset_config (dev);
15832 +
15833 +       gadget_for_each_ep (ep, gadget) {
15834 +
15835 +               if (strcmp (ep->name, "ep4") == 0) {
15836 +
15837 +                       d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
15838 +                       result = usb_ep_enable (ep, d);
15839 +
15840 +                       if (result == 0) {
15841 +                               ep->driver_data = dev;
15842 +                               dev->in_ep = ep;
15843 +
15844 +                               if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
15845 +
15846 +                                       dev->in_ep = ep;
15847 +                                       continue;
15848 +                               }
15849 +
15850 +                               usb_ep_disable (ep);
15851 +                               result = -EIO;
15852 +                       }
15853 +               }
15854 +
15855 +       }
15856 +
15857 +       dev->config = number;
15858 +       return result;
15859 +}
15860 +
15861 +/*-------------------------------------------------------------------------*/
15862 +
15863 +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
15864 +{
15865 +       if (req->status || req->actual != req->length)
15866 +               DBG ((struct zero_dev *) ep->driver_data,
15867 +                               "setup complete --> %d, %d/%d\n",
15868 +                               req->status, req->actual, req->length);
15869 +}
15870 +
15871 +/*
15872 + * The setup() callback implements all the ep0 functionality that's
15873 + * not handled lower down, in hardware or the hardware driver (like
15874 + * device and endpoint feature flags, and their status).  It's all
15875 + * housekeeping for the gadget function we're implementing.  Most of
15876 + * the work is in config-specific setup.
15877 + */
15878 +static int
15879 +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
15880 +{
15881 +       struct zero_dev         *dev = get_gadget_data (gadget);
15882 +       struct usb_request      *req = dev->req;
15883 +       int                     value = -EOPNOTSUPP;
15884 +
15885 +       /* usually this stores reply data in the pre-allocated ep0 buffer,
15886 +        * but config change events will reconfigure hardware.
15887 +        */
15888 +       req->zero = 0;
15889 +       switch (ctrl->bRequest) {
15890 +
15891 +       case USB_REQ_GET_DESCRIPTOR:
15892 +
15893 +               switch (ctrl->wValue >> 8) {
15894 +
15895 +               case USB_DT_DEVICE:
15896 +                       value = min (ctrl->wLength, (u16) sizeof device_desc);
15897 +                       memcpy (req->buf, &device_desc, value);
15898 +                       break;
15899 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15900 +               case USB_DT_DEVICE_QUALIFIER:
15901 +                       if (!gadget->is_dualspeed)
15902 +                               break;
15903 +                       value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
15904 +                       memcpy (req->buf, &dev_qualifier, value);
15905 +                       break;
15906 +
15907 +               case USB_DT_OTHER_SPEED_CONFIG:
15908 +                       if (!gadget->is_dualspeed)
15909 +                               break;
15910 +                       // FALLTHROUGH
15911 +#endif /* CONFIG_USB_GADGET_DUALSPEED */
15912 +               case USB_DT_CONFIG:
15913 +                       value = config_buf (gadget, req->buf,
15914 +                                       ctrl->wValue >> 8,
15915 +                                       ctrl->wValue & 0xff);
15916 +                       if (value >= 0)
15917 +                               value = min (ctrl->wLength, (u16) value);
15918 +                       break;
15919 +
15920 +               case USB_DT_STRING:
15921 +                       /* wIndex == language code.
15922 +                        * this driver only handles one language, you can
15923 +                        * add string tables for other languages, using
15924 +                        * any UTF-8 characters
15925 +                        */
15926 +                       value = usb_gadget_get_string (&stringtab,
15927 +                                       ctrl->wValue & 0xff, req->buf);
15928 +                       if (value >= 0) {
15929 +                               value = min (ctrl->wLength, (u16) value);
15930 +                       }
15931 +                       break;
15932 +               }
15933 +               break;
15934 +
15935 +       /* currently two configs, two speeds */
15936 +       case USB_REQ_SET_CONFIGURATION:
15937 +               if (ctrl->bRequestType != 0)
15938 +                       goto unknown;
15939 +
15940 +               spin_lock (&dev->lock);
15941 +               value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
15942 +               spin_unlock (&dev->lock);
15943 +               break;
15944 +       case USB_REQ_GET_CONFIGURATION:
15945 +               if (ctrl->bRequestType != USB_DIR_IN)
15946 +                       goto unknown;
15947 +               *(u8 *)req->buf = dev->config;
15948 +               value = min (ctrl->wLength, (u16) 1);
15949 +               break;
15950 +
15951 +       /* until we add altsetting support, or other interfaces,
15952 +        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
15953 +        * and already killed pending endpoint I/O.
15954 +        */
15955 +       case USB_REQ_SET_INTERFACE:
15956 +
15957 +               if (ctrl->bRequestType != USB_RECIP_INTERFACE)
15958 +                       goto unknown;
15959 +               spin_lock (&dev->lock);
15960 +               if (dev->config) {
15961 +                       u8              config = dev->config;
15962 +
15963 +                       /* resets interface configuration, forgets about
15964 +                        * previous transaction state (queued bufs, etc)
15965 +                        * and re-inits endpoint state (toggle etc)
15966 +                        * no response queued, just zero status == success.
15967 +                        * if we had more than one interface we couldn't
15968 +                        * use this "reset the config" shortcut.
15969 +                        */
15970 +                       zero_reset_config (dev);
15971 +                       zero_set_config (dev, config, GFP_ATOMIC);
15972 +                       value = 0;
15973 +               }
15974 +               spin_unlock (&dev->lock);
15975 +               break;
15976 +       case USB_REQ_GET_INTERFACE:
15977 +               if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
15978 +                       value = ctrl->wLength;
15979 +                       break;
15980 +               }
15981 +               else {
15982 +                       if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
15983 +                               goto unknown;
15984 +                       if (!dev->config)
15985 +                               break;
15986 +                       if (ctrl->wIndex != 0) {
15987 +                               value = -EDOM;
15988 +                               break;
15989 +                       }
15990 +                       *(u8 *)req->buf = 0;
15991 +                       value = min (ctrl->wLength, (u16) 1);
15992 +               }
15993 +               break;
15994 +
15995 +       /*
15996 +        * These are the same vendor-specific requests supported by
15997 +        * Intel's USB 2.0 compliance test devices.  We exceed that
15998 +        * device spec by allowing multiple-packet requests.
15999 +        */
16000 +       case 0x5b:      /* control WRITE test -- fill the buffer */
16001 +               if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
16002 +                       goto unknown;
16003 +               if (ctrl->wValue || ctrl->wIndex)
16004 +                       break;
16005 +               /* just read that many bytes into the buffer */
16006 +               if (ctrl->wLength > USB_BUFSIZ)
16007 +                       break;
16008 +               value = ctrl->wLength;
16009 +               break;
16010 +       case 0x5c:      /* control READ test -- return the buffer */
16011 +               if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
16012 +                       goto unknown;
16013 +               if (ctrl->wValue || ctrl->wIndex)
16014 +                       break;
16015 +               /* expect those bytes are still in the buffer; send back */
16016 +               if (ctrl->wLength > USB_BUFSIZ
16017 +                               || ctrl->wLength != req->length)
16018 +                       break;
16019 +               value = ctrl->wLength;
16020 +               break;
16021 +
16022 +       case 0x01: // SET_CUR
16023 +       case 0x02:
16024 +       case 0x03:
16025 +       case 0x04:
16026 +       case 0x05:
16027 +               value = ctrl->wLength;
16028 +               break;
16029 +       case 0x81:
16030 +               switch (ctrl->wValue) {
16031 +               case 0x0201:
16032 +               case 0x0202:
16033 +                       ((u8*)req->buf)[0] = 0x00;
16034 +                       ((u8*)req->buf)[1] = 0xe3;
16035 +                       break;
16036 +               case 0x0300:
16037 +               case 0x0500:
16038 +                       ((u8*)req->buf)[0] = 0x00;
16039 +                       break;
16040 +               }
16041 +               //((u8*)req->buf)[0] = 0x81;
16042 +               //((u8*)req->buf)[1] = 0x81;
16043 +               value = ctrl->wLength;
16044 +               break;
16045 +       case 0x82:
16046 +               switch (ctrl->wValue) {
16047 +               case 0x0201:
16048 +               case 0x0202:
16049 +                       ((u8*)req->buf)[0] = 0x00;
16050 +                       ((u8*)req->buf)[1] = 0xc3;
16051 +                       break;
16052 +               case 0x0300:
16053 +               case 0x0500:
16054 +                       ((u8*)req->buf)[0] = 0x00;
16055 +                       break;
16056 +               }
16057 +               //((u8*)req->buf)[0] = 0x82;
16058 +               //((u8*)req->buf)[1] = 0x82;
16059 +               value = ctrl->wLength;
16060 +               break;
16061 +       case 0x83:
16062 +               switch (ctrl->wValue) {
16063 +               case 0x0201:
16064 +               case 0x0202:
16065 +                       ((u8*)req->buf)[0] = 0x00;
16066 +                       ((u8*)req->buf)[1] = 0x00;
16067 +                       break;
16068 +               case 0x0300:
16069 +                       ((u8*)req->buf)[0] = 0x60;
16070 +                       break;
16071 +               case 0x0500:
16072 +                       ((u8*)req->buf)[0] = 0x18;
16073 +                       break;
16074 +               }
16075 +               //((u8*)req->buf)[0] = 0x83;
16076 +               //((u8*)req->buf)[1] = 0x83;
16077 +               value = ctrl->wLength;
16078 +               break;
16079 +       case 0x84:
16080 +               switch (ctrl->wValue) {
16081 +               case 0x0201:
16082 +               case 0x0202:
16083 +                       ((u8*)req->buf)[0] = 0x00;
16084 +                       ((u8*)req->buf)[1] = 0x01;
16085 +                       break;
16086 +               case 0x0300:
16087 +               case 0x0500:
16088 +                       ((u8*)req->buf)[0] = 0x08;
16089 +                       break;
16090 +               }
16091 +               //((u8*)req->buf)[0] = 0x84;
16092 +               //((u8*)req->buf)[1] = 0x84;
16093 +               value = ctrl->wLength;
16094 +               break;
16095 +       case 0x85:
16096 +               ((u8*)req->buf)[0] = 0x85;
16097 +               ((u8*)req->buf)[1] = 0x85;
16098 +               value = ctrl->wLength;
16099 +               break;
16100 +
16101 +
16102 +       default:
16103 +unknown:
16104 +               printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
16105 +                       ctrl->bRequestType, ctrl->bRequest,
16106 +                       ctrl->wValue, ctrl->wIndex, ctrl->wLength);
16107 +       }
16108 +
16109 +       /* respond with data transfer before status phase? */
16110 +       if (value >= 0) {
16111 +               req->length = value;
16112 +               req->zero = value < ctrl->wLength
16113 +                               && (value % gadget->ep0->maxpacket) == 0;
16114 +               value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
16115 +               if (value < 0) {
16116 +                       DBG (dev, "ep_queue < 0 --> %d\n", value);
16117 +                       req->status = 0;
16118 +                       zero_setup_complete (gadget->ep0, req);
16119 +               }
16120 +       }
16121 +
16122 +       /* device either stalls (value < 0) or reports success */
16123 +       return value;
16124 +}
16125 +
16126 +static void
16127 +zero_disconnect (struct usb_gadget *gadget)
16128 +{
16129 +       struct zero_dev         *dev = get_gadget_data (gadget);
16130 +       unsigned long           flags;
16131 +
16132 +       spin_lock_irqsave (&dev->lock, flags);
16133 +       zero_reset_config (dev);
16134 +
16135 +       /* a more significant application might have some non-usb
16136 +        * activities to quiesce here, saving resources like power
16137 +        * or pushing the notification up a network stack.
16138 +        */
16139 +       spin_unlock_irqrestore (&dev->lock, flags);
16140 +
16141 +       /* next we may get setup() calls to enumerate new connections;
16142 +        * or an unbind() during shutdown (including removing module).
16143 +        */
16144 +}
16145 +
16146 +static void
16147 +zero_autoresume (unsigned long _dev)
16148 +{
16149 +       struct zero_dev *dev = (struct zero_dev *) _dev;
16150 +       int             status;
16151 +
16152 +       /* normally the host would be woken up for something
16153 +        * more significant than just a timer firing...
16154 +        */
16155 +       if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
16156 +               status = usb_gadget_wakeup (dev->gadget);
16157 +               DBG (dev, "wakeup --> %d\n", status);
16158 +       }
16159 +}
16160 +
16161 +/*-------------------------------------------------------------------------*/
16162 +
16163 +static void
16164 +zero_unbind (struct usb_gadget *gadget)
16165 +{
16166 +       struct zero_dev         *dev = get_gadget_data (gadget);
16167 +
16168 +       DBG (dev, "unbind\n");
16169 +
16170 +       /* we've already been disconnected ... no i/o is active */
16171 +       if (dev->req)
16172 +               free_ep_req (gadget->ep0, dev->req);
16173 +       del_timer_sync (&dev->resume);
16174 +       kfree (dev);
16175 +       set_gadget_data (gadget, NULL);
16176 +}
16177 +
16178 +static int
16179 +zero_bind (struct usb_gadget *gadget)
16180 +{
16181 +       struct zero_dev         *dev;
16182 +       //struct usb_ep         *ep;
16183 +
16184 +       printk("binding\n");
16185 +       /*
16186 +        * DRIVER POLICY CHOICE:  you may want to do this differently.
16187 +        * One thing to avoid is reusing a bcdDevice revision code
16188 +        * with different host-visible configurations or behavior
16189 +        * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
16190 +        */
16191 +       //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
16192 +
16193 +
16194 +       /* ok, we made sense of the hardware ... */
16195 +       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
16196 +       if (!dev)
16197 +               return -ENOMEM;
16198 +       memset (dev, 0, sizeof *dev);
16199 +       spin_lock_init (&dev->lock);
16200 +       dev->gadget = gadget;
16201 +       set_gadget_data (gadget, dev);
16202 +
16203 +       /* preallocate control response and buffer */
16204 +       dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
16205 +       if (!dev->req)
16206 +               goto enomem;
16207 +       dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
16208 +                               &dev->req->dma, GFP_KERNEL);
16209 +       if (!dev->req->buf)
16210 +               goto enomem;
16211 +
16212 +       dev->req->complete = zero_setup_complete;
16213 +
16214 +       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
16215 +
16216 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16217 +       /* assume ep0 uses the same value for both speeds ... */
16218 +       dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
16219 +
16220 +       /* and that all endpoints are dual-speed */
16221 +       //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
16222 +       //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
16223 +#endif
16224 +
16225 +       usb_gadget_set_selfpowered (gadget);
16226 +
16227 +       init_timer (&dev->resume);
16228 +       dev->resume.function = zero_autoresume;
16229 +       dev->resume.data = (unsigned long) dev;
16230 +
16231 +       gadget->ep0->driver_data = dev;
16232 +
16233 +       INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
16234 +       INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
16235 +               EP_OUT_NAME, EP_IN_NAME);
16236 +
16237 +       snprintf (manufacturer, sizeof manufacturer,
16238 +               UTS_SYSNAME " " UTS_RELEASE " with %s",
16239 +               gadget->name);
16240 +
16241 +       return 0;
16242 +
16243 +enomem:
16244 +       zero_unbind (gadget);
16245 +       return -ENOMEM;
16246 +}
16247 +
16248 +/*-------------------------------------------------------------------------*/
16249 +
16250 +static void
16251 +zero_suspend (struct usb_gadget *gadget)
16252 +{
16253 +       struct zero_dev         *dev = get_gadget_data (gadget);
16254 +
16255 +       if (gadget->speed == USB_SPEED_UNKNOWN)
16256 +               return;
16257 +
16258 +       if (autoresume) {
16259 +               mod_timer (&dev->resume, jiffies + (HZ * autoresume));
16260 +               DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
16261 +       } else
16262 +               DBG (dev, "suspend\n");
16263 +}
16264 +
16265 +static void
16266 +zero_resume (struct usb_gadget *gadget)
16267 +{
16268 +       struct zero_dev         *dev = get_gadget_data (gadget);
16269 +
16270 +       DBG (dev, "resume\n");
16271 +       del_timer (&dev->resume);
16272 +}
16273 +
16274 +
16275 +/*-------------------------------------------------------------------------*/
16276 +
16277 +static struct usb_gadget_driver zero_driver = {
16278 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16279 +       .speed          = USB_SPEED_HIGH,
16280 +#else
16281 +       .speed          = USB_SPEED_FULL,
16282 +#endif
16283 +       .function       = (char *) longname,
16284 +       .bind           = zero_bind,
16285 +       .unbind         = zero_unbind,
16286 +
16287 +       .setup          = zero_setup,
16288 +       .disconnect     = zero_disconnect,
16289 +
16290 +       .suspend        = zero_suspend,
16291 +       .resume         = zero_resume,
16292 +
16293 +       .driver         = {
16294 +               .name           = (char *) shortname,
16295 +               // .shutdown = ...
16296 +               // .suspend = ...
16297 +               // .resume = ...
16298 +       },
16299 +};
16300 +
16301 +MODULE_AUTHOR ("David Brownell");
16302 +MODULE_LICENSE ("Dual BSD/GPL");
16303 +
16304 +static struct proc_dir_entry *pdir, *pfile;
16305 +
16306 +static int isoc_read_data (char *page, char **start,
16307 +                          off_t off, int count,
16308 +                          int *eof, void *data)
16309 +{
16310 +       int i;
16311 +       static int c = 0;
16312 +       static int done = 0;
16313 +       static int s = 0;
16314 +
16315 +/*
16316 +       printk ("\ncount: %d\n", count);
16317 +       printk ("rbuf_start: %d\n", rbuf_start);
16318 +       printk ("rbuf_len: %d\n", rbuf_len);
16319 +       printk ("off: %d\n", off);
16320 +       printk ("start: %p\n\n", *start);
16321 +*/
16322 +       if (done) {
16323 +               c = 0;
16324 +               done = 0;
16325 +               *eof = 1;
16326 +               return 0;
16327 +       }
16328 +
16329 +       if (c == 0) {
16330 +               if (rbuf_len == RBUF_LEN)
16331 +                       s = rbuf_start;
16332 +               else s = 0;
16333 +       }
16334 +
16335 +       for (i=0; i<count && c<rbuf_len; i++, c++) {
16336 +               page[i] = rbuf[(c+s) % RBUF_LEN];
16337 +       }
16338 +       *start = page;
16339 +
16340 +       if (c >= rbuf_len) {
16341 +               *eof = 1;
16342 +               done = 1;
16343 +       }
16344 +
16345 +
16346 +       return i;
16347 +}
16348 +
16349 +static int __init init (void)
16350 +{
16351 +
16352 +       int retval = 0;
16353 +
16354 +       pdir = proc_mkdir("isoc_test", NULL);
16355 +       if(pdir == NULL) {
16356 +               retval = -ENOMEM;
16357 +               printk("Error creating dir\n");
16358 +               goto done;
16359 +       }
16360 +       pdir->owner = THIS_MODULE;
16361 +
16362 +       pfile = create_proc_read_entry("isoc_data",
16363 +                                      0444, pdir,
16364 +                                      isoc_read_data,
16365 +                                      NULL);
16366 +       if (pfile == NULL) {
16367 +               retval = -ENOMEM;
16368 +               printk("Error creating file\n");
16369 +               goto no_file;
16370 +       }
16371 +       pfile->owner = THIS_MODULE;
16372 +
16373 +       return usb_gadget_register_driver (&zero_driver);
16374 +
16375 + no_file:
16376 +       remove_proc_entry("isoc_data", NULL);
16377 + done:
16378 +       return retval;
16379 +}
16380 +module_init (init);
16381 +
16382 +static void __exit cleanup (void)
16383 +{
16384 +
16385 +       usb_gadget_unregister_driver (&zero_driver);
16386 +
16387 +       remove_proc_entry("isoc_data", pdir);
16388 +       remove_proc_entry("isoc_test", NULL);
16389 +}
16390 +module_exit (cleanup);
16391 --- /dev/null
16392 +++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16393 @@ -0,0 +1,142 @@
16394 +/* ==========================================================================
16395 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16396 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16397 + * otherwise expressly agreed to in writing between Synopsys and you.
16398 + *
16399 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16400 + * any End User Software License Agreement or Agreement for Licensed Product
16401 + * with Synopsys or any supplement thereto. You are permitted to use and
16402 + * redistribute this Software in source and binary forms, with or without
16403 + * modification, provided that redistributions of source code must retain this
16404 + * notice. You may not view, use, disclose, copy or distribute this file or
16405 + * any information contained herein except pursuant to this license grant from
16406 + * Synopsys. If you do not agree with this notice, including the disclaimer
16407 + * below, then you are not authorized to use the Software.
16408 + *
16409 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16410 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16411 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16412 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16413 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16414 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16415 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16416 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16417 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16418 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16419 + * DAMAGE.
16420 + * ========================================================================== */
16421 +
16422 +#if !defined(__DWC_CFI_COMMON_H__)
16423 +#define __DWC_CFI_COMMON_H__
16424 +
16425 +//#include <linux/types.h>
16426 +
16427 +/**
16428 + * @file
16429 + *
16430 + * This file contains the CFI specific common constants, interfaces
16431 + * (functions and macros) and structures for Linux. No PCD specific
16432 + * data structure or definition is to be included in this file.
16433 + *
16434 + */
16435 +
16436 +/** This is a request for all Core Features */
16437 +#define VEN_CORE_GET_FEATURES          0xB1
16438 +
16439 +/** This is a request to get the value of a specific Core Feature */
16440 +#define VEN_CORE_GET_FEATURE           0xB2
16441 +
16442 +/** This command allows the host to set the value of a specific Core Feature */
16443 +#define VEN_CORE_SET_FEATURE           0xB3
16444 +
16445 +/** This command allows the host to set the default values of
16446 + * either all or any specific Core Feature
16447 + */
16448 +#define VEN_CORE_RESET_FEATURES                0xB4
16449 +
16450 +/** This command forces the PCD to write the deferred values of a Core Features */
16451 +#define VEN_CORE_ACTIVATE_FEATURES     0xB5
16452 +
16453 +/** This request reads a DWORD value from a register at the specified offset */
16454 +#define VEN_CORE_READ_REGISTER         0xB6
16455 +
16456 +/** This request writes a DWORD value into a register at the specified offset */
16457 +#define VEN_CORE_WRITE_REGISTER                0xB7
16458 +
16459 +/** This structure is the header of the Core Features dataset returned to
16460 + *  the Host
16461 + */
16462 +struct cfi_all_features_header {
16463 +/** The features header structure length is */
16464 +#define CFI_ALL_FEATURES_HDR_LEN               8
16465 +       /**
16466 +        * The total length of the features dataset returned to the Host
16467 +        */
16468 +       uint16_t wTotalLen;
16469 +
16470 +       /**
16471 +        * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
16472 +        * This field identifies the version of the CFI Specification with which
16473 +        * the device is compliant.
16474 +        */
16475 +       uint16_t wVersion;
16476 +
16477 +       /** The ID of the Core */
16478 +       uint16_t wCoreID;
16479 +#define CFI_CORE_ID_UDC                1
16480 +#define CFI_CORE_ID_OTG                2
16481 +#define CFI_CORE_ID_WUDEV      3
16482 +
16483 +       /** Number of features returned by VEN_CORE_GET_FEATURES request */
16484 +       uint16_t wNumFeatures;
16485 +} UPACKED;
16486 +
16487 +typedef struct cfi_all_features_header cfi_all_features_header_t;
16488 +
16489 +/** This structure is a header of the Core Feature descriptor dataset returned to
16490 + *  the Host after the VEN_CORE_GET_FEATURES request
16491 + */
16492 +struct cfi_feature_desc_header {
16493 +#define CFI_FEATURE_DESC_HDR_LEN       8
16494 +
16495 +       /** The feature ID */
16496 +       uint16_t wFeatureID;
16497 +
16498 +       /** Length of this feature descriptor in bytes - including the
16499 +        * length of the feature name string
16500 +        */
16501 +       uint16_t wLength;
16502 +
16503 +       /** The data length of this feature in bytes */
16504 +       uint16_t wDataLength;
16505 +
16506 +       /**
16507 +        * Attributes of this features
16508 +        * D0: Access rights
16509 +        * 0 - Read/Write
16510 +        * 1 - Read only
16511 +        */
16512 +       uint8_t bmAttributes;
16513 +#define CFI_FEATURE_ATTR_RO            1
16514 +#define CFI_FEATURE_ATTR_RW            0
16515 +
16516 +       /** Length of the feature name in bytes */
16517 +       uint8_t bNameLen;
16518 +
16519 +       /** The feature name buffer */
16520 +       //uint8_t *name;
16521 +} UPACKED;
16522 +
16523 +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
16524 +
16525 +/**
16526 + * This structure describes a NULL terminated string referenced by its id field.
16527 + * It is very similar to usb_string structure but has the id field type set to 16-bit.
16528 + */
16529 +struct cfi_string {
16530 +       uint16_t id;
16531 +       const uint8_t *s;
16532 +};
16533 +typedef struct cfi_string cfi_string_t;
16534 +
16535 +#endif
16536 --- /dev/null
16537 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16538 @@ -0,0 +1,854 @@
16539 +/* ==========================================================================
16540 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
16541 + * $Revision: #12 $
16542 + * $Date: 2011/10/26 $
16543 + * $Change: 1873028 $
16544 + *
16545 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16546 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16547 + * otherwise expressly agreed to in writing between Synopsys and you.
16548 + *
16549 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16550 + * any End User Software License Agreement or Agreement for Licensed Product
16551 + * with Synopsys or any supplement thereto. You are permitted to use and
16552 + * redistribute this Software in source and binary forms, with or without
16553 + * modification, provided that redistributions of source code must retain this
16554 + * notice. You may not view, use, disclose, copy or distribute this file or
16555 + * any information contained herein except pursuant to this license grant from
16556 + * Synopsys. If you do not agree with this notice, including the disclaimer
16557 + * below, then you are not authorized to use the Software.
16558 + *
16559 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16560 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16561 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16562 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16563 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16564 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16565 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16566 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16567 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16568 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16569 + * DAMAGE.
16570 + * ========================================================================== */
16571 +
16572 +#include "dwc_os.h"
16573 +#include "dwc_otg_regs.h"
16574 +#include "dwc_otg_cil.h"
16575 +#include "dwc_otg_adp.h"
16576 +
16577 +/** @file
16578 + *
16579 + * This file contains the most of the Attach Detect Protocol implementation for
16580 + * the driver to support OTG Rev2.0.
16581 + *
16582 + */
16583 +
16584 +void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
16585 +{
16586 +       adpctl_data_t adpctl;
16587 +
16588 +       adpctl.d32 = value;
16589 +       adpctl.b.ar = 0x2;
16590 +
16591 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16592 +
16593 +       while (adpctl.b.ar) {
16594 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16595 +       }
16596 +
16597 +}
16598 +
16599 +/**
16600 + * Function is called to read ADP registers
16601 + */
16602 +uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
16603 +{
16604 +       adpctl_data_t adpctl;
16605 +
16606 +       adpctl.d32 = 0;
16607 +       adpctl.b.ar = 0x1;
16608 +
16609 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16610 +
16611 +       while (adpctl.b.ar) {
16612 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16613 +       }
16614 +
16615 +       return adpctl.d32;
16616 +}
16617 +
16618 +/**
16619 + * Function is called to read ADPCTL register and filter Write-clear bits
16620 + */
16621 +uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
16622 +{
16623 +       adpctl_data_t adpctl;
16624 +
16625 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16626 +       adpctl.b.adp_tmout_int = 0;
16627 +       adpctl.b.adp_prb_int = 0;
16628 +       adpctl.b.adp_tmout_int = 0;
16629 +
16630 +       return adpctl.d32;
16631 +}
16632 +
16633 +/**
16634 + * Function is called to write ADP registers
16635 + */
16636 +void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
16637 +                           uint32_t set)
16638 +{
16639 +       dwc_otg_adp_write_reg(core_if,
16640 +                             (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
16641 +}
16642 +
16643 +static void adp_sense_timeout(void *ptr)
16644 +{
16645 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16646 +       core_if->adp.sense_timer_started = 0;
16647 +       DWC_PRINTF("ADP SENSE TIMEOUT\n");
16648 +       if (core_if->adp_enable) {
16649 +               dwc_otg_adp_sense_stop(core_if);
16650 +               dwc_otg_adp_probe_start(core_if);
16651 +       }
16652 +}
16653 +
16654 +/**
16655 + * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
16656 + */
16657 +static void adp_vbuson_timeout(void *ptr)
16658 +{
16659 +       gpwrdn_data_t gpwrdn;
16660 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16661 +       hprt0_data_t hprt0 = {.d32 = 0 };
16662 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
16663 +       DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
16664 +       if (core_if) {
16665 +               core_if->adp.vbuson_timer_started = 0;
16666 +               /* Turn off vbus */
16667 +               hprt0.b.prtpwr = 1;
16668 +               DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
16669 +               gpwrdn.d32 = 0;
16670 +
16671 +               /* Power off the core */
16672 +               if (core_if->power_down == 2) {
16673 +                       /* Enable Wakeup Logic */
16674 +//                      gpwrdn.b.wkupactiv = 1;
16675 +                       gpwrdn.b.pmuactv = 0;
16676 +                       gpwrdn.b.pwrdnrstn = 1;
16677 +                       gpwrdn.b.pwrdnclmp = 1;
16678 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16679 +                                        gpwrdn.d32);
16680 +
16681 +                       /* Suspend the Phy Clock */
16682 +                       pcgcctl.b.stoppclk = 1;
16683 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
16684 +
16685 +                       /* Switch on VDD */
16686 +//                      gpwrdn.b.wkupactiv = 1;
16687 +                       gpwrdn.b.pmuactv = 1;
16688 +                       gpwrdn.b.pwrdnrstn = 1;
16689 +                       gpwrdn.b.pwrdnclmp = 1;
16690 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16691 +                                        gpwrdn.d32);
16692 +               } else {
16693 +                       /* Enable Power Down Logic */
16694 +                       gpwrdn.b.pmuintsel = 1;
16695 +                       gpwrdn.b.pmuactv = 1;
16696 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16697 +               }
16698 +
16699 +               /* Power off the core */
16700 +               if (core_if->power_down == 2) {
16701 +                       gpwrdn.d32 = 0;
16702 +                       gpwrdn.b.pwrdnswtch = 1;
16703 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
16704 +                                        gpwrdn.d32, 0);
16705 +               }
16706 +
16707 +               /* Unmask SRP detected interrupt from Power Down Logic */
16708 +               gpwrdn.d32 = 0;
16709 +               gpwrdn.b.srp_det_msk = 1;
16710 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16711 +
16712 +               dwc_otg_adp_probe_start(core_if);
16713 +               dwc_otg_dump_global_registers(core_if);
16714 +               dwc_otg_dump_host_registers(core_if);
16715 +       }
16716 +
16717 +}
16718 +
16719 +/**
16720 + * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
16721 + * not asserted within 1.1 seconds.
16722 + *
16723 + * @param core_if the pointer to core_if strucure.
16724 + */
16725 +void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
16726 +{
16727 +       core_if->adp.vbuson_timer_started = 1;
16728 +       if (core_if->adp.vbuson_timer)
16729 +       {
16730 +               DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
16731 +               /* 1.1 secs + 60ms necessary for cil_hcd_start*/
16732 +               DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
16733 +       } else {
16734 +               DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
16735 +       }
16736 +}
16737 +
16738 +#if 0
16739 +/**
16740 + * Masks all DWC OTG core interrupts
16741 + *
16742 + */
16743 +static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
16744 +{
16745 +       int i;
16746 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
16747 +
16748 +       /* Mask Host Interrupts */
16749 +
16750 +       /* Clear and disable HCINTs */
16751 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
16752 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
16753 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
16754 +
16755 +       }
16756 +
16757 +       /* Clear and disable HAINT */
16758 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
16759 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
16760 +
16761 +       /* Mask Device Interrupts */
16762 +       if (!core_if->multiproc_int_enable) {
16763 +               /* Clear and disable IN Endpoint interrupts */
16764 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
16765 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16766 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16767 +                                       diepint, 0xFFFFFFFF);
16768 +               }
16769 +
16770 +               /* Clear and disable OUT Endpoint interrupts */
16771 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
16772 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16773 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16774 +                                       doepint, 0xFFFFFFFF);
16775 +               }
16776 +
16777 +               /* Clear and disable DAINT */
16778 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
16779 +                               0xFFFFFFFF);
16780 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
16781 +       } else {
16782 +               for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
16783 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16784 +                                       diepeachintmsk[i], 0);
16785 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16786 +                                       diepint, 0xFFFFFFFF);
16787 +               }
16788 +
16789 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
16790 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16791 +                                       doepeachintmsk[i], 0);
16792 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16793 +                                       doepint, 0xFFFFFFFF);
16794 +               }
16795 +
16796 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
16797 +                               0);
16798 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
16799 +                               0xFFFFFFFF);
16800 +
16801 +       }
16802 +
16803 +       /* Disable interrupts */
16804 +       ahbcfg.b.glblintrmsk = 1;
16805 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
16806 +
16807 +       /* Disable all interrupts. */
16808 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
16809 +
16810 +       /* Clear any pending interrupts */
16811 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16812 +
16813 +       /* Clear any pending OTG Interrupts */
16814 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
16815 +}
16816 +
16817 +/**
16818 + * Unmask Port Connection Detected interrupt
16819 + *
16820 + */
16821 +static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
16822 +{
16823 +       gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
16824 +
16825 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
16826 +}
16827 +#endif
16828 +
16829 +/**
16830 + * Starts the ADP Probing
16831 + *
16832 + * @param core_if the pointer to core_if structure.
16833 + */
16834 +uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
16835 +{
16836 +
16837 +       adpctl_data_t adpctl = {.d32 = 0};
16838 +       gpwrdn_data_t gpwrdn;
16839 +#if 0
16840 +       adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
16841 +                                                               .b.adp_sns_int = 1, b.adp_tmout_int};
16842 +#endif
16843 +       dwc_otg_disable_global_interrupts(core_if);
16844 +       DWC_PRINTF("ADP Probe Start\n");
16845 +       core_if->adp.probe_enabled = 1;
16846 +
16847 +       adpctl.b.adpres = 1;
16848 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16849 +
16850 +       while (adpctl.b.adpres) {
16851 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16852 +       }
16853 +
16854 +       adpctl.d32 = 0;
16855 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16856 +
16857 +       /* In Host mode unmask SRP detected interrupt */
16858 +       gpwrdn.d32 = 0;
16859 +       gpwrdn.b.sts_chngint_msk = 1;
16860 +       if (!gpwrdn.b.idsts) {
16861 +               gpwrdn.b.srp_det_msk = 1;
16862 +       }
16863 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16864 +
16865 +       adpctl.b.adp_tmout_int_msk = 1;
16866 +       adpctl.b.adp_prb_int_msk = 1;
16867 +       adpctl.b.prb_dschg = 1;
16868 +       adpctl.b.prb_delta = 1;
16869 +       adpctl.b.prb_per = 1;
16870 +       adpctl.b.adpen = 1;
16871 +       adpctl.b.enaprb = 1;
16872 +
16873 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16874 +       DWC_PRINTF("ADP Probe Finish\n");
16875 +       return 0;
16876 +}
16877 +
16878 +/**
16879 + * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
16880 + * within 3 seconds.
16881 + *
16882 + * @param core_if the pointer to core_if strucure.
16883 + */
16884 +void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
16885 +{
16886 +       core_if->adp.sense_timer_started = 1;
16887 +       DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
16888 +}
16889 +
16890 +/**
16891 + * Starts the ADP Sense
16892 + *
16893 + * @param core_if the pointer to core_if strucure.
16894 + */
16895 +uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
16896 +{
16897 +       adpctl_data_t adpctl;
16898 +
16899 +       DWC_PRINTF("ADP Sense Start\n");
16900 +
16901 +       /* Unmask ADP sense interrupt and mask all other from the core */
16902 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16903 +       adpctl.b.adp_sns_int_msk = 1;
16904 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16905 +       dwc_otg_disable_global_interrupts(core_if); // vahrama
16906 +
16907 +       /* Set ADP reset bit*/
16908 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16909 +       adpctl.b.adpres = 1;
16910 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16911 +
16912 +       while (adpctl.b.adpres) {
16913 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16914 +       }
16915 +
16916 +       adpctl.b.adpres = 0;
16917 +       adpctl.b.adpen = 1;
16918 +       adpctl.b.enasns = 1;
16919 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16920 +
16921 +       dwc_otg_adp_sense_timer_start(core_if);
16922 +
16923 +       return 0;
16924 +}
16925 +
16926 +/**
16927 + * Stops the ADP Probing
16928 + *
16929 + * @param core_if the pointer to core_if strucure.
16930 + */
16931 +uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
16932 +{
16933 +
16934 +       adpctl_data_t adpctl;
16935 +       DWC_PRINTF("Stop ADP probe\n");
16936 +       core_if->adp.probe_enabled = 0;
16937 +       core_if->adp.probe_counter = 0;
16938 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16939 +
16940 +       adpctl.b.adpen = 0;
16941 +       adpctl.b.adp_prb_int = 1;
16942 +       adpctl.b.adp_tmout_int = 1;
16943 +       adpctl.b.adp_sns_int = 1;
16944 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16945 +
16946 +       return 0;
16947 +}
16948 +
16949 +/**
16950 + * Stops the ADP Sensing
16951 + *
16952 + * @param core_if the pointer to core_if strucure.
16953 + */
16954 +uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
16955 +{
16956 +       adpctl_data_t adpctl;
16957 +
16958 +       core_if->adp.sense_enabled = 0;
16959 +
16960 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16961 +       adpctl.b.enasns = 0;
16962 +       adpctl.b.adp_sns_int = 1;
16963 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16964 +
16965 +       return 0;
16966 +}
16967 +
16968 +/**
16969 + * Called to turn on the VBUS after initial ADP probe in host mode.
16970 + * If port power was already enabled in cil_hcd_start function then
16971 + * only schedule a timer.
16972 + *
16973 + * @param core_if the pointer to core_if structure.
16974 + */
16975 +void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
16976 +{
16977 +       hprt0_data_t hprt0 = {.d32 = 0 };
16978 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
16979 +       DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
16980 +
16981 +       if (hprt0.b.prtpwr == 0) {
16982 +               hprt0.b.prtpwr = 1;
16983 +               //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
16984 +       }
16985 +
16986 +       dwc_otg_adp_vbuson_timer_start(core_if);
16987 +}
16988 +
16989 +/**
16990 + * Called right after driver is loaded
16991 + * to perform initial actions for ADP
16992 + *
16993 + * @param core_if the pointer to core_if structure.
16994 + * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
16995 + */
16996 +void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
16997 +{
16998 +       gpwrdn_data_t gpwrdn;
16999 +
17000 +       DWC_PRINTF("ADP Initial Start\n");
17001 +       core_if->adp.adp_started = 1;
17002 +
17003 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17004 +       dwc_otg_disable_global_interrupts(core_if);
17005 +       if (is_host) {
17006 +               DWC_PRINTF("HOST MODE\n");
17007 +               /* Enable Power Down Logic Interrupt*/
17008 +               gpwrdn.d32 = 0;
17009 +               gpwrdn.b.pmuintsel = 1;
17010 +               gpwrdn.b.pmuactv = 1;
17011 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17012 +               /* Initialize first ADP probe to obtain Ramp Time value */
17013 +               core_if->adp.initial_probe = 1;
17014 +               dwc_otg_adp_probe_start(core_if);
17015 +       } else {
17016 +               gotgctl_data_t gotgctl;
17017 +               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17018 +               DWC_PRINTF("DEVICE MODE\n");
17019 +               if (gotgctl.b.bsesvld == 0) {
17020 +                       /* Enable Power Down Logic Interrupt*/
17021 +                       gpwrdn.d32 = 0;
17022 +                       DWC_PRINTF("VBUS is not valid - start ADP probe\n");
17023 +                       gpwrdn.b.pmuintsel = 1;
17024 +                       gpwrdn.b.pmuactv = 1;
17025 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17026 +                       core_if->adp.initial_probe = 1;
17027 +                       dwc_otg_adp_probe_start(core_if);
17028 +               } else {
17029 +                       DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
17030 +                       core_if->op_state = B_PERIPHERAL;
17031 +                       dwc_otg_core_init(core_if);
17032 +                       dwc_otg_enable_global_interrupts(core_if);
17033 +                       cil_pcd_start(core_if);
17034 +                       dwc_otg_dump_global_registers(core_if);
17035 +                       dwc_otg_dump_dev_registers(core_if);
17036 +               }
17037 +       }
17038 +}
17039 +
17040 +void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
17041 +{
17042 +       core_if->adp.adp_started = 0;
17043 +       core_if->adp.initial_probe = 0;
17044 +       core_if->adp.probe_timer_values[0] = -1;
17045 +       core_if->adp.probe_timer_values[1] = -1;
17046 +       core_if->adp.probe_enabled = 0;
17047 +       core_if->adp.sense_enabled = 0;
17048 +       core_if->adp.sense_timer_started = 0;
17049 +       core_if->adp.vbuson_timer_started = 0;
17050 +       core_if->adp.probe_counter = 0;
17051 +       core_if->adp.gpwrdn = 0;
17052 +       core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
17053 +       /* Initialize timers */
17054 +       core_if->adp.sense_timer =
17055 +           DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
17056 +       core_if->adp.vbuson_timer =
17057 +           DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
17058 +       if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
17059 +       {
17060 +               DWC_ERROR("Could not allocate memory for ADP timers\n");
17061 +       }
17062 +}
17063 +
17064 +void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
17065 +{
17066 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
17067 +       gpwrdn.b.pmuintsel = 1;
17068 +       gpwrdn.b.pmuactv = 1;
17069 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17070 +
17071 +       if (core_if->adp.probe_enabled)
17072 +               dwc_otg_adp_probe_stop(core_if);
17073 +       if (core_if->adp.sense_enabled)
17074 +               dwc_otg_adp_sense_stop(core_if);
17075 +       if (core_if->adp.sense_timer_started)
17076 +               DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17077 +       if (core_if->adp.vbuson_timer_started)
17078 +               DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
17079 +       DWC_TIMER_FREE(core_if->adp.sense_timer);
17080 +       DWC_TIMER_FREE(core_if->adp.vbuson_timer);
17081 +}
17082 +
17083 +/////////////////////////////////////////////////////////////////////
17084 +////////////// ADP Interrupt Handlers ///////////////////////////////
17085 +/////////////////////////////////////////////////////////////////////
17086 +/**
17087 + * This function sets Ramp Timer values
17088 + */
17089 +static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
17090 +{
17091 +       if (core_if->adp.probe_timer_values[0] == -1) {
17092 +               core_if->adp.probe_timer_values[0] = val;
17093 +               core_if->adp.probe_timer_values[1] = -1;
17094 +               return 1;
17095 +       } else {
17096 +               core_if->adp.probe_timer_values[1] =
17097 +                   core_if->adp.probe_timer_values[0];
17098 +               core_if->adp.probe_timer_values[0] = val;
17099 +               return 0;
17100 +       }
17101 +}
17102 +
17103 +/**
17104 + * This function compares Ramp Timer values
17105 + */
17106 +static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
17107 +{
17108 +       uint32_t diff;
17109 +       if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
17110 +                       diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
17111 +       else
17112 +                       diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];
17113 +       if(diff < 2) {
17114 +               return 0;
17115 +       } else {
17116 +               return 1;
17117 +       }
17118 +}
17119 +
17120 +/**
17121 + * This function handles ADP Probe Interrupts
17122 + */
17123 +static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
17124 +                                                uint32_t val)
17125 +{
17126 +       adpctl_data_t adpctl = {.d32 = 0 };
17127 +       gpwrdn_data_t gpwrdn, temp;
17128 +       adpctl.d32 = val;
17129 +
17130 +       temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17131 +       core_if->adp.probe_counter++;
17132 +       core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17133 +       if (adpctl.b.rtim == 0 && !temp.b.idsts){
17134 +               DWC_PRINTF("RTIM value is 0\n");
17135 +               goto exit;
17136 +       }
17137 +       if (set_timer_value(core_if, adpctl.b.rtim) &&
17138 +           core_if->adp.initial_probe) {
17139 +               core_if->adp.initial_probe = 0;
17140 +               dwc_otg_adp_probe_stop(core_if);
17141 +               gpwrdn.d32 = 0;
17142 +               gpwrdn.b.pmuactv = 1;
17143 +               gpwrdn.b.pmuintsel = 1;
17144 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17145 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17146 +
17147 +               /* check which value is for device mode and which for Host mode */
17148 +               if (!temp.b.idsts) {    /* considered host mode value is 0 */
17149 +                       /*
17150 +                        * Turn on VBUS after initial ADP probe.
17151 +                        */
17152 +                       core_if->op_state = A_HOST;
17153 +                       dwc_otg_enable_global_interrupts(core_if);
17154 +                       DWC_SPINUNLOCK(core_if->lock);
17155 +                       cil_hcd_start(core_if);
17156 +                       dwc_otg_adp_turnon_vbus(core_if);
17157 +                       DWC_SPINLOCK(core_if->lock);
17158 +               } else {
17159 +                       /*
17160 +                        * Initiate SRP after initial ADP probe.
17161 +                        */
17162 +                       dwc_otg_enable_global_interrupts(core_if);
17163 +                       dwc_otg_initiate_srp(core_if);
17164 +               }
17165 +       } else if (core_if->adp.probe_counter > 2){
17166 +               gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17167 +               if (compare_timer_values(core_if)) {
17168 +                       DWC_PRINTF("Difference in timer values !!! \n");
17169 +//                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
17170 +                       dwc_otg_adp_probe_stop(core_if);
17171 +
17172 +                       /* Power on the core */
17173 +                       if (core_if->power_down == 2) {
17174 +                               gpwrdn.b.pwrdnswtch = 1;
17175 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17176 +                                                gpwrdn, 0, gpwrdn.d32);
17177 +                       }
17178 +
17179 +                       /* check which value is for device mode and which for Host mode */
17180 +                       if (!temp.b.idsts) {    /* considered host mode value is 0 */
17181 +                               /* Disable Interrupt from Power Down Logic */
17182 +                               gpwrdn.d32 = 0;
17183 +                               gpwrdn.b.pmuintsel = 1;
17184 +                               gpwrdn.b.pmuactv = 1;
17185 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17186 +                                                gpwrdn, gpwrdn.d32, 0);
17187 +
17188 +                               /*
17189 +                                * Initialize the Core for Host mode.
17190 +                                */
17191 +                               core_if->op_state = A_HOST;
17192 +                               dwc_otg_core_init(core_if);
17193 +                               dwc_otg_enable_global_interrupts(core_if);
17194 +                               cil_hcd_start(core_if);
17195 +                       } else {
17196 +                               gotgctl_data_t gotgctl;
17197 +                               /* Mask SRP detected interrupt from Power Down Logic */
17198 +                               gpwrdn.d32 = 0;
17199 +                               gpwrdn.b.srp_det_msk = 1;
17200 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17201 +                                                gpwrdn, gpwrdn.d32, 0);
17202 +
17203 +                               /* Disable Power Down Logic */
17204 +                               gpwrdn.d32 = 0;
17205 +                               gpwrdn.b.pmuintsel = 1;
17206 +                               gpwrdn.b.pmuactv = 1;
17207 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17208 +                                                gpwrdn, gpwrdn.d32, 0);
17209 +
17210 +                               /*
17211 +                                * Initialize the Core for Device mode.
17212 +                                */
17213 +                               core_if->op_state = B_PERIPHERAL;
17214 +                               dwc_otg_core_init(core_if);
17215 +                               dwc_otg_enable_global_interrupts(core_if);
17216 +                               cil_pcd_start(core_if);
17217 +
17218 +                               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17219 +                               if (!gotgctl.b.bsesvld) {
17220 +                                       dwc_otg_initiate_srp(core_if);
17221 +                               }
17222 +                       }
17223 +               }
17224 +               if (core_if->power_down == 2) {
17225 +                       if (gpwrdn.b.bsessvld) {
17226 +                               /* Mask SRP detected interrupt from Power Down Logic */
17227 +                               gpwrdn.d32 = 0;
17228 +                               gpwrdn.b.srp_det_msk = 1;
17229 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17230 +
17231 +                               /* Disable Power Down Logic */
17232 +                               gpwrdn.d32 = 0;
17233 +                               gpwrdn.b.pmuactv = 1;
17234 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17235 +
17236 +                               /*
17237 +                                * Initialize the Core for Device mode.
17238 +                                */
17239 +                               core_if->op_state = B_PERIPHERAL;
17240 +                               dwc_otg_core_init(core_if);
17241 +                               dwc_otg_enable_global_interrupts(core_if);
17242 +                               cil_pcd_start(core_if);
17243 +                       }
17244 +               }
17245 +       }
17246 +exit:
17247 +       /* Clear interrupt */
17248 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17249 +       adpctl.b.adp_prb_int = 1;
17250 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17251 +
17252 +       return 0;
17253 +}
17254 +
17255 +/**
17256 + * This function hadles ADP Sense Interrupt
17257 + */
17258 +static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
17259 +{
17260 +       adpctl_data_t adpctl;
17261 +       /* Stop ADP Sense timer */
17262 +       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17263 +
17264 +       /* Restart ADP Sense timer */
17265 +       dwc_otg_adp_sense_timer_start(core_if);
17266 +
17267 +       /* Clear interrupt */
17268 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17269 +       adpctl.b.adp_sns_int = 1;
17270 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17271 +
17272 +       return 0;
17273 +}
17274 +
17275 +/**
17276 + * This function handles ADP Probe Interrupts
17277 + */
17278 +static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
17279 +                                                uint32_t val)
17280 +{
17281 +       adpctl_data_t adpctl = {.d32 = 0 };
17282 +       adpctl.d32 = val;
17283 +       set_timer_value(core_if, adpctl.b.rtim);
17284 +
17285 +       /* Clear interrupt */
17286 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17287 +       adpctl.b.adp_tmout_int = 1;
17288 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17289 +
17290 +       return 0;
17291 +}
17292 +
17293 +/**
17294 + * ADP Interrupt handler.
17295 + *
17296 + */
17297 +int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
17298 +{
17299 +       int retval = 0;
17300 +       adpctl_data_t adpctl = {.d32 = 0};
17301 +
17302 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17303 +       DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
17304 +
17305 +       if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
17306 +               DWC_PRINTF("ADP Sense interrupt\n");
17307 +               retval |= dwc_otg_adp_handle_sns_intr(core_if);
17308 +       }
17309 +       if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
17310 +               DWC_PRINTF("ADP timeout interrupt\n");
17311 +               retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
17312 +       }
17313 +       if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
17314 +               DWC_PRINTF("ADP Probe interrupt\n");
17315 +               adpctl.b.adp_prb_int = 1;
17316 +               retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
17317 +       }
17318 +
17319 +//     dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
17320 +       //dwc_otg_adp_write_reg(core_if, adpctl.d32);
17321 +       DWC_PRINTF("RETURN FROM ADP ISR\n");
17322 +
17323 +       return retval;
17324 +}
17325 +
17326 +/**
17327 + *
17328 + * @param core_if Programming view of DWC_otg controller.
17329 + */
17330 +int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
17331 +{
17332 +
17333 +#ifndef DWC_HOST_ONLY
17334 +       hprt0_data_t hprt0;
17335 +       gpwrdn_data_t gpwrdn;
17336 +       DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
17337 +
17338 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17339 +       /* check which value is for device mode and which for Host mode */
17340 +       if (!gpwrdn.b.idsts) {  /* considered host mode value is 0 */
17341 +               DWC_PRINTF("SRP: Host mode\n");
17342 +
17343 +               if (core_if->adp_enable) {
17344 +                       dwc_otg_adp_probe_stop(core_if);
17345 +
17346 +                       /* Power on the core */
17347 +                       if (core_if->power_down == 2) {
17348 +                               gpwrdn.b.pwrdnswtch = 1;
17349 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17350 +                                                gpwrdn, 0, gpwrdn.d32);
17351 +                       }
17352 +
17353 +                       core_if->op_state = A_HOST;
17354 +                       dwc_otg_core_init(core_if);
17355 +                       dwc_otg_enable_global_interrupts(core_if);
17356 +                       cil_hcd_start(core_if);
17357 +               }
17358 +
17359 +               /* Turn on the port power bit. */
17360 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
17361 +               hprt0.b.prtpwr = 1;
17362 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17363 +
17364 +               /* Start the Connection timer. So a message can be displayed
17365 +                * if connect does not occur within 10 seconds. */
17366 +               cil_hcd_session_start(core_if);
17367 +       } else {
17368 +               DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
17369 +               if (core_if->adp_enable) {
17370 +                       dwc_otg_adp_probe_stop(core_if);
17371 +
17372 +                       /* Power on the core */
17373 +                       if (core_if->power_down == 2) {
17374 +                               gpwrdn.b.pwrdnswtch = 1;
17375 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17376 +                                                gpwrdn, 0, gpwrdn.d32);
17377 +                       }
17378 +
17379 +                       gpwrdn.d32 = 0;
17380 +                       gpwrdn.b.pmuactv = 0;
17381 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
17382 +                                        gpwrdn.d32);
17383 +
17384 +                       core_if->op_state = B_PERIPHERAL;
17385 +                       dwc_otg_core_init(core_if);
17386 +                       dwc_otg_enable_global_interrupts(core_if);
17387 +                       cil_pcd_start(core_if);
17388 +               }
17389 +       }
17390 +#endif
17391 +       return 1;
17392 +}
17393 --- /dev/null
17394 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17395 @@ -0,0 +1,80 @@
17396 +/* ==========================================================================
17397 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
17398 + * $Revision: #7 $
17399 + * $Date: 2011/10/24 $
17400 + * $Change: 1871159 $
17401 + *
17402 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17403 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17404 + * otherwise expressly agreed to in writing between Synopsys and you.
17405 + *
17406 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17407 + * any End User Software License Agreement or Agreement for Licensed Product
17408 + * with Synopsys or any supplement thereto. You are permitted to use and
17409 + * redistribute this Software in source and binary forms, with or without
17410 + * modification, provided that redistributions of source code must retain this
17411 + * notice. You may not view, use, disclose, copy or distribute this file or
17412 + * any information contained herein except pursuant to this license grant from
17413 + * Synopsys. If you do not agree with this notice, including the disclaimer
17414 + * below, then you are not authorized to use the Software.
17415 + *
17416 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17417 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17418 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17419 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17420 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17421 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17422 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17423 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17424 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17425 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17426 + * DAMAGE.
17427 + * ========================================================================== */
17428 +
17429 +#ifndef __DWC_OTG_ADP_H__
17430 +#define __DWC_OTG_ADP_H__
17431 +
17432 +/**
17433 + * @file
17434 + *
17435 + * This file contains the Attach Detect Protocol interfaces and defines
17436 + * (functions) and structures for Linux.
17437 + *
17438 + */
17439 +
17440 +#define DWC_OTG_ADP_UNATTACHED 0
17441 +#define DWC_OTG_ADP_ATTACHED   1
17442 +#define DWC_OTG_ADP_UNKOWN     2
17443 +
17444 +typedef struct dwc_otg_adp {
17445 +       uint32_t adp_started;
17446 +       uint32_t initial_probe;
17447 +       int32_t probe_timer_values[2];
17448 +       uint32_t probe_enabled;
17449 +       uint32_t sense_enabled;
17450 +       dwc_timer_t *sense_timer;
17451 +       uint32_t sense_timer_started;
17452 +       dwc_timer_t *vbuson_timer;
17453 +       uint32_t vbuson_timer_started;
17454 +       uint32_t attached;
17455 +       uint32_t probe_counter;
17456 +       uint32_t gpwrdn;
17457 +} dwc_otg_adp_t;
17458 +
17459 +/**
17460 + * Attach Detect Protocol functions
17461 + */
17462 +
17463 +extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);
17464 +extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);
17465 +extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);
17466 +extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
17467 +extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
17468 +extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
17469 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
17470 +extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
17471 +extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
17472 +extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
17473 +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
17474 +
17475 +#endif //__DWC_OTG_ADP_H__
17476 --- /dev/null
17477 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17478 @@ -0,0 +1,1210 @@
17479 +/* ==========================================================================
17480 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
17481 + * $Revision: #44 $
17482 + * $Date: 2010/11/29 $
17483 + * $Change: 1636033 $
17484 + *
17485 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17486 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17487 + * otherwise expressly agreed to in writing between Synopsys and you.
17488 + *
17489 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17490 + * any End User Software License Agreement or Agreement for Licensed Product
17491 + * with Synopsys or any supplement thereto. You are permitted to use and
17492 + * redistribute this Software in source and binary forms, with or without
17493 + * modification, provided that redistributions of source code must retain this
17494 + * notice. You may not view, use, disclose, copy or distribute this file or
17495 + * any information contained herein except pursuant to this license grant from
17496 + * Synopsys. If you do not agree with this notice, including the disclaimer
17497 + * below, then you are not authorized to use the Software.
17498 + *
17499 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17500 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17501 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17502 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17503 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17504 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17505 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17506 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17507 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17508 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17509 + * DAMAGE.
17510 + * ========================================================================== */
17511 +
17512 +/** @file
17513 + *
17514 + * The diagnostic interface will provide access to the controller for
17515 + * bringing up the hardware and testing.  The Linux driver attributes
17516 + * feature will be used to provide the Linux Diagnostic
17517 + * Interface. These attributes are accessed through sysfs.
17518 + */
17519 +
17520 +/** @page "Linux Module Attributes"
17521 + *
17522 + * The Linux module attributes feature is used to provide the Linux
17523 + * Diagnostic Interface.  These attributes are accessed through sysfs.
17524 + * The diagnostic interface will provide access to the controller for
17525 + * bringing up the hardware and testing.
17526 +
17527 + The following table shows the attributes.
17528 + <table>
17529 + <tr>
17530 + <td><b> Name</b></td>
17531 + <td><b> Description</b></td>
17532 + <td><b> Access</b></td>
17533 + </tr>
17534 +
17535 + <tr>
17536 + <td> mode </td>
17537 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
17538 + <td> Read</td>
17539 + </tr>
17540 +
17541 + <tr>
17542 + <td> hnpcapable </td>
17543 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
17544 + Read returns the current value.</td>
17545 + <td> Read/Write</td>
17546 + </tr>
17547 +
17548 + <tr>
17549 + <td> srpcapable </td>
17550 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
17551 + Read returns the current value.</td>
17552 + <td> Read/Write</td>
17553 + </tr>
17554 +
17555 + <tr>
17556 + <td> hsic_connect </td>
17557 + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
17558 + Read returns the current value.</td>
17559 + <td> Read/Write</td>
17560 + </tr>
17561 +
17562 + <tr>
17563 + <td> inv_sel_hsic </td>
17564 + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
17565 + Read returns the current value.</td>
17566 + <td> Read/Write</td>
17567 + </tr>
17568 +
17569 + <tr>
17570 + <td> hnp </td>
17571 + <td> Initiates the Host Negotiation Protocol.  Read returns the status.</td>
17572 + <td> Read/Write</td>
17573 + </tr>
17574 +
17575 + <tr>
17576 + <td> srp </td>
17577 + <td> Initiates the Session Request Protocol.  Read returns the status.</td>
17578 + <td> Read/Write</td>
17579 + </tr>
17580 +
17581 + <tr>
17582 + <td> buspower </td>
17583 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
17584 + <td> Read/Write</td>
17585 + </tr>
17586 +
17587 + <tr>
17588 + <td> bussuspend </td>
17589 + <td> Suspends the USB bus.</td>
17590 + <td> Read/Write</td>
17591 + </tr>
17592 +
17593 + <tr>
17594 + <td> busconnected </td>
17595 + <td> Gets the connection status of the bus</td>
17596 + <td> Read</td>
17597 + </tr>
17598 +
17599 + <tr>
17600 + <td> gotgctl </td>
17601 + <td> Gets or sets the Core Control Status Register.</td>
17602 + <td> Read/Write</td>
17603 + </tr>
17604 +
17605 + <tr>
17606 + <td> gusbcfg </td>
17607 + <td> Gets or sets the Core USB Configuration Register</td>
17608 + <td> Read/Write</td>
17609 + </tr>
17610 +
17611 + <tr>
17612 + <td> grxfsiz </td>
17613 + <td> Gets or sets the Receive FIFO Size Register</td>
17614 + <td> Read/Write</td>
17615 + </tr>
17616 +
17617 + <tr>
17618 + <td> gnptxfsiz </td>
17619 + <td> Gets or sets the non-periodic Transmit Size Register</td>
17620 + <td> Read/Write</td>
17621 + </tr>
17622 +
17623 + <tr>
17624 + <td> gpvndctl </td>
17625 + <td> Gets or sets the PHY Vendor Control Register</td>
17626 + <td> Read/Write</td>
17627 + </tr>
17628 +
17629 + <tr>
17630 + <td> ggpio </td>
17631 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
17632 + or sets the upper 16 bits.</td>
17633 + <td> Read/Write</td>
17634 + </tr>
17635 +
17636 + <tr>
17637 + <td> guid </td>
17638 + <td> Gets or sets the value of the User ID Register</td>
17639 + <td> Read/Write</td>
17640 + </tr>
17641 +
17642 + <tr>
17643 + <td> gsnpsid </td>
17644 + <td> Gets the value of the Synopsys ID Regester</td>
17645 + <td> Read</td>
17646 + </tr>
17647 +
17648 + <tr>
17649 + <td> devspeed </td>
17650 + <td> Gets or sets the device speed setting in the DCFG register</td>
17651 + <td> Read/Write</td>
17652 + </tr>
17653 +
17654 + <tr>
17655 + <td> enumspeed </td>
17656 + <td> Gets the device enumeration Speed.</td>
17657 + <td> Read</td>
17658 + </tr>
17659 +
17660 + <tr>
17661 + <td> hptxfsiz </td>
17662 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
17663 + <td> Read</td>
17664 + </tr>
17665 +
17666 + <tr>
17667 + <td> hprt0 </td>
17668 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
17669 + <td> Read/Write</td>
17670 + </tr>
17671 +
17672 + <tr>
17673 + <td> regoffset </td>
17674 + <td> Sets the register offset for the next Register Access</td>
17675 + <td> Read/Write</td>
17676 + </tr>
17677 +
17678 + <tr>
17679 + <td> regvalue </td>
17680 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
17681 + <td> Read/Write</td>
17682 + </tr>
17683 +
17684 + <tr>
17685 + <td> remote_wakeup </td>
17686 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
17687 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
17688 + Wakeup signalling bit in the Device Control Register is set for 1
17689 + milli-second.</td>
17690 + <td> Read/Write</td>
17691 + </tr>
17692 +
17693 + <tr>
17694 + <td> rem_wakeup_pwrdn </td>
17695 + <td> On read, shows the status core - hibernated or not. On write, initiates
17696 + a remote wakeup of the device from Hibernation. </td>
17697 + <td> Read/Write</td>
17698 + </tr>
17699 +
17700 + <tr>
17701 + <td> mode_ch_tim_en </td>
17702 + <td> This bit is used to enable or disable the host core to wait for 200 PHY
17703 + clock cycles at the end of Resume to change the opmode signal to the PHY to 00
17704 + after Suspend or LPM. </td>
17705 + <td> Read/Write</td>
17706 + </tr>
17707 +
17708 + <tr>
17709 + <td> fr_interval </td>
17710 + <td> On read, shows the value of HFIR Frame Interval. On write, dynamically
17711 + reload HFIR register during runtime. The application can write a value to this
17712 + register only after the Port Enable bit of the Host Port Control and Status
17713 + register (HPRT.PrtEnaPort) has been set </td>
17714 + <td> Read/Write</td>
17715 + </tr>
17716 +
17717 + <tr>
17718 + <td> disconnect_us </td>
17719 + <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
17720 + which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>
17721 + <td> Read/Write</td>
17722 + </tr>
17723 +
17724 + <tr>
17725 + <td> regdump </td>
17726 + <td> Dumps the contents of core registers.</td>
17727 + <td> Read</td>
17728 + </tr>
17729 +
17730 + <tr>
17731 + <td> spramdump </td>
17732 + <td> Dumps the contents of core registers.</td>
17733 + <td> Read</td>
17734 + </tr>
17735 +
17736 + <tr>
17737 + <td> hcddump </td>
17738 + <td> Dumps the current HCD state.</td>
17739 + <td> Read</td>
17740 + </tr>
17741 +
17742 + <tr>
17743 + <td> hcd_frrem </td>
17744 + <td> Shows the average value of the Frame Remaining
17745 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
17746 + occurs. This can be used to determine the average interrupt latency. Also
17747 + shows the average Frame Remaining value for start_transfer and the "a" and
17748 + "b" sample points. The "a" and "b" sample points may be used during debugging
17749 + bto determine how long it takes to execute a section of the HCD code.</td>
17750 + <td> Read</td>
17751 + </tr>
17752 +
17753 + <tr>
17754 + <td> rd_reg_test </td>
17755 + <td> Displays the time required to read the GNPTXFSIZ register many times
17756 + (the output shows the number of times the register is read).
17757 + <td> Read</td>
17758 + </tr>
17759 +
17760 + <tr>
17761 + <td> wr_reg_test </td>
17762 + <td> Displays the time required to write the GNPTXFSIZ register many times
17763 + (the output shows the number of times the register is written).
17764 + <td> Read</td>
17765 + </tr>
17766 +
17767 + <tr>
17768 + <td> lpm_response </td>
17769 + <td> Gets or sets lpm_response mode. Applicable only in device mode.
17770 + <td> Write</td>
17771 + </tr>
17772 +
17773 + <tr>
17774 + <td> sleep_status </td>
17775 + <td> Shows sleep status of device.
17776 + <td> Read</td>
17777 + </tr>
17778 +
17779 + </table>
17780 +
17781 + Example usage:
17782 + To get the current mode:
17783 + cat /sys/devices/lm0/mode
17784 +
17785 + To power down the USB:
17786 + echo 0 > /sys/devices/lm0/buspower
17787 + */
17788 +
17789 +#include "dwc_otg_os_dep.h"
17790 +#include "dwc_os.h"
17791 +#include "dwc_otg_driver.h"
17792 +#include "dwc_otg_attr.h"
17793 +#include "dwc_otg_core_if.h"
17794 +#include "dwc_otg_pcd_if.h"
17795 +#include "dwc_otg_hcd_if.h"
17796 +
17797 +/*
17798 + * MACROs for defining sysfs attribute
17799 + */
17800 +#ifdef LM_INTERFACE
17801 +
17802 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17803 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17804 +{ \
17805 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17806 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);             \
17807 +       uint32_t val; \
17808 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17809 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17810 +}
17811 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17812 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17813 +                                       const char *buf, size_t count) \
17814 +{ \
17815 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17816 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17817 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17818 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17819 +       return count; \
17820 +}
17821 +
17822 +#elif defined(PCI_INTERFACE)
17823 +
17824 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17825 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17826 +{ \
17827 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);      \
17828 +       uint32_t val; \
17829 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17830 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17831 +}
17832 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17833 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17834 +                                       const char *buf, size_t count) \
17835 +{ \
17836 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17837 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17838 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17839 +       return count; \
17840 +}
17841 +
17842 +#elif defined(PLATFORM_INTERFACE)
17843 +
17844 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17845 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17846 +{ \
17847 +        struct platform_device *platform_dev = \
17848 +                container_of(_dev, struct platform_device, dev); \
17849 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);  \
17850 +       uint32_t val; \
17851 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17852 +                    __func__, _dev, platform_dev, otg_dev); \
17853 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17854 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17855 +}
17856 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17857 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17858 +                                       const char *buf, size_t count) \
17859 +{ \
17860 +        struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17861 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17862 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17863 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17864 +       return count; \
17865 +}
17866 +#endif
17867 +
17868 +/*
17869 + * MACROs for defining sysfs attribute for 32-bit registers
17870 + */
17871 +#ifdef LM_INTERFACE
17872 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17873 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17874 +{ \
17875 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17876 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17877 +       uint32_t val; \
17878 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17879 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17880 +}
17881 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17882 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17883 +                                       const char *buf, size_t count) \
17884 +{ \
17885 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17886 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17887 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
17888 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17889 +       return count; \
17890 +}
17891 +#elif defined(PCI_INTERFACE)
17892 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17893 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17894 +{ \
17895 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17896 +       uint32_t val; \
17897 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17898 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17899 +}
17900 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17901 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17902 +                                       const char *buf, size_t count) \
17903 +{ \
17904 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17905 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
17906 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17907 +       return count; \
17908 +}
17909 +
17910 +#elif defined(PLATFORM_INTERFACE)
17911 +#include "dwc_otg_dbg.h"
17912 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17913 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17914 +{ \
17915 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17916 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17917 +       uint32_t val; \
17918 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17919 +                    __func__, _dev, platform_dev, otg_dev); \
17920 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17921 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17922 +}
17923 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17924 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17925 +                                       const char *buf, size_t count) \
17926 +{ \
17927 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17928 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17929 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
17930 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17931 +       return count; \
17932 +}
17933 +
17934 +#endif
17935 +
17936 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
17937 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17938 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17939 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
17940 +
17941 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
17942 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17943 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
17944 +
17945 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
17946 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17947 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17948 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
17949 +
17950 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
17951 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17952 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
17953 +
17954 +/** @name Functions for Show/Store of Attributes */
17955 +/**@{*/
17956 +
17957 +/**
17958 + * Helper function returning the otg_device structure of the given device
17959 + */
17960 +static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
17961 +{
17962 +        dwc_otg_device_t *otg_dev;
17963 +        DWC_OTG_GETDRVDEV(otg_dev, _dev);
17964 +        return otg_dev;
17965 +}
17966 +
17967 +/**
17968 + * Show the register offset of the Register Access.
17969 + */
17970 +static ssize_t regoffset_show(struct device *_dev,
17971 +                             struct device_attribute *attr, char *buf)
17972 +{
17973 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17974 +       return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
17975 +                       otg_dev->os_dep.reg_offset);
17976 +}
17977 +
17978 +/**
17979 + * Set the register offset for the next Register Access        Read/Write
17980 + */
17981 +static ssize_t regoffset_store(struct device *_dev,
17982 +                              struct device_attribute *attr,
17983 +                              const char *buf, size_t count)
17984 +{
17985 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
17986 +       uint32_t offset = simple_strtoul(buf, NULL, 16);
17987 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
17988 +       if (offset < SZ_256K) {
17989 +#elif  defined(PCI_INTERFACE)
17990 +       if (offset < 0x00040000) {
17991 +#endif
17992 +               otg_dev->os_dep.reg_offset = offset;
17993 +       } else {
17994 +               dev_err(_dev, "invalid offset\n");
17995 +       }
17996 +
17997 +       return count;
17998 +}
17999 +
18000 +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
18001 +
18002 +/**
18003 + * Show the value of the register at the offset in the reg_offset
18004 + * attribute.
18005 + */
18006 +static ssize_t regvalue_show(struct device *_dev,
18007 +                            struct device_attribute *attr, char *buf)
18008 +{
18009 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18010 +       uint32_t val;
18011 +       volatile uint32_t *addr;
18012 +
18013 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18014 +               /* Calculate the address */
18015 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18016 +                                    (uint8_t *) otg_dev->os_dep.base);
18017 +               val = DWC_READ_REG32(addr);
18018 +               return snprintf(buf,
18019 +                               sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
18020 +                               "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,
18021 +                               val);
18022 +       } else {
18023 +               dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);
18024 +               return sprintf(buf, "invalid offset\n");
18025 +       }
18026 +}
18027 +
18028 +/**
18029 + * Store the value in the register at the offset in the reg_offset
18030 + * attribute.
18031 + *
18032 + */
18033 +static ssize_t regvalue_store(struct device *_dev,
18034 +                             struct device_attribute *attr,
18035 +                             const char *buf, size_t count)
18036 +{
18037 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18038 +       volatile uint32_t *addr;
18039 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18040 +       //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
18041 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18042 +               /* Calculate the address */
18043 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18044 +                                    (uint8_t *) otg_dev->os_dep.base);
18045 +               DWC_WRITE_REG32(addr, val);
18046 +       } else {
18047 +               dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
18048 +                       otg_dev->os_dep.reg_offset);
18049 +       }
18050 +       return count;
18051 +}
18052 +
18053 +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
18054 +
18055 +/*
18056 + * Attributes
18057 + */
18058 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
18059 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
18060 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");
18061 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
18062 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
18063 +
18064 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18065 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18066 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
18067 +
18068 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
18069 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
18070 +                            &(otg_dev->core_if->core_global_regs->gusbcfg),
18071 +                            "GUSBCFG");
18072 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
18073 +                            &(otg_dev->core_if->core_global_regs->grxfsiz),
18074 +                            "GRXFSIZ");
18075 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
18076 +                            &(otg_dev->core_if->core_global_regs->gnptxfsiz),
18077 +                            "GNPTXFSIZ");
18078 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
18079 +                            &(otg_dev->core_if->core_global_regs->gpvndctl),
18080 +                            "GPVNDCTL");
18081 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
18082 +                            &(otg_dev->core_if->core_global_regs->ggpio),
18083 +                            "GGPIO");
18084 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
18085 +                            "GUID");
18086 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
18087 +                            &(otg_dev->core_if->core_global_regs->gsnpsid),
18088 +                            "GSNPSID");
18089 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
18090 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
18091 +
18092 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
18093 +                            &(otg_dev->core_if->core_global_regs->hptxfsiz),
18094 +                            "HPTXFSIZ");
18095 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
18096 +
18097 +/**
18098 + * @todo Add code to initiate the HNP.
18099 + */
18100 +/**
18101 + * Show the HNP status bit
18102 + */
18103 +static ssize_t hnp_show(struct device *_dev,
18104 +                       struct device_attribute *attr, char *buf)
18105 +{
18106 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18107 +       return sprintf(buf, "HstNegScs = 0x%x\n",
18108 +                      dwc_otg_get_hnpstatus(otg_dev->core_if));
18109 +}
18110 +
18111 +/**
18112 + * Set the HNP Request bit
18113 + */
18114 +static ssize_t hnp_store(struct device *_dev,
18115 +                        struct device_attribute *attr,
18116 +                        const char *buf, size_t count)
18117 +{
18118 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18119 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18120 +       dwc_otg_set_hnpreq(otg_dev->core_if, in);
18121 +       return count;
18122 +}
18123 +
18124 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
18125 +
18126 +/**
18127 + * @todo Add code to initiate the SRP.
18128 + */
18129 +/**
18130 + * Show the SRP status bit
18131 + */
18132 +static ssize_t srp_show(struct device *_dev,
18133 +                       struct device_attribute *attr, char *buf)
18134 +{
18135 +#ifndef DWC_HOST_ONLY
18136 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18137 +       return sprintf(buf, "SesReqScs = 0x%x\n",
18138 +                      dwc_otg_get_srpstatus(otg_dev->core_if));
18139 +#else
18140 +       return sprintf(buf, "Host Only Mode!\n");
18141 +#endif
18142 +}
18143 +
18144 +/**
18145 + * Set the SRP Request bit
18146 + */
18147 +static ssize_t srp_store(struct device *_dev,
18148 +                        struct device_attribute *attr,
18149 +                        const char *buf, size_t count)
18150 +{
18151 +#ifndef DWC_HOST_ONLY
18152 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18153 +       dwc_otg_pcd_initiate_srp(otg_dev->pcd);
18154 +#endif
18155 +       return count;
18156 +}
18157 +
18158 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
18159 +
18160 +/**
18161 + * @todo Need to do more for power on/off?
18162 + */
18163 +/**
18164 + * Show the Bus Power status
18165 + */
18166 +static ssize_t buspower_show(struct device *_dev,
18167 +                            struct device_attribute *attr, char *buf)
18168 +{
18169 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18170 +       return sprintf(buf, "Bus Power = 0x%x\n",
18171 +                      dwc_otg_get_prtpower(otg_dev->core_if));
18172 +}
18173 +
18174 +/**
18175 + * Set the Bus Power status
18176 + */
18177 +static ssize_t buspower_store(struct device *_dev,
18178 +                             struct device_attribute *attr,
18179 +                             const char *buf, size_t count)
18180 +{
18181 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18182 +       uint32_t on = simple_strtoul(buf, NULL, 16);
18183 +       dwc_otg_set_prtpower(otg_dev->core_if, on);
18184 +       return count;
18185 +}
18186 +
18187 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
18188 +
18189 +/**
18190 + * @todo Need to do more for suspend?
18191 + */
18192 +/**
18193 + * Show the Bus Suspend status
18194 + */
18195 +static ssize_t bussuspend_show(struct device *_dev,
18196 +                              struct device_attribute *attr, char *buf)
18197 +{
18198 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18199 +       return sprintf(buf, "Bus Suspend = 0x%x\n",
18200 +                      dwc_otg_get_prtsuspend(otg_dev->core_if));
18201 +}
18202 +
18203 +/**
18204 + * Set the Bus Suspend status
18205 + */
18206 +static ssize_t bussuspend_store(struct device *_dev,
18207 +                               struct device_attribute *attr,
18208 +                               const char *buf, size_t count)
18209 +{
18210 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18211 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18212 +       dwc_otg_set_prtsuspend(otg_dev->core_if, in);
18213 +       return count;
18214 +}
18215 +
18216 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
18217 +
18218 +/**
18219 + * Show the Mode Change Ready Timer status
18220 + */
18221 +static ssize_t mode_ch_tim_en_show(struct device *_dev,
18222 +                                  struct device_attribute *attr, char *buf)
18223 +{
18224 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18225 +       return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
18226 +                      dwc_otg_get_mode_ch_tim(otg_dev->core_if));
18227 +}
18228 +
18229 +/**
18230 + * Set the Mode Change Ready Timer status
18231 + */
18232 +static ssize_t mode_ch_tim_en_store(struct device *_dev,
18233 +                                   struct device_attribute *attr,
18234 +                                   const char *buf, size_t count)
18235 +{
18236 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18237 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18238 +       dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);
18239 +       return count;
18240 +}
18241 +
18242 +DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);
18243 +
18244 +/**
18245 + * Show the value of HFIR Frame Interval bitfield
18246 + */
18247 +static ssize_t fr_interval_show(struct device *_dev,
18248 +                               struct device_attribute *attr, char *buf)
18249 +{
18250 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18251 +       return sprintf(buf, "Frame Interval = 0x%x\n",
18252 +                      dwc_otg_get_fr_interval(otg_dev->core_if));
18253 +}
18254 +
18255 +/**
18256 + * Set the HFIR Frame Interval value
18257 + */
18258 +static ssize_t fr_interval_store(struct device *_dev,
18259 +                                struct device_attribute *attr,
18260 +                                const char *buf, size_t count)
18261 +{
18262 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18263 +       uint32_t in = simple_strtoul(buf, NULL, 10);
18264 +       dwc_otg_set_fr_interval(otg_dev->core_if, in);
18265 +       return count;
18266 +}
18267 +
18268 +DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);
18269 +
18270 +/**
18271 + * Show the status of Remote Wakeup.
18272 + */
18273 +static ssize_t remote_wakeup_show(struct device *_dev,
18274 +                                 struct device_attribute *attr, char *buf)
18275 +{
18276 +#ifndef DWC_HOST_ONLY
18277 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18278 +
18279 +       return sprintf(buf,
18280 +                      "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
18281 +                      dwc_otg_get_remotewakesig(otg_dev->core_if),
18282 +                      dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
18283 +                      dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
18284 +#else
18285 +       return sprintf(buf, "Host Only Mode!\n");
18286 +#endif /* DWC_HOST_ONLY */
18287 +}
18288 +
18289 +/**
18290 + * Initiate a remote wakeup of the host.  The Device control register
18291 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
18292 + * flag is set.
18293 + *
18294 + */
18295 +static ssize_t remote_wakeup_store(struct device *_dev,
18296 +                                  struct device_attribute *attr,
18297 +                                  const char *buf, size_t count)
18298 +{
18299 +#ifndef DWC_HOST_ONLY
18300 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18301 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18302 +
18303 +       if (val & 1) {
18304 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
18305 +       } else {
18306 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
18307 +       }
18308 +#endif /* DWC_HOST_ONLY */
18309 +       return count;
18310 +}
18311 +
18312 +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
18313 +           remote_wakeup_store);
18314 +
18315 +/**
18316 + * Show the whether core is hibernated or not.
18317 + */
18318 +static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
18319 +                                    struct device_attribute *attr, char *buf)
18320 +{
18321 +#ifndef DWC_HOST_ONLY
18322 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18323 +
18324 +       if (dwc_otg_get_core_state(otg_dev->core_if)) {
18325 +               DWC_PRINTF("Core is in hibernation\n");
18326 +       } else {
18327 +               DWC_PRINTF("Core is not in hibernation\n");
18328 +       }
18329 +#endif /* DWC_HOST_ONLY */
18330 +       return 0;
18331 +}
18332 +
18333 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
18334 +                                             int rem_wakeup, int reset);
18335 +
18336 +/**
18337 + * Initiate a remote wakeup of the device to exit from hibernation.
18338 + */
18339 +static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,
18340 +                                     struct device_attribute *attr,
18341 +                                     const char *buf, size_t count)
18342 +{
18343 +#ifndef DWC_HOST_ONLY
18344 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18345 +       dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
18346 +#endif
18347 +       return count;
18348 +}
18349 +
18350 +DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,
18351 +           rem_wakeup_pwrdn_store);
18352 +
18353 +static ssize_t disconnect_us(struct device *_dev,
18354 +                            struct device_attribute *attr,
18355 +                            const char *buf, size_t count)
18356 +{
18357 +
18358 +#ifndef DWC_HOST_ONLY
18359 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18360 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18361 +       DWC_PRINTF("The Passed value is %04x\n", val);
18362 +
18363 +       dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);
18364 +
18365 +#endif /* DWC_HOST_ONLY */
18366 +       return count;
18367 +}
18368 +
18369 +DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);
18370 +
18371 +/**
18372 + * Dump global registers and either host or device registers (depending on the
18373 + * current mode of the core).
18374 + */
18375 +static ssize_t regdump_show(struct device *_dev,
18376 +                           struct device_attribute *attr, char *buf)
18377 +{
18378 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18379 +
18380 +       dwc_otg_dump_global_registers(otg_dev->core_if);
18381 +       if (dwc_otg_is_host_mode(otg_dev->core_if)) {
18382 +               dwc_otg_dump_host_registers(otg_dev->core_if);
18383 +       } else {
18384 +               dwc_otg_dump_dev_registers(otg_dev->core_if);
18385 +
18386 +       }
18387 +       return sprintf(buf, "Register Dump\n");
18388 +}
18389 +
18390 +DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
18391 +
18392 +/**
18393 + * Dump global registers and either host or device registers (depending on the
18394 + * current mode of the core).
18395 + */
18396 +static ssize_t spramdump_show(struct device *_dev,
18397 +                             struct device_attribute *attr, char *buf)
18398 +{
18399 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18400 +
18401 +       dwc_otg_dump_spram(otg_dev->core_if);
18402 +
18403 +       return sprintf(buf, "SPRAM Dump\n");
18404 +}
18405 +
18406 +DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
18407 +
18408 +/**
18409 + * Dump the current hcd state.
18410 + */
18411 +static ssize_t hcddump_show(struct device *_dev,
18412 +                           struct device_attribute *attr, char *buf)
18413 +{
18414 +#ifndef DWC_DEVICE_ONLY
18415 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18416 +       dwc_otg_hcd_dump_state(otg_dev->hcd);
18417 +#endif /* DWC_DEVICE_ONLY */
18418 +       return sprintf(buf, "HCD Dump\n");
18419 +}
18420 +
18421 +DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
18422 +
18423 +/**
18424 + * Dump the average frame remaining at SOF. This can be used to
18425 + * determine average interrupt latency. Frame remaining is also shown for
18426 + * start transfer and two additional sample points.
18427 + */
18428 +static ssize_t hcd_frrem_show(struct device *_dev,
18429 +                             struct device_attribute *attr, char *buf)
18430 +{
18431 +#ifndef DWC_DEVICE_ONLY
18432 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18433 +
18434 +       dwc_otg_hcd_dump_frrem(otg_dev->hcd);
18435 +#endif /* DWC_DEVICE_ONLY */
18436 +       return sprintf(buf, "HCD Dump Frame Remaining\n");
18437 +}
18438 +
18439 +DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
18440 +
18441 +/**
18442 + * Displays the time required to read the GNPTXFSIZ register many times (the
18443 + * output shows the number of times the register is read).
18444 + */
18445 +#define RW_REG_COUNT 10000000
18446 +#define MSEC_PER_JIFFIE 1000/HZ
18447 +static ssize_t rd_reg_test_show(struct device *_dev,
18448 +                               struct device_attribute *attr, char *buf)
18449 +{
18450 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18451 +       int i;
18452 +       int time;
18453 +       int start_jiffies;
18454 +
18455 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18456 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18457 +       start_jiffies = jiffies;
18458 +       for (i = 0; i < RW_REG_COUNT; i++) {
18459 +               dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18460 +       }
18461 +       time = jiffies - start_jiffies;
18462 +       return sprintf(buf,
18463 +                      "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18464 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18465 +}
18466 +
18467 +DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
18468 +
18469 +/**
18470 + * Displays the time required to write the GNPTXFSIZ register many times (the
18471 + * output shows the number of times the register is written).
18472 + */
18473 +static ssize_t wr_reg_test_show(struct device *_dev,
18474 +                               struct device_attribute *attr, char *buf)
18475 +{
18476 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18477 +       uint32_t reg_val;
18478 +       int i;
18479 +       int time;
18480 +       int start_jiffies;
18481 +
18482 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18483 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18484 +       reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18485 +       start_jiffies = jiffies;
18486 +       for (i = 0; i < RW_REG_COUNT; i++) {
18487 +               dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
18488 +       }
18489 +       time = jiffies - start_jiffies;
18490 +       return sprintf(buf,
18491 +                      "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18492 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18493 +}
18494 +
18495 +DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
18496 +
18497 +#ifdef CONFIG_USB_DWC_OTG_LPM
18498 +
18499 +/**
18500 +* Show the lpm_response attribute.
18501 +*/
18502 +static ssize_t lpmresp_show(struct device *_dev,
18503 +                           struct device_attribute *attr, char *buf)
18504 +{
18505 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18506 +
18507 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
18508 +               return sprintf(buf, "** LPM is DISABLED **\n");
18509 +
18510 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18511 +               return sprintf(buf, "** Current mode is not device mode\n");
18512 +       }
18513 +       return sprintf(buf, "lpm_response = %d\n",
18514 +                      dwc_otg_get_lpmresponse(otg_dev->core_if));
18515 +}
18516 +
18517 +/**
18518 +* Store the lpm_response attribute.
18519 +*/
18520 +static ssize_t lpmresp_store(struct device *_dev,
18521 +                            struct device_attribute *attr,
18522 +                            const char *buf, size_t count)
18523 +{
18524 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18525 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18526 +
18527 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
18528 +               return 0;
18529 +       }
18530 +
18531 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18532 +               return 0;
18533 +       }
18534 +
18535 +       dwc_otg_set_lpmresponse(otg_dev->core_if, val);
18536 +       return count;
18537 +}
18538 +
18539 +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
18540 +
18541 +/**
18542 +* Show the sleep_status attribute.
18543 +*/
18544 +static ssize_t sleepstatus_show(struct device *_dev,
18545 +                               struct device_attribute *attr, char *buf)
18546 +{
18547 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18548 +       return sprintf(buf, "Sleep Status = %d\n",
18549 +                      dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
18550 +}
18551 +
18552 +/**
18553 + * Store the sleep_status attribure.
18554 + */
18555 +static ssize_t sleepstatus_store(struct device *_dev,
18556 +                                struct device_attribute *attr,
18557 +                                const char *buf, size_t count)
18558 +{
18559 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18560 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
18561 +
18562 +       if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
18563 +               if (dwc_otg_is_host_mode(core_if)) {
18564 +
18565 +                       DWC_PRINTF("Host initiated resume\n");
18566 +                       dwc_otg_set_prtresume(otg_dev->core_if, 1);
18567 +               }
18568 +       }
18569 +
18570 +       return count;
18571 +}
18572 +
18573 +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
18574 +           sleepstatus_store);
18575 +
18576 +#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
18577 +
18578 +/**@}*/
18579 +
18580 +/**
18581 + * Create the device files
18582 + */
18583 +void dwc_otg_attr_create(
18584 +#ifdef LM_INTERFACE
18585 +       struct lm_device *dev
18586 +#elif  defined(PCI_INTERFACE)
18587 +       struct pci_dev *dev
18588 +#elif  defined(PLATFORM_INTERFACE)
18589 +        struct platform_device *dev
18590 +#endif
18591 +    )
18592 +{
18593 +       int error;
18594 +
18595 +       error = device_create_file(&dev->dev, &dev_attr_regoffset);
18596 +       error = device_create_file(&dev->dev, &dev_attr_regvalue);
18597 +       error = device_create_file(&dev->dev, &dev_attr_mode);
18598 +       error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
18599 +       error = device_create_file(&dev->dev, &dev_attr_srpcapable);
18600 +       error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
18601 +       error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
18602 +       error = device_create_file(&dev->dev, &dev_attr_hnp);
18603 +       error = device_create_file(&dev->dev, &dev_attr_srp);
18604 +       error = device_create_file(&dev->dev, &dev_attr_buspower);
18605 +       error = device_create_file(&dev->dev, &dev_attr_bussuspend);
18606 +       error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18607 +       error = device_create_file(&dev->dev, &dev_attr_fr_interval);
18608 +       error = device_create_file(&dev->dev, &dev_attr_busconnected);
18609 +       error = device_create_file(&dev->dev, &dev_attr_gotgctl);
18610 +       error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
18611 +       error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
18612 +       error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
18613 +       error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
18614 +       error = device_create_file(&dev->dev, &dev_attr_ggpio);
18615 +       error = device_create_file(&dev->dev, &dev_attr_guid);
18616 +       error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
18617 +       error = device_create_file(&dev->dev, &dev_attr_devspeed);
18618 +       error = device_create_file(&dev->dev, &dev_attr_enumspeed);
18619 +       error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
18620 +       error = device_create_file(&dev->dev, &dev_attr_hprt0);
18621 +       error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
18622 +       error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18623 +       error = device_create_file(&dev->dev, &dev_attr_disconnect_us);
18624 +       error = device_create_file(&dev->dev, &dev_attr_regdump);
18625 +       error = device_create_file(&dev->dev, &dev_attr_spramdump);
18626 +       error = device_create_file(&dev->dev, &dev_attr_hcddump);
18627 +       error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
18628 +       error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
18629 +       error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
18630 +#ifdef CONFIG_USB_DWC_OTG_LPM
18631 +       error = device_create_file(&dev->dev, &dev_attr_lpm_response);
18632 +       error = device_create_file(&dev->dev, &dev_attr_sleep_status);
18633 +#endif
18634 +}
18635 +
18636 +/**
18637 + * Remove the device files
18638 + */
18639 +void dwc_otg_attr_remove(
18640 +#ifdef LM_INTERFACE
18641 +       struct lm_device *dev
18642 +#elif  defined(PCI_INTERFACE)
18643 +       struct pci_dev *dev
18644 +#elif  defined(PLATFORM_INTERFACE)
18645 +       struct platform_device *dev
18646 +#endif
18647 +    )
18648 +{
18649 +       device_remove_file(&dev->dev, &dev_attr_regoffset);
18650 +       device_remove_file(&dev->dev, &dev_attr_regvalue);
18651 +       device_remove_file(&dev->dev, &dev_attr_mode);
18652 +       device_remove_file(&dev->dev, &dev_attr_hnpcapable);
18653 +       device_remove_file(&dev->dev, &dev_attr_srpcapable);
18654 +       device_remove_file(&dev->dev, &dev_attr_hsic_connect);
18655 +       device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
18656 +       device_remove_file(&dev->dev, &dev_attr_hnp);
18657 +       device_remove_file(&dev->dev, &dev_attr_srp);
18658 +       device_remove_file(&dev->dev, &dev_attr_buspower);
18659 +       device_remove_file(&dev->dev, &dev_attr_bussuspend);
18660 +       device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18661 +       device_remove_file(&dev->dev, &dev_attr_fr_interval);
18662 +       device_remove_file(&dev->dev, &dev_attr_busconnected);
18663 +       device_remove_file(&dev->dev, &dev_attr_gotgctl);
18664 +       device_remove_file(&dev->dev, &dev_attr_gusbcfg);
18665 +       device_remove_file(&dev->dev, &dev_attr_grxfsiz);
18666 +       device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
18667 +       device_remove_file(&dev->dev, &dev_attr_gpvndctl);
18668 +       device_remove_file(&dev->dev, &dev_attr_ggpio);
18669 +       device_remove_file(&dev->dev, &dev_attr_guid);
18670 +       device_remove_file(&dev->dev, &dev_attr_gsnpsid);
18671 +       device_remove_file(&dev->dev, &dev_attr_devspeed);
18672 +       device_remove_file(&dev->dev, &dev_attr_enumspeed);
18673 +       device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
18674 +       device_remove_file(&dev->dev, &dev_attr_hprt0);
18675 +       device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
18676 +       device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18677 +       device_remove_file(&dev->dev, &dev_attr_disconnect_us);
18678 +       device_remove_file(&dev->dev, &dev_attr_regdump);
18679 +       device_remove_file(&dev->dev, &dev_attr_spramdump);
18680 +       device_remove_file(&dev->dev, &dev_attr_hcddump);
18681 +       device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
18682 +       device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
18683 +       device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
18684 +#ifdef CONFIG_USB_DWC_OTG_LPM
18685 +       device_remove_file(&dev->dev, &dev_attr_lpm_response);
18686 +       device_remove_file(&dev->dev, &dev_attr_sleep_status);
18687 +#endif
18688 +}
18689 --- /dev/null
18690 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18691 @@ -0,0 +1,89 @@
18692 +/* ==========================================================================
18693 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
18694 + * $Revision: #13 $
18695 + * $Date: 2010/06/21 $
18696 + * $Change: 1532021 $
18697 + *
18698 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18699 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18700 + * otherwise expressly agreed to in writing between Synopsys and you.
18701 + *
18702 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18703 + * any End User Software License Agreement or Agreement for Licensed Product
18704 + * with Synopsys or any supplement thereto. You are permitted to use and
18705 + * redistribute this Software in source and binary forms, with or without
18706 + * modification, provided that redistributions of source code must retain this
18707 + * notice. You may not view, use, disclose, copy or distribute this file or
18708 + * any information contained herein except pursuant to this license grant from
18709 + * Synopsys. If you do not agree with this notice, including the disclaimer
18710 + * below, then you are not authorized to use the Software.
18711 + *
18712 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18713 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18714 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18715 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18716 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18717 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18718 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18719 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18720 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18721 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18722 + * DAMAGE.
18723 + * ========================================================================== */
18724 +
18725 +#if !defined(__DWC_OTG_ATTR_H__)
18726 +#define __DWC_OTG_ATTR_H__
18727 +
18728 +/** @file
18729 + * This file contains the interface to the Linux device attributes.
18730 + */
18731 +extern struct device_attribute dev_attr_regoffset;
18732 +extern struct device_attribute dev_attr_regvalue;
18733 +
18734 +extern struct device_attribute dev_attr_mode;
18735 +extern struct device_attribute dev_attr_hnpcapable;
18736 +extern struct device_attribute dev_attr_srpcapable;
18737 +extern struct device_attribute dev_attr_hnp;
18738 +extern struct device_attribute dev_attr_srp;
18739 +extern struct device_attribute dev_attr_buspower;
18740 +extern struct device_attribute dev_attr_bussuspend;
18741 +extern struct device_attribute dev_attr_mode_ch_tim_en;
18742 +extern struct device_attribute dev_attr_fr_interval;
18743 +extern struct device_attribute dev_attr_busconnected;
18744 +extern struct device_attribute dev_attr_gotgctl;
18745 +extern struct device_attribute dev_attr_gusbcfg;
18746 +extern struct device_attribute dev_attr_grxfsiz;
18747 +extern struct device_attribute dev_attr_gnptxfsiz;
18748 +extern struct device_attribute dev_attr_gpvndctl;
18749 +extern struct device_attribute dev_attr_ggpio;
18750 +extern struct device_attribute dev_attr_guid;
18751 +extern struct device_attribute dev_attr_gsnpsid;
18752 +extern struct device_attribute dev_attr_devspeed;
18753 +extern struct device_attribute dev_attr_enumspeed;
18754 +extern struct device_attribute dev_attr_hptxfsiz;
18755 +extern struct device_attribute dev_attr_hprt0;
18756 +#ifdef CONFIG_USB_DWC_OTG_LPM
18757 +extern struct device_attribute dev_attr_lpm_response;
18758 +extern struct device_attribute devi_attr_sleep_status;
18759 +#endif
18760 +
18761 +void dwc_otg_attr_create(
18762 +#ifdef LM_INTERFACE
18763 +                               struct lm_device *dev
18764 +#elif  defined(PCI_INTERFACE)
18765 +                               struct pci_dev *dev
18766 +#elif  defined(PLATFORM_INTERFACE)
18767 +       struct platform_device *dev
18768 +#endif
18769 +    );
18770 +
18771 +void dwc_otg_attr_remove(
18772 +#ifdef LM_INTERFACE
18773 +                               struct lm_device *dev
18774 +#elif  defined(PCI_INTERFACE)
18775 +                               struct pci_dev *dev
18776 +#elif  defined(PLATFORM_INTERFACE)
18777 +       struct platform_device *dev
18778 +#endif
18779 +    );
18780 +#endif
18781 --- /dev/null
18782 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18783 @@ -0,0 +1,1876 @@
18784 +/* ==========================================================================
18785 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18786 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18787 + * otherwise expressly agreed to in writing between Synopsys and you.
18788 + *
18789 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18790 + * any End User Software License Agreement or Agreement for Licensed Product
18791 + * with Synopsys or any supplement thereto. You are permitted to use and
18792 + * redistribute this Software in source and binary forms, with or without
18793 + * modification, provided that redistributions of source code must retain this
18794 + * notice. You may not view, use, disclose, copy or distribute this file or
18795 + * any information contained herein except pursuant to this license grant from
18796 + * Synopsys. If you do not agree with this notice, including the disclaimer
18797 + * below, then you are not authorized to use the Software.
18798 + *
18799 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18800 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18801 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18802 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18803 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18804 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18805 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18806 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18807 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18808 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18809 + * DAMAGE.
18810 + * ========================================================================== */
18811 +
18812 +/** @file
18813 + *
18814 + * This file contains the most of the CFI(Core Feature Interface)
18815 + * implementation for the OTG.
18816 + */
18817 +
18818 +#ifdef DWC_UTE_CFI
18819 +
18820 +#include "dwc_otg_pcd.h"
18821 +#include "dwc_otg_cfi.h"
18822 +
18823 +/** This definition should actually migrate to the Portability Library */
18824 +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
18825 +
18826 +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
18827 +
18828 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
18829 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
18830 +                                struct dwc_otg_pcd *pcd,
18831 +                                struct cfi_usb_ctrlrequest *ctrl_req);
18832 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
18833 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18834 +                            struct cfi_usb_ctrlrequest *req);
18835 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18836 +                                struct cfi_usb_ctrlrequest *req);
18837 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18838 +                               struct cfi_usb_ctrlrequest *req);
18839 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
18840 +                            struct cfi_usb_ctrlrequest *req);
18841 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
18842 +
18843 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
18844 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
18845 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
18846 +
18847 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
18848 +
18849 +/** This is the header of the all features descriptor */
18850 +static cfi_all_features_header_t all_props_desc_header = {
18851 +       .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
18852 +       .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
18853 +       .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
18854 +};
18855 +
18856 +/** This is an array of statically allocated feature descriptors */
18857 +static cfi_feature_desc_header_t prop_descs[] = {
18858 +
18859 +       /* FT_ID_DMA_MODE */
18860 +       {
18861 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
18862 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18863 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
18864 +        },
18865 +
18866 +       /* FT_ID_DMA_BUFFER_SETUP */
18867 +       {
18868 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
18869 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18870 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18871 +        },
18872 +
18873 +       /* FT_ID_DMA_BUFF_ALIGN */
18874 +       {
18875 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
18876 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18877 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18878 +        },
18879 +
18880 +       /* FT_ID_DMA_CONCAT_SETUP */
18881 +       {
18882 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
18883 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18884 +        //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
18885 +        },
18886 +
18887 +       /* FT_ID_DMA_CIRCULAR */
18888 +       {
18889 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
18890 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18891 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18892 +        },
18893 +
18894 +       /* FT_ID_THRESHOLD_SETUP */
18895 +       {
18896 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
18897 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18898 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18899 +        },
18900 +
18901 +       /* FT_ID_DFIFO_DEPTH */
18902 +       {
18903 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
18904 +        .bmAttributes = CFI_FEATURE_ATTR_RO,
18905 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18906 +        },
18907 +
18908 +       /* FT_ID_TX_FIFO_DEPTH */
18909 +       {
18910 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
18911 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18912 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18913 +        },
18914 +
18915 +       /* FT_ID_RX_FIFO_DEPTH */
18916 +       {
18917 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
18918 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18919 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18920 +        }
18921 +};
18922 +
18923 +/** The table of feature names */
18924 +cfi_string_t prop_name_table[] = {
18925 +       {FT_ID_DMA_MODE, "dma_mode"},
18926 +       {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
18927 +       {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
18928 +       {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
18929 +       {FT_ID_DMA_CIRCULAR, "buffer_circular"},
18930 +       {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
18931 +       {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
18932 +       {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
18933 +       {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
18934 +       {}
18935 +};
18936 +
18937 +/************************************************************************/
18938 +
18939 +/**
18940 + * Returns the name of the feature by its ID
18941 + * or NULL if no featute ID matches.
18942 + *
18943 + */
18944 +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
18945 +{
18946 +       cfi_string_t *pstr;
18947 +       *len = 0;
18948 +
18949 +       for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
18950 +               if (pstr->id == prop_id) {
18951 +                       *len = DWC_STRLEN(pstr->s);
18952 +                       return pstr->s;
18953 +               }
18954 +       }
18955 +       return NULL;
18956 +}
18957 +
18958 +/**
18959 + * This function handles all CFI specific control requests.
18960 + *
18961 + * Return a negative value to stall the DCE.
18962 + */
18963 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
18964 +{
18965 +       int retval = 0;
18966 +       dwc_otg_pcd_ep_t *ep = NULL;
18967 +       cfiobject_t *cfi = pcd->cfi;
18968 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
18969 +       uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
18970 +       uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
18971 +       uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
18972 +       uint32_t regaddr = 0;
18973 +       uint32_t regval = 0;
18974 +
18975 +       /* Save this Control Request in the CFI object.
18976 +        * The data field will be assigned in the data stage completion CB function.
18977 +        */
18978 +       cfi->ctrl_req = *ctrl;
18979 +       cfi->ctrl_req.data = NULL;
18980 +
18981 +       cfi->need_gadget_att = 0;
18982 +       cfi->need_status_in_complete = 0;
18983 +
18984 +       switch (ctrl->bRequest) {
18985 +       case VEN_CORE_GET_FEATURES:
18986 +               retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
18987 +               if (retval >= 0) {
18988 +                       //dump_msg(cfi->buf_in.buf, retval);
18989 +                       ep = &pcd->ep0;
18990 +
18991 +                       retval = min((uint16_t) retval, wLen);
18992 +                       /* Transfer this buffer to the host through the EP0-IN EP */
18993 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
18994 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
18995 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
18996 +                       ep->dwc_ep.xfer_len = retval;
18997 +                       ep->dwc_ep.xfer_count = 0;
18998 +                       ep->dwc_ep.sent_zlp = 0;
18999 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19000 +
19001 +                       pcd->ep0_pending = 1;
19002 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19003 +               }
19004 +               retval = 0;
19005 +               break;
19006 +
19007 +       case VEN_CORE_GET_FEATURE:
19008 +               CFI_INFO("VEN_CORE_GET_FEATURE\n");
19009 +               retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
19010 +                                              pcd, ctrl);
19011 +               if (retval >= 0) {
19012 +                       ep = &pcd->ep0;
19013 +
19014 +                       retval = min((uint16_t) retval, wLen);
19015 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19016 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19017 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19018 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19019 +                       ep->dwc_ep.xfer_len = retval;
19020 +                       ep->dwc_ep.xfer_count = 0;
19021 +                       ep->dwc_ep.sent_zlp = 0;
19022 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19023 +
19024 +                       pcd->ep0_pending = 1;
19025 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19026 +               }
19027 +               CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
19028 +               dump_msg(cfi->buf_in.buf, retval);
19029 +               break;
19030 +
19031 +       case VEN_CORE_SET_FEATURE:
19032 +               CFI_INFO("VEN_CORE_SET_FEATURE\n");
19033 +               /* Set up an XFER to get the data stage of the control request,
19034 +                * which is the new value of the feature to be modified.
19035 +                */
19036 +               ep = &pcd->ep0;
19037 +               ep->dwc_ep.is_in = 0;
19038 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19039 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19040 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19041 +               ep->dwc_ep.xfer_len = wLen;
19042 +               ep->dwc_ep.xfer_count = 0;
19043 +               ep->dwc_ep.sent_zlp = 0;
19044 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19045 +
19046 +               pcd->ep0_pending = 1;
19047 +               /* Read the control write's data stage */
19048 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19049 +               retval = 0;
19050 +               break;
19051 +
19052 +       case VEN_CORE_RESET_FEATURES:
19053 +               CFI_INFO("VEN_CORE_RESET_FEATURES\n");
19054 +               cfi->need_gadget_att = 1;
19055 +               cfi->need_status_in_complete = 1;
19056 +               retval = cfi_preproc_reset(pcd, ctrl);
19057 +               CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
19058 +               break;
19059 +
19060 +       case VEN_CORE_ACTIVATE_FEATURES:
19061 +               CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
19062 +               break;
19063 +
19064 +       case VEN_CORE_READ_REGISTER:
19065 +               CFI_INFO("VEN_CORE_READ_REGISTER\n");
19066 +               /* wValue optionally contains the HI WORD of the register offset and
19067 +                * wIndex contains the LOW WORD of the register offset
19068 +                */
19069 +               if (wValue == 0) {
19070 +                       /* @TODO - MAS - fix the access to the base field */
19071 +                       regaddr = 0;
19072 +                       //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
19073 +                       //GET_CORE_IF(pcd)->co
19074 +                       regaddr |= wIndex;
19075 +               } else {
19076 +                       regaddr = (wValue << 16) | wIndex;
19077 +               }
19078 +
19079 +               /* Read a 32-bit value of the memory at the regaddr */
19080 +               regval = DWC_READ_REG32((uint32_t *) regaddr);
19081 +
19082 +               ep = &pcd->ep0;
19083 +               dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
19084 +               ep->dwc_ep.is_in = 1;
19085 +               ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19086 +               ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19087 +               ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19088 +               ep->dwc_ep.xfer_len = wLen;
19089 +               ep->dwc_ep.xfer_count = 0;
19090 +               ep->dwc_ep.sent_zlp = 0;
19091 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19092 +
19093 +               pcd->ep0_pending = 1;
19094 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19095 +               cfi->need_gadget_att = 0;
19096 +               retval = 0;
19097 +               break;
19098 +
19099 +       case VEN_CORE_WRITE_REGISTER:
19100 +               CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
19101 +               /* Set up an XFER to get the data stage of the control request,
19102 +                * which is the new value of the register to be modified.
19103 +                */
19104 +               ep = &pcd->ep0;
19105 +               ep->dwc_ep.is_in = 0;
19106 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19107 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19108 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19109 +               ep->dwc_ep.xfer_len = wLen;
19110 +               ep->dwc_ep.xfer_count = 0;
19111 +               ep->dwc_ep.sent_zlp = 0;
19112 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19113 +
19114 +               pcd->ep0_pending = 1;
19115 +               /* Read the control write's data stage */
19116 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19117 +               retval = 0;
19118 +               break;
19119 +
19120 +       default:
19121 +               retval = -DWC_E_NOT_SUPPORTED;
19122 +               break;
19123 +       }
19124 +
19125 +       return retval;
19126 +}
19127 +
19128 +/**
19129 + * This function prepares the core features descriptors and copies its
19130 + * raw representation into the buffer <buf>.
19131 + *
19132 + * The buffer structure is as follows:
19133 + *     all_features_header (8 bytes)
19134 + *     features_#1 (8 bytes + feature name string length)
19135 + *     features_#2 (8 bytes + feature name string length)
19136 + *     .....
19137 + *     features_#n - where n=the total count of feature descriptors
19138 + */
19139 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
19140 +{
19141 +       cfi_feature_desc_header_t *prop_hdr = prop_descs;
19142 +       cfi_feature_desc_header_t *prop;
19143 +       cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
19144 +       cfi_all_features_header_t *tmp;
19145 +       uint8_t *tmpbuf = buf;
19146 +       const uint8_t *pname = NULL;
19147 +       int i, j, namelen = 0, totlen;
19148 +
19149 +       /* Prepare and copy the core features into the buffer */
19150 +       CFI_INFO("%s:\n", __func__);
19151 +
19152 +       tmp = (cfi_all_features_header_t *) tmpbuf;
19153 +       *tmp = *all_props_hdr;
19154 +       tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
19155 +
19156 +       j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
19157 +       for (i = 0; i < j; i++, prop_hdr++) {
19158 +               pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
19159 +               prop = (cfi_feature_desc_header_t *) tmpbuf;
19160 +               *prop = *prop_hdr;
19161 +
19162 +               prop->bNameLen = namelen;
19163 +               prop->wLength =
19164 +                   DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
19165 +                                            namelen);
19166 +
19167 +               tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
19168 +               dwc_memcpy(tmpbuf, pname, namelen);
19169 +               tmpbuf += namelen;
19170 +       }
19171 +
19172 +       totlen = tmpbuf - buf;
19173 +
19174 +       if (totlen > 0) {
19175 +               tmp = (cfi_all_features_header_t *) buf;
19176 +               tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
19177 +       }
19178 +
19179 +       return totlen;
19180 +}
19181 +
19182 +/**
19183 + * This function releases all the dynamic memory in the CFI object.
19184 + */
19185 +static void cfi_release(cfiobject_t * cfiobj)
19186 +{
19187 +       cfi_ep_t *cfiep;
19188 +       dwc_list_link_t *tmp;
19189 +
19190 +       CFI_INFO("%s\n", __func__);
19191 +
19192 +       if (cfiobj->buf_in.buf) {
19193 +               DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
19194 +                            cfiobj->buf_in.addr);
19195 +               cfiobj->buf_in.buf = NULL;
19196 +       }
19197 +
19198 +       if (cfiobj->buf_out.buf) {
19199 +               DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
19200 +                            cfiobj->buf_out.addr);
19201 +               cfiobj->buf_out.buf = NULL;
19202 +       }
19203 +
19204 +       /* Free the Buffer Setup values for each EP */
19205 +       //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
19206 +       DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
19207 +               cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19208 +               cfi_free_ep_bs_dyn_data(cfiep);
19209 +       }
19210 +}
19211 +
19212 +/**
19213 + * This function frees the dynamically allocated EP buffer setup data.
19214 + */
19215 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
19216 +{
19217 +       if (cfiep->bm_sg) {
19218 +               DWC_FREE(cfiep->bm_sg);
19219 +               cfiep->bm_sg = NULL;
19220 +       }
19221 +
19222 +       if (cfiep->bm_align) {
19223 +               DWC_FREE(cfiep->bm_align);
19224 +               cfiep->bm_align = NULL;
19225 +       }
19226 +
19227 +       if (cfiep->bm_concat) {
19228 +               if (NULL != cfiep->bm_concat->wTxBytes) {
19229 +                       DWC_FREE(cfiep->bm_concat->wTxBytes);
19230 +                       cfiep->bm_concat->wTxBytes = NULL;
19231 +               }
19232 +               DWC_FREE(cfiep->bm_concat);
19233 +               cfiep->bm_concat = NULL;
19234 +       }
19235 +}
19236 +
19237 +/**
19238 + * This function initializes the default values of the features
19239 + * for a specific endpoint and should be called only once when
19240 + * the EP is enabled first time.
19241 + */
19242 +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
19243 +{
19244 +       int retval = 0;
19245 +
19246 +       cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
19247 +       if (NULL == cfiep->bm_sg) {
19248 +               CFI_INFO("Failed to allocate memory for SG feature value\n");
19249 +               return -DWC_E_NO_MEMORY;
19250 +       }
19251 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19252 +
19253 +       /* For the Concatenation feature's default value we do not allocate
19254 +        * memory for the wTxBytes field - it will be done in the set_feature_value
19255 +        * request handler.
19256 +        */
19257 +       cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
19258 +       if (NULL == cfiep->bm_concat) {
19259 +               CFI_INFO
19260 +                   ("Failed to allocate memory for CONCATENATION feature value\n");
19261 +               DWC_FREE(cfiep->bm_sg);
19262 +               return -DWC_E_NO_MEMORY;
19263 +       }
19264 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19265 +
19266 +       cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
19267 +       if (NULL == cfiep->bm_align) {
19268 +               CFI_INFO
19269 +                   ("Failed to allocate memory for Alignment feature value\n");
19270 +               DWC_FREE(cfiep->bm_sg);
19271 +               DWC_FREE(cfiep->bm_concat);
19272 +               return -DWC_E_NO_MEMORY;
19273 +       }
19274 +       dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
19275 +
19276 +       return retval;
19277 +}
19278 +
19279 +/**
19280 + * The callback function that notifies the CFI on the activation of
19281 + * an endpoint in the PCD. The following steps are done in this function:
19282 + *
19283 + *     Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's
19284 + *             active endpoint)
19285 + *     Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
19286 + *     Set the Buffer Mode to standard
19287 + *     Initialize the default values for all EP modes (SG, Circular, Concat, Align)
19288 + *     Add the cfi_ep_t object to the list of active endpoints in the CFI object
19289 + */
19290 +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19291 +                        struct dwc_otg_pcd_ep *ep)
19292 +{
19293 +       cfi_ep_t *cfiep;
19294 +       int retval = -DWC_E_NOT_SUPPORTED;
19295 +
19296 +       CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
19297 +                "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
19298 +       /* MAS - Check whether this endpoint already is in the list */
19299 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19300 +
19301 +       if (NULL == cfiep) {
19302 +               /* Allocate a cfi_ep_t object */
19303 +               cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
19304 +               if (NULL == cfiep) {
19305 +                       CFI_INFO
19306 +                           ("Unable to allocate memory for <cfiep> in function %s\n",
19307 +                            __func__);
19308 +                       return -DWC_E_NO_MEMORY;
19309 +               }
19310 +               dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
19311 +
19312 +               /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
19313 +               cfiep->ep = ep;
19314 +
19315 +               /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
19316 +               ep->dwc_ep.descs =
19317 +                   DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
19318 +                                 sizeof(dwc_otg_dma_desc_t),
19319 +                                 &ep->dwc_ep.descs_dma_addr);
19320 +
19321 +               if (NULL == ep->dwc_ep.descs) {
19322 +                       DWC_FREE(cfiep);
19323 +                       return -DWC_E_NO_MEMORY;
19324 +               }
19325 +
19326 +               DWC_LIST_INIT(&cfiep->lh);
19327 +
19328 +               /* Set the buffer mode to BM_STANDARD. It will be modified
19329 +                * when building descriptors for a specific buffer mode */
19330 +               ep->dwc_ep.buff_mode = BM_STANDARD;
19331 +
19332 +               /* Create and initialize the default values for this EP's Buffer modes */
19333 +               if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
19334 +                       return retval;
19335 +
19336 +               /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
19337 +               DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
19338 +               retval = 0;
19339 +       } else {                /* The sought EP already is in the list */
19340 +               CFI_INFO("%s: The sought EP already is in the list\n",
19341 +                        __func__);
19342 +       }
19343 +
19344 +       return retval;
19345 +}
19346 +
19347 +/**
19348 + * This function is called when the data stage of a 3-stage Control Write request
19349 + * is complete.
19350 + *
19351 + */
19352 +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
19353 +                                  struct dwc_otg_pcd *pcd)
19354 +{
19355 +       uint32_t addr, reg_value;
19356 +       uint16_t wIndex, wValue;
19357 +       uint8_t bRequest;
19358 +       uint8_t *buf = cfi->buf_out.buf;
19359 +       //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
19360 +       struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
19361 +       int retval = -DWC_E_NOT_SUPPORTED;
19362 +
19363 +       CFI_INFO("%s\n", __func__);
19364 +
19365 +       bRequest = ctrl_req->bRequest;
19366 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
19367 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
19368 +
19369 +       /*
19370 +        * Save the pointer to the data stage in the ctrl_req's <data> field.
19371 +        * The request should be already saved in the command stage by now.
19372 +        */
19373 +       ctrl_req->data = cfi->buf_out.buf;
19374 +       cfi->need_status_in_complete = 0;
19375 +       cfi->need_gadget_att = 0;
19376 +
19377 +       switch (bRequest) {
19378 +       case VEN_CORE_WRITE_REGISTER:
19379 +               /* The buffer contains raw data of the new value for the register */
19380 +               reg_value = *((uint32_t *) buf);
19381 +               if (wValue == 0) {
19382 +                       addr = 0;
19383 +                       //addr = (uint32_t) pcd->otg_dev->os_dep.base;
19384 +                       addr += wIndex;
19385 +               } else {
19386 +                       addr = (wValue << 16) | wIndex;
19387 +               }
19388 +
19389 +               //writel(reg_value, addr);
19390 +
19391 +               retval = 0;
19392 +               cfi->need_status_in_complete = 1;
19393 +               break;
19394 +
19395 +       case VEN_CORE_SET_FEATURE:
19396 +               /* The buffer contains raw data of the new value of the feature */
19397 +               retval = cfi_set_feature_value(pcd);
19398 +               if (retval < 0)
19399 +                       return retval;
19400 +
19401 +               cfi->need_status_in_complete = 1;
19402 +               break;
19403 +
19404 +       default:
19405 +               break;
19406 +       }
19407 +
19408 +       return retval;
19409 +}
19410 +
19411 +/**
19412 + * This function builds the DMA descriptors for the SG buffer mode.
19413 + */
19414 +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19415 +                              dwc_otg_pcd_request_t * req)
19416 +{
19417 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19418 +       ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
19419 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19420 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19421 +       dma_addr_t buff_addr = req->dma;
19422 +       int i;
19423 +       uint32_t txsize, off;
19424 +
19425 +       txsize = sgval->wSize;
19426 +       off = sgval->bOffset;
19427 +
19428 +//      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n",
19429 +//              __func__, cfiep->ep->ep.name, txsize, off);
19430 +
19431 +       for (i = 0; i < sgval->bCount; i++) {
19432 +               desc->status.b.bs = BS_HOST_BUSY;
19433 +               desc->buf = buff_addr;
19434 +               desc->status.b.l = 0;
19435 +               desc->status.b.ioc = 0;
19436 +               desc->status.b.sp = 0;
19437 +               desc->status.b.bytes = txsize;
19438 +               desc->status.b.bs = BS_HOST_READY;
19439 +
19440 +               /* Set the next address of the buffer */
19441 +               buff_addr += txsize + off;
19442 +               desc_last = desc;
19443 +               desc++;
19444 +       }
19445 +
19446 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19447 +       desc_last->status.b.l = 1;
19448 +       desc_last->status.b.ioc = 1;
19449 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19450 +       /* Save the last DMA descriptor pointer */
19451 +       cfiep->dma_desc_last = desc_last;
19452 +       cfiep->desc_count = sgval->bCount;
19453 +}
19454 +
19455 +/**
19456 + * This function builds the DMA descriptors for the Concatenation buffer mode.
19457 + */
19458 +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19459 +                                  dwc_otg_pcd_request_t * req)
19460 +{
19461 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19462 +       ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
19463 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19464 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19465 +       dma_addr_t buff_addr = req->dma;
19466 +       int i;
19467 +       uint16_t *txsize;
19468 +
19469 +       txsize = concatval->wTxBytes;
19470 +
19471 +       for (i = 0; i < concatval->hdr.bDescCount; i++) {
19472 +               desc->buf = buff_addr;
19473 +               desc->status.b.bs = BS_HOST_BUSY;
19474 +               desc->status.b.l = 0;
19475 +               desc->status.b.ioc = 0;
19476 +               desc->status.b.sp = 0;
19477 +               desc->status.b.bytes = *txsize;
19478 +               desc->status.b.bs = BS_HOST_READY;
19479 +
19480 +               txsize++;
19481 +               /* Set the next address of the buffer */
19482 +               buff_addr += UGETW(ep->desc->wMaxPacketSize);
19483 +               desc_last = desc;
19484 +               desc++;
19485 +       }
19486 +
19487 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19488 +       desc_last->status.b.l = 1;
19489 +       desc_last->status.b.ioc = 1;
19490 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19491 +       cfiep->dma_desc_last = desc_last;
19492 +       cfiep->desc_count = concatval->hdr.bDescCount;
19493 +}
19494 +
19495 +/**
19496 + * This function builds the DMA descriptors for the Circular buffer mode
19497 + */
19498 +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19499 +                                dwc_otg_pcd_request_t * req)
19500 +{
19501 +       /* @todo: MAS - add implementation when this feature needs to be tested */
19502 +}
19503 +
19504 +/**
19505 + * This function builds the DMA descriptors for the Alignment buffer mode
19506 + */
19507 +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19508 +                                 dwc_otg_pcd_request_t * req)
19509 +{
19510 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19511 +       ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
19512 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19513 +       dma_addr_t buff_addr = req->dma;
19514 +
19515 +       desc->status.b.bs = BS_HOST_BUSY;
19516 +       desc->status.b.l = 1;
19517 +       desc->status.b.ioc = 1;
19518 +       desc->status.b.sp = ep->dwc_ep.sent_zlp;
19519 +       desc->status.b.bytes = req->length;
19520 +       /* Adjust the buffer alignment */
19521 +       desc->buf = (buff_addr + alignval->bAlign);
19522 +       desc->status.b.bs = BS_HOST_READY;
19523 +       cfiep->dma_desc_last = desc;
19524 +       cfiep->desc_count = 1;
19525 +}
19526 +
19527 +/**
19528 + * This function builds the DMA descriptors chain for different modes of the
19529 + * buffer setup of an endpoint.
19530 + */
19531 +static void cfi_build_descriptors(struct cfiobject *cfi,
19532 +                                 struct dwc_otg_pcd *pcd,
19533 +                                 struct dwc_otg_pcd_ep *ep,
19534 +                                 dwc_otg_pcd_request_t * req)
19535 +{
19536 +       cfi_ep_t *cfiep;
19537 +
19538 +       /* Get the cfiep by the dwc_otg_pcd_ep */
19539 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19540 +       if (NULL == cfiep) {
19541 +               CFI_INFO("%s: Unable to find a matching active endpoint\n",
19542 +                        __func__);
19543 +               return;
19544 +       }
19545 +
19546 +       cfiep->xfer_len = req->length;
19547 +
19548 +       /* Iterate through all the DMA descriptors */
19549 +       switch (cfiep->ep->dwc_ep.buff_mode) {
19550 +       case BM_SG:
19551 +               cfi_build_sg_descs(cfi, cfiep, req);
19552 +               break;
19553 +
19554 +       case BM_CONCAT:
19555 +               cfi_build_concat_descs(cfi, cfiep, req);
19556 +               break;
19557 +
19558 +       case BM_CIRCULAR:
19559 +               cfi_build_circ_descs(cfi, cfiep, req);
19560 +               break;
19561 +
19562 +       case BM_ALIGN:
19563 +               cfi_build_align_descs(cfi, cfiep, req);
19564 +               break;
19565 +
19566 +       default:
19567 +               break;
19568 +       }
19569 +}
19570 +
19571 +/**
19572 + * Allocate DMA buffer for different Buffer modes.
19573 + */
19574 +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19575 +                             struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
19576 +                             unsigned size, gfp_t flags)
19577 +{
19578 +       return DWC_DMA_ALLOC(size, dma);
19579 +}
19580 +
19581 +/**
19582 + * This function initializes the CFI object.
19583 + */
19584 +int init_cfi(cfiobject_t * cfiobj)
19585 +{
19586 +       CFI_INFO("%s\n", __func__);
19587 +
19588 +       /* Allocate a buffer for IN XFERs */
19589 +       cfiobj->buf_in.buf =
19590 +           DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
19591 +       if (NULL == cfiobj->buf_in.buf) {
19592 +               CFI_INFO("Unable to allocate buffer for INs\n");
19593 +               return -DWC_E_NO_MEMORY;
19594 +       }
19595 +
19596 +       /* Allocate a buffer for OUT XFERs */
19597 +       cfiobj->buf_out.buf =
19598 +           DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
19599 +       if (NULL == cfiobj->buf_out.buf) {
19600 +               CFI_INFO("Unable to allocate buffer for OUT\n");
19601 +               return -DWC_E_NO_MEMORY;
19602 +       }
19603 +
19604 +       /* Initialize the callback function pointers */
19605 +       cfiobj->ops.release = cfi_release;
19606 +       cfiobj->ops.ep_enable = cfi_ep_enable;
19607 +       cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
19608 +       cfiobj->ops.build_descriptors = cfi_build_descriptors;
19609 +       cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
19610 +
19611 +       /* Initialize the list of active endpoints in the CFI object */
19612 +       DWC_LIST_INIT(&cfiobj->active_eps);
19613 +
19614 +       return 0;
19615 +}
19616 +
19617 +/**
19618 + * This function reads the required feature's current value into the buffer
19619 + *
19620 + * @retval: Returns negative as error, or the data length of the feature
19621 + */
19622 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
19623 +                                struct dwc_otg_pcd *pcd,
19624 +                                struct cfi_usb_ctrlrequest *ctrl_req)
19625 +{
19626 +       int retval = -DWC_E_NOT_SUPPORTED;
19627 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19628 +       uint16_t dfifo, rxfifo, txfifo;
19629 +
19630 +       switch (ctrl_req->wIndex) {
19631 +               /* Whether the DDMA is enabled or not */
19632 +       case FT_ID_DMA_MODE:
19633 +               *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
19634 +               retval = 1;
19635 +               break;
19636 +
19637 +       case FT_ID_DMA_BUFFER_SETUP:
19638 +               retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
19639 +               break;
19640 +
19641 +       case FT_ID_DMA_BUFF_ALIGN:
19642 +               retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
19643 +               break;
19644 +
19645 +       case FT_ID_DMA_CONCAT_SETUP:
19646 +               retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
19647 +               break;
19648 +
19649 +       case FT_ID_DMA_CIRCULAR:
19650 +               CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
19651 +               break;
19652 +
19653 +       case FT_ID_THRESHOLD_SETUP:
19654 +               CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
19655 +               break;
19656 +
19657 +       case FT_ID_DFIFO_DEPTH:
19658 +               dfifo = get_dfifo_size(coreif);
19659 +               *((uint16_t *) buf) = dfifo;
19660 +               retval = sizeof(uint16_t);
19661 +               break;
19662 +
19663 +       case FT_ID_TX_FIFO_DEPTH:
19664 +               retval = get_txfifo_size(pcd, ctrl_req->wValue);
19665 +               if (retval >= 0) {
19666 +                       txfifo = retval;
19667 +                       *((uint16_t *) buf) = txfifo;
19668 +                       retval = sizeof(uint16_t);
19669 +               }
19670 +               break;
19671 +
19672 +       case FT_ID_RX_FIFO_DEPTH:
19673 +               retval = get_rxfifo_size(coreif, ctrl_req->wValue);
19674 +               if (retval >= 0) {
19675 +                       rxfifo = retval;
19676 +                       *((uint16_t *) buf) = rxfifo;
19677 +                       retval = sizeof(uint16_t);
19678 +               }
19679 +               break;
19680 +       }
19681 +
19682 +       return retval;
19683 +}
19684 +
19685 +/**
19686 + * This function resets the SG for the specified EP to its default value
19687 + */
19688 +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
19689 +{
19690 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19691 +       return 0;
19692 +}
19693 +
19694 +/**
19695 + * This function resets the Alignment for the specified EP to its default value
19696 + */
19697 +static int cfi_reset_align_val(cfi_ep_t * cfiep)
19698 +{
19699 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19700 +       return 0;
19701 +}
19702 +
19703 +/**
19704 + * This function resets the Concatenation for the specified EP to its default value
19705 + * This function will also set the value of the wTxBytes field to NULL after
19706 + * freeing the memory previously allocated for this field.
19707 + */
19708 +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
19709 +{
19710 +       /* First we need to free the wTxBytes field */
19711 +       if (cfiep->bm_concat->wTxBytes) {
19712 +               DWC_FREE(cfiep->bm_concat->wTxBytes);
19713 +               cfiep->bm_concat->wTxBytes = NULL;
19714 +       }
19715 +
19716 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19717 +       return 0;
19718 +}
19719 +
19720 +/**
19721 + * This function resets all the buffer setups of the specified endpoint
19722 + */
19723 +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
19724 +{
19725 +       cfi_reset_sg_val(cfiep);
19726 +       cfi_reset_align_val(cfiep);
19727 +       cfi_reset_concat_val(cfiep);
19728 +       return 0;
19729 +}
19730 +
19731 +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
19732 +                                    uint8_t rx_rst, uint8_t tx_rst)
19733 +{
19734 +       int retval = -DWC_E_INVALID;
19735 +       uint16_t tx_siz[15];
19736 +       uint16_t rx_siz = 0;
19737 +       dwc_otg_pcd_ep_t *ep = NULL;
19738 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
19739 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
19740 +
19741 +       if (rx_rst) {
19742 +               rx_siz = params->dev_rx_fifo_size;
19743 +               params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
19744 +       }
19745 +
19746 +       if (tx_rst) {
19747 +               if (ep_addr == 0) {
19748 +                       int i;
19749 +
19750 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
19751 +                               tx_siz[i] =
19752 +                                   core_if->core_params->dev_tx_fifo_size[i];
19753 +                               core_if->core_params->dev_tx_fifo_size[i] =
19754 +                                   core_if->init_txfsiz[i];
19755 +                       }
19756 +               } else {
19757 +
19758 +                       ep = get_ep_by_addr(pcd, ep_addr);
19759 +
19760 +                       if (NULL == ep) {
19761 +                               CFI_INFO
19762 +                                   ("%s: Unable to get the endpoint addr=0x%02x\n",
19763 +                                    __func__, ep_addr);
19764 +                               return -DWC_E_INVALID;
19765 +                       }
19766 +
19767 +                       tx_siz[0] =
19768 +                           params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
19769 +                                                    1];
19770 +                       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
19771 +                           GET_CORE_IF(pcd)->init_txfsiz[ep->
19772 +                                                         dwc_ep.tx_fifo_num -
19773 +                                                         1];
19774 +               }
19775 +       }
19776 +
19777 +       if (resize_fifos(GET_CORE_IF(pcd))) {
19778 +               retval = 0;
19779 +       } else {
19780 +               CFI_INFO
19781 +                   ("%s: Error resetting the feature Reset All(FIFO size)\n",
19782 +                    __func__);
19783 +               if (rx_rst) {
19784 +                       params->dev_rx_fifo_size = rx_siz;
19785 +               }
19786 +
19787 +               if (tx_rst) {
19788 +                       if (ep_addr == 0) {
19789 +                               int i;
19790 +                               for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
19791 +                                    i++) {
19792 +                                       core_if->
19793 +                                           core_params->dev_tx_fifo_size[i] =
19794 +                                           tx_siz[i];
19795 +                               }
19796 +                       } else {
19797 +                               params->dev_tx_fifo_size[ep->
19798 +                                                        dwc_ep.tx_fifo_num -
19799 +                                                        1] = tx_siz[0];
19800 +                       }
19801 +               }
19802 +               retval = -DWC_E_INVALID;
19803 +       }
19804 +       return retval;
19805 +}
19806 +
19807 +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
19808 +{
19809 +       int retval = 0;
19810 +       cfi_ep_t *cfiep;
19811 +       cfiobject_t *cfi = pcd->cfi;
19812 +       dwc_list_link_t *tmp;
19813 +
19814 +       retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
19815 +       if (retval < 0) {
19816 +               return retval;
19817 +       }
19818 +
19819 +       /* If the EP address is known then reset the features for only that EP */
19820 +       if (addr) {
19821 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19822 +               if (NULL == cfiep) {
19823 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19824 +                                __func__, addr);
19825 +                       return -DWC_E_INVALID;
19826 +               }
19827 +               retval = cfi_ep_reset_all_setup_vals(cfiep);
19828 +               cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19829 +       }
19830 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19831 +       else {
19832 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19833 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19834 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19835 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19836 +                       retval = cfi_ep_reset_all_setup_vals(cfiep);
19837 +                       cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19838 +                       if (retval < 0) {
19839 +                               CFI_INFO
19840 +                                   ("%s: Error resetting the feature Reset All\n",
19841 +                                    __func__);
19842 +                               return retval;
19843 +                       }
19844 +               }
19845 +       }
19846 +       return retval;
19847 +}
19848 +
19849 +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
19850 +                                          uint8_t addr)
19851 +{
19852 +       int retval = 0;
19853 +       cfi_ep_t *cfiep;
19854 +       cfiobject_t *cfi = pcd->cfi;
19855 +       dwc_list_link_t *tmp;
19856 +
19857 +       /* If the EP address is known then reset the features for only that EP */
19858 +       if (addr) {
19859 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19860 +               if (NULL == cfiep) {
19861 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19862 +                                __func__, addr);
19863 +                       return -DWC_E_INVALID;
19864 +               }
19865 +               retval = cfi_reset_sg_val(cfiep);
19866 +       }
19867 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19868 +       else {
19869 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19870 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19871 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19872 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19873 +                       retval = cfi_reset_sg_val(cfiep);
19874 +                       if (retval < 0) {
19875 +                               CFI_INFO
19876 +                                   ("%s: Error resetting the feature Buffer Setup\n",
19877 +                                    __func__);
19878 +                               return retval;
19879 +                       }
19880 +               }
19881 +       }
19882 +       return retval;
19883 +}
19884 +
19885 +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19886 +{
19887 +       int retval = 0;
19888 +       cfi_ep_t *cfiep;
19889 +       cfiobject_t *cfi = pcd->cfi;
19890 +       dwc_list_link_t *tmp;
19891 +
19892 +       /* If the EP address is known then reset the features for only that EP */
19893 +       if (addr) {
19894 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19895 +               if (NULL == cfiep) {
19896 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19897 +                                __func__, addr);
19898 +                       return -DWC_E_INVALID;
19899 +               }
19900 +               retval = cfi_reset_concat_val(cfiep);
19901 +       }
19902 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19903 +       else {
19904 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19905 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19906 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19907 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19908 +                       retval = cfi_reset_concat_val(cfiep);
19909 +                       if (retval < 0) {
19910 +                               CFI_INFO
19911 +                                   ("%s: Error resetting the feature Concatenation Value\n",
19912 +                                    __func__);
19913 +                               return retval;
19914 +                       }
19915 +               }
19916 +       }
19917 +       return retval;
19918 +}
19919 +
19920 +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19921 +{
19922 +       int retval = 0;
19923 +       cfi_ep_t *cfiep;
19924 +       cfiobject_t *cfi = pcd->cfi;
19925 +       dwc_list_link_t *tmp;
19926 +
19927 +       /* If the EP address is known then reset the features for only that EP */
19928 +       if (addr) {
19929 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19930 +               if (NULL == cfiep) {
19931 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19932 +                                __func__, addr);
19933 +                       return -DWC_E_INVALID;
19934 +               }
19935 +               retval = cfi_reset_align_val(cfiep);
19936 +       }
19937 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19938 +       else {
19939 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19940 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19941 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19942 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19943 +                       retval = cfi_reset_align_val(cfiep);
19944 +                       if (retval < 0) {
19945 +                               CFI_INFO
19946 +                                   ("%s: Error resetting the feature Aliignment Value\n",
19947 +                                    __func__);
19948 +                               return retval;
19949 +                       }
19950 +               }
19951 +       }
19952 +       return retval;
19953 +
19954 +}
19955 +
19956 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
19957 +                            struct cfi_usb_ctrlrequest *req)
19958 +{
19959 +       int retval = 0;
19960 +
19961 +       switch (req->wIndex) {
19962 +       case 0:
19963 +               /* Reset all features */
19964 +               retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
19965 +               break;
19966 +
19967 +       case FT_ID_DMA_BUFFER_SETUP:
19968 +               /* Reset the SG buffer setup */
19969 +               retval =
19970 +                   cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
19971 +               break;
19972 +
19973 +       case FT_ID_DMA_CONCAT_SETUP:
19974 +               /* Reset the Concatenation buffer setup */
19975 +               retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
19976 +               break;
19977 +
19978 +       case FT_ID_DMA_BUFF_ALIGN:
19979 +               /* Reset the Alignment buffer setup */
19980 +               retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
19981 +               break;
19982 +
19983 +       case FT_ID_TX_FIFO_DEPTH:
19984 +               retval =
19985 +                   cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
19986 +               pcd->cfi->need_gadget_att = 0;
19987 +               break;
19988 +
19989 +       case FT_ID_RX_FIFO_DEPTH:
19990 +               retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
19991 +               pcd->cfi->need_gadget_att = 0;
19992 +               break;
19993 +       default:
19994 +               break;
19995 +       }
19996 +       return retval;
19997 +}
19998 +
19999 +/**
20000 + * This function sets a new value for the SG buffer setup.
20001 + */
20002 +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20003 +{
20004 +       uint8_t inaddr, outaddr;
20005 +       cfi_ep_t *epin, *epout;
20006 +       ddma_sg_buffer_setup_t *psgval;
20007 +       uint32_t desccount, size;
20008 +
20009 +       CFI_INFO("%s\n", __func__);
20010 +
20011 +       psgval = (ddma_sg_buffer_setup_t *) buf;
20012 +       desccount = (uint32_t) psgval->bCount;
20013 +       size = (uint32_t) psgval->wSize;
20014 +
20015 +       /* Check the DMA descriptor count */
20016 +       if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
20017 +               CFI_INFO
20018 +                   ("%s: The count of DMA Descriptors should be between 1 and %d\n",
20019 +                    __func__, MAX_DMA_DESCS_PER_EP);
20020 +               return -DWC_E_INVALID;
20021 +       }
20022 +
20023 +       /* Check the DMA descriptor count */
20024 +
20025 +       if (size == 0) {
20026 +
20027 +               CFI_INFO("%s: The transfer size should be at least 1 byte\n",
20028 +                        __func__);
20029 +
20030 +               return -DWC_E_INVALID;
20031 +
20032 +       }
20033 +
20034 +       inaddr = psgval->bInEndpointAddress;
20035 +       outaddr = psgval->bOutEndpointAddress;
20036 +
20037 +       epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
20038 +       epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
20039 +
20040 +       if (NULL == epin || NULL == epout) {
20041 +               CFI_INFO
20042 +                   ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
20043 +                    __func__, inaddr, outaddr);
20044 +               return -DWC_E_INVALID;
20045 +       }
20046 +
20047 +       epin->ep->dwc_ep.buff_mode = BM_SG;
20048 +       dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20049 +
20050 +       epout->ep->dwc_ep.buff_mode = BM_SG;
20051 +       dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20052 +
20053 +       return 0;
20054 +}
20055 +
20056 +/**
20057 + * This function sets a new value for the buffer Alignment setup.
20058 + */
20059 +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20060 +{
20061 +       cfi_ep_t *ep;
20062 +       uint8_t addr;
20063 +       ddma_align_buffer_setup_t *palignval;
20064 +
20065 +       palignval = (ddma_align_buffer_setup_t *) buf;
20066 +       addr = palignval->bEndpointAddress;
20067 +
20068 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20069 +
20070 +       if (NULL == ep) {
20071 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20072 +                        __func__, addr);
20073 +               return -DWC_E_INVALID;
20074 +       }
20075 +
20076 +       ep->ep->dwc_ep.buff_mode = BM_ALIGN;
20077 +       dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
20078 +
20079 +       return 0;
20080 +}
20081 +
20082 +/**
20083 + * This function sets a new value for the Concatenation buffer setup.
20084 + */
20085 +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20086 +{
20087 +       uint8_t addr;
20088 +       cfi_ep_t *ep;
20089 +       struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
20090 +       uint16_t *pVals;
20091 +       uint32_t desccount;
20092 +       int i;
20093 +       uint16_t mps;
20094 +
20095 +       pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
20096 +       desccount = (uint32_t) pConcatValHdr->bDescCount;
20097 +       pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
20098 +
20099 +       /* Check the DMA descriptor count */
20100 +       if (desccount > MAX_DMA_DESCS_PER_EP) {
20101 +               CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
20102 +                        __func__, MAX_DMA_DESCS_PER_EP);
20103 +               return -DWC_E_INVALID;
20104 +       }
20105 +
20106 +       addr = pConcatValHdr->bEndpointAddress;
20107 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20108 +       if (NULL == ep) {
20109 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20110 +                        __func__, addr);
20111 +               return -DWC_E_INVALID;
20112 +       }
20113 +
20114 +       mps = UGETW(ep->ep->desc->wMaxPacketSize);
20115 +
20116 +#if 0
20117 +       for (i = 0; i < desccount; i++) {
20118 +               CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
20119 +       }
20120 +       CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
20121 +#endif
20122 +
20123 +       /* Check the wTxSizes to be less than or equal to the mps */
20124 +       for (i = 0; i < desccount; i++) {
20125 +               if (pVals[i] > mps) {
20126 +                       CFI_INFO
20127 +                           ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
20128 +                            __func__, i, pVals[i]);
20129 +                       return -DWC_E_INVALID;
20130 +               }
20131 +       }
20132 +
20133 +       ep->ep->dwc_ep.buff_mode = BM_CONCAT;
20134 +       dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
20135 +
20136 +       /* Free the previously allocated storage for the wTxBytes */
20137 +       if (ep->bm_concat->wTxBytes) {
20138 +               DWC_FREE(ep->bm_concat->wTxBytes);
20139 +       }
20140 +
20141 +       /* Allocate a new storage for the wTxBytes field */
20142 +       ep->bm_concat->wTxBytes =
20143 +           DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
20144 +       if (NULL == ep->bm_concat->wTxBytes) {
20145 +               CFI_INFO("%s: Unable to allocate memory\n", __func__);
20146 +               return -DWC_E_NO_MEMORY;
20147 +       }
20148 +
20149 +       /* Copy the new values into the wTxBytes filed */
20150 +       dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
20151 +                  sizeof(uint16_t) * pConcatValHdr->bDescCount);
20152 +
20153 +       return 0;
20154 +}
20155 +
20156 +/**
20157 + * This function calculates the total of all FIFO sizes
20158 + *
20159 + * @param core_if Programming view of DWC_otg controller
20160 + *
20161 + * @return The total of data FIFO sizes.
20162 + *
20163 + */
20164 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
20165 +{
20166 +       dwc_otg_core_params_t *params = core_if->core_params;
20167 +       uint16_t dfifo_total = 0;
20168 +       int i;
20169 +
20170 +       /* The shared RxFIFO size */
20171 +       dfifo_total =
20172 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20173 +
20174 +       /* Add up each TxFIFO size to the total */
20175 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20176 +               dfifo_total += params->dev_tx_fifo_size[i];
20177 +       }
20178 +
20179 +       return dfifo_total;
20180 +}
20181 +
20182 +/**
20183 + * This function returns Rx FIFO size
20184 + *
20185 + * @param core_if Programming view of DWC_otg controller
20186 + *
20187 + * @return The total of data FIFO sizes.
20188 + *
20189 + */
20190 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
20191 +{
20192 +       switch (wValue >> 8) {
20193 +       case 0:
20194 +               return (core_if->pwron_rxfsiz <
20195 +                       32768) ? core_if->pwron_rxfsiz : 32768;
20196 +               break;
20197 +       case 1:
20198 +               return core_if->core_params->dev_rx_fifo_size;
20199 +               break;
20200 +       default:
20201 +               return -DWC_E_INVALID;
20202 +               break;
20203 +       }
20204 +}
20205 +
20206 +/**
20207 + * This function returns Tx FIFO size for IN EP
20208 + *
20209 + * @param core_if Programming view of DWC_otg controller
20210 + *
20211 + * @return The total of data FIFO sizes.
20212 + *
20213 + */
20214 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
20215 +{
20216 +       dwc_otg_pcd_ep_t *ep;
20217 +
20218 +       ep = get_ep_by_addr(pcd, wValue & 0xff);
20219 +
20220 +       if (NULL == ep) {
20221 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20222 +                        __func__, wValue & 0xff);
20223 +               return -DWC_E_INVALID;
20224 +       }
20225 +
20226 +       if (!ep->dwc_ep.is_in) {
20227 +               CFI_INFO
20228 +                   ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
20229 +                    __func__, wValue & 0xff);
20230 +               return -DWC_E_INVALID;
20231 +       }
20232 +
20233 +       switch (wValue >> 8) {
20234 +       case 0:
20235 +               return (GET_CORE_IF(pcd)->pwron_txfsiz
20236 +                       [ep->dwc_ep.tx_fifo_num - 1] <
20237 +                       768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
20238 +                                                             dwc_ep.tx_fifo_num
20239 +                                                             - 1] : 32768;
20240 +               break;
20241 +       case 1:
20242 +               return GET_CORE_IF(pcd)->core_params->
20243 +                   dev_tx_fifo_size[ep->dwc_ep.num - 1];
20244 +               break;
20245 +       default:
20246 +               return -DWC_E_INVALID;
20247 +               break;
20248 +       }
20249 +}
20250 +
20251 +/**
20252 + * This function checks if the submitted combination of
20253 + * device mode FIFO sizes is possible or not.
20254 + *
20255 + * @param core_if Programming view of DWC_otg controller
20256 + *
20257 + * @return 1 if possible, 0 otherwise.
20258 + *
20259 + */
20260 +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
20261 +{
20262 +       uint16_t dfifo_actual = 0;
20263 +       dwc_otg_core_params_t *params = core_if->core_params;
20264 +       uint16_t start_addr = 0;
20265 +       int i;
20266 +
20267 +       dfifo_actual =
20268 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20269 +
20270 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20271 +               dfifo_actual += params->dev_tx_fifo_size[i];
20272 +       }
20273 +
20274 +       if (dfifo_actual > core_if->total_fifo_size) {
20275 +               return 0;
20276 +       }
20277 +
20278 +       if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
20279 +               return 0;
20280 +
20281 +       if (params->dev_nperio_tx_fifo_size > 32768
20282 +           || params->dev_nperio_tx_fifo_size < 16)
20283 +               return 0;
20284 +
20285 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20286 +
20287 +               if (params->dev_tx_fifo_size[i] > 768
20288 +                   || params->dev_tx_fifo_size[i] < 4)
20289 +                       return 0;
20290 +       }
20291 +
20292 +       if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
20293 +               return 0;
20294 +       start_addr = params->dev_rx_fifo_size;
20295 +
20296 +       if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
20297 +               return 0;
20298 +       start_addr += params->dev_nperio_tx_fifo_size;
20299 +
20300 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20301 +
20302 +               if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
20303 +                       return 0;
20304 +               start_addr += params->dev_tx_fifo_size[i];
20305 +       }
20306 +
20307 +       return 1;
20308 +}
20309 +
20310 +/**
20311 + * This function resizes Device mode FIFOs
20312 + *
20313 + * @param core_if Programming view of DWC_otg controller
20314 + *
20315 + * @return 1 if successful, 0 otherwise
20316 + *
20317 + */
20318 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
20319 +{
20320 +       int i = 0;
20321 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
20322 +       dwc_otg_core_params_t *params = core_if->core_params;
20323 +       uint32_t rx_fifo_size;
20324 +       fifosize_data_t nptxfifosize;
20325 +       fifosize_data_t txfifosize[15];
20326 +
20327 +       uint32_t rx_fsz_bak;
20328 +       uint32_t nptxfsz_bak;
20329 +       uint32_t txfsz_bak[15];
20330 +
20331 +       uint16_t start_address;
20332 +       uint8_t retval = 1;
20333 +
20334 +       if (!check_fifo_sizes(core_if)) {
20335 +               return 0;
20336 +       }
20337 +
20338 +       /* Configure data FIFO sizes */
20339 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
20340 +               rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
20341 +               rx_fifo_size = params->dev_rx_fifo_size;
20342 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
20343 +
20344 +               /*
20345 +                * Tx FIFOs These FIFOs are numbered from 1 to 15.
20346 +                * Indexes of the FIFO size module parameters in the
20347 +                * dev_tx_fifo_size array and the FIFO size registers in
20348 +                * the dtxfsiz array run from 0 to 14.
20349 +                */
20350 +
20351 +               /* Non-periodic Tx FIFO */
20352 +               nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
20353 +               nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
20354 +               start_address = params->dev_rx_fifo_size;
20355 +               nptxfifosize.b.startaddr = start_address;
20356 +
20357 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
20358 +
20359 +               start_address += nptxfifosize.b.depth;
20360 +
20361 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20362 +                       txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
20363 +
20364 +                       txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
20365 +                       txfifosize[i].b.startaddr = start_address;
20366 +                       DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20367 +                                       txfifosize[i].d32);
20368 +
20369 +                       start_address += txfifosize[i].b.depth;
20370 +               }
20371 +
20372 +               /** Check if register values are set correctly */
20373 +               if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
20374 +                       retval = 0;
20375 +               }
20376 +
20377 +               if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
20378 +                       retval = 0;
20379 +               }
20380 +
20381 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20382 +                       if (txfifosize[i].d32 !=
20383 +                           DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
20384 +                               retval = 0;
20385 +                       }
20386 +               }
20387 +
20388 +               /** If register values are not set correctly, reset old values */
20389 +               if (retval == 0) {
20390 +                       DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
20391 +
20392 +                       /* Non-periodic Tx FIFO */
20393 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
20394 +
20395 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20396 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20397 +                                               txfsz_bak[i]);
20398 +                       }
20399 +               }
20400 +       } else {
20401 +               return 0;
20402 +       }
20403 +
20404 +       /* Flush the FIFOs */
20405 +       dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
20406 +       dwc_otg_flush_rx_fifo(core_if);
20407 +
20408 +       return retval;
20409 +}
20410 +
20411 +/**
20412 + * This function sets a new value for the buffer Alignment setup.
20413 + */
20414 +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20415 +{
20416 +       int retval;
20417 +       uint32_t fsiz;
20418 +       uint16_t size;
20419 +       uint16_t ep_addr;
20420 +       dwc_otg_pcd_ep_t *ep;
20421 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20422 +       tx_fifo_size_setup_t *ptxfifoval;
20423 +
20424 +       ptxfifoval = (tx_fifo_size_setup_t *) buf;
20425 +       ep_addr = ptxfifoval->bEndpointAddress;
20426 +       size = ptxfifoval->wDepth;
20427 +
20428 +       ep = get_ep_by_addr(pcd, ep_addr);
20429 +
20430 +       CFI_INFO
20431 +           ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
20432 +            __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
20433 +
20434 +       if (NULL == ep) {
20435 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20436 +                        __func__, ep_addr);
20437 +               return -DWC_E_INVALID;
20438 +       }
20439 +
20440 +       fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
20441 +       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
20442 +
20443 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20444 +               retval = 0;
20445 +       } else {
20446 +               CFI_INFO
20447 +                   ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
20448 +                    __func__, ep_addr);
20449 +               params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
20450 +               retval = -DWC_E_INVALID;
20451 +       }
20452 +
20453 +       return retval;
20454 +}
20455 +
20456 +/**
20457 + * This function sets a new value for the buffer Alignment setup.
20458 + */
20459 +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20460 +{
20461 +       int retval;
20462 +       uint32_t fsiz;
20463 +       uint16_t size;
20464 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20465 +       rx_fifo_size_setup_t *prxfifoval;
20466 +
20467 +       prxfifoval = (rx_fifo_size_setup_t *) buf;
20468 +       size = prxfifoval->wDepth;
20469 +
20470 +       fsiz = params->dev_rx_fifo_size;
20471 +       params->dev_rx_fifo_size = size;
20472 +
20473 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20474 +               retval = 0;
20475 +       } else {
20476 +               CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
20477 +                        __func__);
20478 +               params->dev_rx_fifo_size = fsiz;
20479 +               retval = -DWC_E_INVALID;
20480 +       }
20481 +
20482 +       return retval;
20483 +}
20484 +
20485 +/**
20486 + * This function reads the SG of an EP's buffer setup into the buffer buf
20487 + */
20488 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20489 +                            struct cfi_usb_ctrlrequest *req)
20490 +{
20491 +       int retval = -DWC_E_INVALID;
20492 +       uint8_t addr;
20493 +       cfi_ep_t *ep;
20494 +
20495 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20496 +       addr = req->wValue & 0xFF;
20497 +       if (addr == 0)          /* The address should be non-zero */
20498 +               return retval;
20499 +
20500 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20501 +       if (NULL == ep) {
20502 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20503 +                        __func__, addr);
20504 +               return retval;
20505 +       }
20506 +
20507 +       dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
20508 +       retval = BS_SG_VAL_DESC_LEN;
20509 +       return retval;
20510 +}
20511 +
20512 +/**
20513 + * This function reads the Concatenation value of an EP's buffer mode into
20514 + * the buffer buf
20515 + */
20516 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20517 +                                struct cfi_usb_ctrlrequest *req)
20518 +{
20519 +       int retval = -DWC_E_INVALID;
20520 +       uint8_t addr;
20521 +       cfi_ep_t *ep;
20522 +       uint8_t desc_count;
20523 +
20524 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20525 +       addr = req->wValue & 0xFF;
20526 +       if (addr == 0)          /* The address should be non-zero */
20527 +               return retval;
20528 +
20529 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20530 +       if (NULL == ep) {
20531 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20532 +                        __func__, addr);
20533 +               return retval;
20534 +       }
20535 +
20536 +       /* Copy the header to the buffer */
20537 +       dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
20538 +       /* Advance the buffer pointer by the header size */
20539 +       buf += BS_CONCAT_VAL_HDR_LEN;
20540 +
20541 +       desc_count = ep->bm_concat->hdr.bDescCount;
20542 +       /* Copy alll the wTxBytes to the buffer */
20543 +       dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
20544 +
20545 +       retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
20546 +       return retval;
20547 +}
20548 +
20549 +/**
20550 + * This function reads the buffer Alignment value of an EP's buffer mode into
20551 + * the buffer buf
20552 + *
20553 + * @return The total number of bytes copied to the buffer or negative error code.
20554 + */
20555 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20556 +                               struct cfi_usb_ctrlrequest *req)
20557 +{
20558 +       int retval = -DWC_E_INVALID;
20559 +       uint8_t addr;
20560 +       cfi_ep_t *ep;
20561 +
20562 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20563 +       addr = req->wValue & 0xFF;
20564 +       if (addr == 0)          /* The address should be non-zero */
20565 +               return retval;
20566 +
20567 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20568 +       if (NULL == ep) {
20569 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20570 +                        __func__, addr);
20571 +               return retval;
20572 +       }
20573 +
20574 +       dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
20575 +       retval = BS_ALIGN_VAL_HDR_LEN;
20576 +
20577 +       return retval;
20578 +}
20579 +
20580 +/**
20581 + * This function sets a new value for the specified feature
20582 + *
20583 + * @param      pcd     A pointer to the PCD object
20584 + *
20585 + * @return 0 if successful, negative error code otherwise to stall the DCE.
20586 + */
20587 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
20588 +{
20589 +       int retval = -DWC_E_NOT_SUPPORTED;
20590 +       uint16_t wIndex, wValue;
20591 +       uint8_t bRequest;
20592 +       struct dwc_otg_core_if *coreif;
20593 +       cfiobject_t *cfi = pcd->cfi;
20594 +       struct cfi_usb_ctrlrequest *ctrl_req;
20595 +       uint8_t *buf;
20596 +       ctrl_req = &cfi->ctrl_req;
20597 +
20598 +       buf = pcd->cfi->ctrl_req.data;
20599 +
20600 +       coreif = GET_CORE_IF(pcd);
20601 +       bRequest = ctrl_req->bRequest;
20602 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
20603 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
20604 +
20605 +       /* See which feature is to be modified */
20606 +       switch (wIndex) {
20607 +       case FT_ID_DMA_BUFFER_SETUP:
20608 +               /* Modify the feature */
20609 +               if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
20610 +                       return retval;
20611 +
20612 +               /* And send this request to the gadget */
20613 +               cfi->need_gadget_att = 1;
20614 +               break;
20615 +
20616 +       case FT_ID_DMA_BUFF_ALIGN:
20617 +               if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
20618 +                       return retval;
20619 +               cfi->need_gadget_att = 1;
20620 +               break;
20621 +
20622 +       case FT_ID_DMA_CONCAT_SETUP:
20623 +               /* Modify the feature */
20624 +               if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
20625 +                       return retval;
20626 +               cfi->need_gadget_att = 1;
20627 +               break;
20628 +
20629 +       case FT_ID_DMA_CIRCULAR:
20630 +               CFI_INFO("FT_ID_DMA_CIRCULAR\n");
20631 +               break;
20632 +
20633 +       case FT_ID_THRESHOLD_SETUP:
20634 +               CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
20635 +               break;
20636 +
20637 +       case FT_ID_DFIFO_DEPTH:
20638 +               CFI_INFO("FT_ID_DFIFO_DEPTH\n");
20639 +               break;
20640 +
20641 +       case FT_ID_TX_FIFO_DEPTH:
20642 +               CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
20643 +               if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
20644 +                       return retval;
20645 +               cfi->need_gadget_att = 0;
20646 +               break;
20647 +
20648 +       case FT_ID_RX_FIFO_DEPTH:
20649 +               CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
20650 +               if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
20651 +                       return retval;
20652 +               cfi->need_gadget_att = 0;
20653 +               break;
20654 +       }
20655 +
20656 +       return retval;
20657 +}
20658 +
20659 +#endif //DWC_UTE_CFI
20660 --- /dev/null
20661 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20662 @@ -0,0 +1,320 @@
20663 +/* ==========================================================================
20664 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20665 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20666 + * otherwise expressly agreed to in writing between Synopsys and you.
20667 + *
20668 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20669 + * any End User Software License Agreement or Agreement for Licensed Product
20670 + * with Synopsys or any supplement thereto. You are permitted to use and
20671 + * redistribute this Software in source and binary forms, with or without
20672 + * modification, provided that redistributions of source code must retain this
20673 + * notice. You may not view, use, disclose, copy or distribute this file or
20674 + * any information contained herein except pursuant to this license grant from
20675 + * Synopsys. If you do not agree with this notice, including the disclaimer
20676 + * below, then you are not authorized to use the Software.
20677 + *
20678 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20679 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20680 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20681 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20682 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20683 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20684 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20685 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20686 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20687 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20688 + * DAMAGE.
20689 + * ========================================================================== */
20690 +
20691 +#if !defined(__DWC_OTG_CFI_H__)
20692 +#define __DWC_OTG_CFI_H__
20693 +
20694 +#include "dwc_otg_pcd.h"
20695 +#include "dwc_cfi_common.h"
20696 +
20697 +/**
20698 + * @file
20699 + * This file contains the CFI related OTG PCD specific common constants,
20700 + * interfaces(functions and macros) and data structures.The CFI Protocol is an
20701 + * optional interface for internal testing purposes that a DUT may implement to
20702 + * support testing of configurable features.
20703 + *
20704 + */
20705 +
20706 +struct dwc_otg_pcd;
20707 +struct dwc_otg_pcd_ep;
20708 +
20709 +/** OTG CFI Features (properties) ID constants */
20710 +/** This is a request for all Core Features */
20711 +#define FT_ID_DMA_MODE                                 0x0001
20712 +#define FT_ID_DMA_BUFFER_SETUP                 0x0002
20713 +#define FT_ID_DMA_BUFF_ALIGN                   0x0003
20714 +#define FT_ID_DMA_CONCAT_SETUP                 0x0004
20715 +#define FT_ID_DMA_CIRCULAR                             0x0005
20716 +#define FT_ID_THRESHOLD_SETUP                  0x0006
20717 +#define FT_ID_DFIFO_DEPTH                              0x0007
20718 +#define FT_ID_TX_FIFO_DEPTH                            0x0008
20719 +#define FT_ID_RX_FIFO_DEPTH                            0x0009
20720 +
20721 +/**********************************************************/
20722 +#define CFI_INFO_DEF
20723 +
20724 +#ifdef CFI_INFO_DEF
20725 +#define CFI_INFO(fmt...)       DWC_PRINTF("CFI: " fmt);
20726 +#else
20727 +#define CFI_INFO(fmt...)
20728 +#endif
20729 +
20730 +#define min(x,y) ({ \
20731 +       x < y ? x : y; })
20732 +
20733 +#define max(x,y) ({ \
20734 +       x > y ? x : y; })
20735 +
20736 +/**
20737 + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
20738 + * also used for setting up a buffer for Circular DDMA.
20739 + */
20740 +struct _ddma_sg_buffer_setup {
20741 +#define BS_SG_VAL_DESC_LEN     6
20742 +       /* The OUT EP address */
20743 +       uint8_t bOutEndpointAddress;
20744 +       /* The IN EP address */
20745 +       uint8_t bInEndpointAddress;
20746 +       /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
20747 +       uint8_t bOffset;
20748 +       /* The number of transfer segments (a DMA descriptors per each segment) */
20749 +       uint8_t bCount;
20750 +       /* Size (in byte) of each transfer segment */
20751 +       uint16_t wSize;
20752 +} __attribute__ ((packed));
20753 +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
20754 +
20755 +/** Descriptor DMA Concatenation Buffer setup structure */
20756 +struct _ddma_concat_buffer_setup_hdr {
20757 +#define BS_CONCAT_VAL_HDR_LEN  4
20758 +       /* The endpoint for which the buffer is to be set up */
20759 +       uint8_t bEndpointAddress;
20760 +       /* The count of descriptors to be used */
20761 +       uint8_t bDescCount;
20762 +       /* The total size of the transfer */
20763 +       uint16_t wSize;
20764 +} __attribute__ ((packed));
20765 +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
20766 +
20767 +/** Descriptor DMA Concatenation Buffer setup structure */
20768 +struct _ddma_concat_buffer_setup {
20769 +       /* The SG header */
20770 +       ddma_concat_buffer_setup_hdr_t hdr;
20771 +
20772 +       /* The XFER sizes pointer (allocated dynamically) */
20773 +       uint16_t *wTxBytes;
20774 +} __attribute__ ((packed));
20775 +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
20776 +
20777 +/** Descriptor DMA Alignment Buffer setup structure */
20778 +struct _ddma_align_buffer_setup {
20779 +#define BS_ALIGN_VAL_HDR_LEN   2
20780 +       uint8_t bEndpointAddress;
20781 +       uint8_t bAlign;
20782 +} __attribute__ ((packed));
20783 +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
20784 +
20785 +/** Transmit FIFO Size setup structure */
20786 +struct _tx_fifo_size_setup {
20787 +       uint8_t bEndpointAddress;
20788 +       uint16_t wDepth;
20789 +} __attribute__ ((packed));
20790 +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
20791 +
20792 +/** Transmit FIFO Size setup structure */
20793 +struct _rx_fifo_size_setup {
20794 +       uint16_t wDepth;
20795 +} __attribute__ ((packed));
20796 +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
20797 +
20798 +/**
20799 + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
20800 + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer
20801 + * to the data returned in the data stage of a 3-stage Control Write requests.
20802 + */
20803 +struct cfi_usb_ctrlrequest {
20804 +       uint8_t bRequestType;
20805 +       uint8_t bRequest;
20806 +       uint16_t wValue;
20807 +       uint16_t wIndex;
20808 +       uint16_t wLength;
20809 +       uint8_t *data;
20810 +} UPACKED;
20811 +
20812 +/*---------------------------------------------------------------------------*/
20813 +
20814 +/**
20815 + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
20816 + * This structure is used to store the buffer setup data for any
20817 + * enabled endpoint in the PCD.
20818 + */
20819 +struct cfi_ep {
20820 +       /* Entry for the list container */
20821 +       dwc_list_link_t lh;
20822 +       /* Pointer to the active PCD endpoint structure */
20823 +       struct dwc_otg_pcd_ep *ep;
20824 +       /* The last descriptor in the chain of DMA descriptors of the endpoint */
20825 +       struct dwc_otg_dma_desc *dma_desc_last;
20826 +       /* The SG feature value */
20827 +       ddma_sg_buffer_setup_t *bm_sg;
20828 +       /* The Circular feature value */
20829 +       ddma_sg_buffer_setup_t *bm_circ;
20830 +       /* The Concatenation feature value */
20831 +       ddma_concat_buffer_setup_t *bm_concat;
20832 +       /* The Alignment feature value */
20833 +       ddma_align_buffer_setup_t *bm_align;
20834 +       /* XFER length */
20835 +       uint32_t xfer_len;
20836 +       /*
20837 +        * Count of DMA descriptors currently used.
20838 +        * The total should not exceed the MAX_DMA_DESCS_PER_EP value
20839 +        * defined in the dwc_otg_cil.h
20840 +        */
20841 +       uint32_t desc_count;
20842 +};
20843 +typedef struct cfi_ep cfi_ep_t;
20844 +
20845 +typedef struct cfi_dma_buff {
20846 +#define CFI_IN_BUF_LEN 1024
20847 +#define CFI_OUT_BUF_LEN        1024
20848 +       dma_addr_t addr;
20849 +       uint8_t *buf;
20850 +} cfi_dma_buff_t;
20851 +
20852 +struct cfiobject;
20853 +
20854 +/**
20855 + * This is the interface for the CFI operations.
20856 + *
20857 + * @param      ep_enable                       Called when any endpoint is enabled and activated.
20858 + * @param      release                         Called when the CFI object is released and it needs to correctly
20859 + *                                                             deallocate the dynamic memory
20860 + * @param      ctrl_write_complete     Called when the data stage of the request is complete
20861 + */
20862 +typedef struct cfi_ops {
20863 +       int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20864 +                         struct dwc_otg_pcd_ep * ep);
20865 +       void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20866 +                              struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
20867 +                              unsigned size, gfp_t flags);
20868 +       void (*release) (struct cfiobject * cfi);
20869 +       int (*ctrl_write_complete) (struct cfiobject * cfi,
20870 +                                   struct dwc_otg_pcd * pcd);
20871 +       void (*build_descriptors) (struct cfiobject * cfi,
20872 +                                  struct dwc_otg_pcd * pcd,
20873 +                                  struct dwc_otg_pcd_ep * ep,
20874 +                                  dwc_otg_pcd_request_t * req);
20875 +} cfi_ops_t;
20876 +
20877 +struct cfiobject {
20878 +       cfi_ops_t ops;
20879 +       struct dwc_otg_pcd *pcd;
20880 +       struct usb_gadget *gadget;
20881 +
20882 +       /* Buffers used to send/receive CFI-related request data */
20883 +       cfi_dma_buff_t buf_in;
20884 +       cfi_dma_buff_t buf_out;
20885 +
20886 +       /* CFI specific Control request wrapper */
20887 +       struct cfi_usb_ctrlrequest ctrl_req;
20888 +
20889 +       /* The list of active EP's in the PCD of type cfi_ep_t */
20890 +       dwc_list_link_t active_eps;
20891 +
20892 +       /* This flag shall control the propagation of a specific request
20893 +        * to the gadget's processing routines.
20894 +        * 0 - no gadget handling
20895 +        * 1 - the gadget needs to know about this request (w/o completing a status
20896 +        * phase - just return a 0 to the _setup callback)
20897 +        */
20898 +       uint8_t need_gadget_att;
20899 +
20900 +       /* Flag indicating whether the status IN phase needs to be
20901 +        * completed by the PCD
20902 +        */
20903 +       uint8_t need_status_in_complete;
20904 +};
20905 +typedef struct cfiobject cfiobject_t;
20906 +
20907 +#define DUMP_MSG
20908 +
20909 +#if defined(DUMP_MSG)
20910 +static inline void dump_msg(const u8 * buf, unsigned int length)
20911 +{
20912 +       unsigned int start, num, i;
20913 +       char line[52], *p;
20914 +
20915 +       if (length >= 512)
20916 +               return;
20917 +
20918 +       start = 0;
20919 +       while (length > 0) {
20920 +               num = min(length, 16u);
20921 +               p = line;
20922 +               for (i = 0; i < num; ++i) {
20923 +                       if (i == 8)
20924 +                               *p++ = ' ';
20925 +                       DWC_SPRINTF(p, " %02x", buf[i]);
20926 +                       p += 3;
20927 +               }
20928 +               *p = 0;
20929 +               DWC_DEBUG("%6x: %s\n", start, line);
20930 +               buf += num;
20931 +               start += num;
20932 +               length -= num;
20933 +       }
20934 +}
20935 +#else
20936 +static inline void dump_msg(const u8 * buf, unsigned int length)
20937 +{
20938 +}
20939 +#endif
20940 +
20941 +/**
20942 + * This function returns a pointer to cfi_ep_t object with the addr address.
20943 + */
20944 +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
20945 +                                               uint8_t addr)
20946 +{
20947 +       struct cfi_ep *pcfiep;
20948 +       dwc_list_link_t *tmp;
20949 +
20950 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20951 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20952 +
20953 +               if (pcfiep->ep->desc->bEndpointAddress == addr) {
20954 +                       return pcfiep;
20955 +               }
20956 +       }
20957 +
20958 +       return NULL;
20959 +}
20960 +
20961 +/**
20962 + * This function returns a pointer to cfi_ep_t object that matches
20963 + * the dwc_otg_pcd_ep object.
20964 + */
20965 +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
20966 +                                                 struct dwc_otg_pcd_ep *ep)
20967 +{
20968 +       struct cfi_ep *pcfiep = NULL;
20969 +       dwc_list_link_t *tmp;
20970 +
20971 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20972 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20973 +               if (pcfiep->ep == ep) {
20974 +                       return pcfiep;
20975 +               }
20976 +       }
20977 +       return NULL;
20978 +}
20979 +
20980 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
20981 +
20982 +#endif /* (__DWC_OTG_CFI_H__) */
20983 --- /dev/null
20984 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
20985 @@ -0,0 +1,7151 @@
20986 +/* ==========================================================================
20987 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
20988 + * $Revision: #191 $
20989 + * $Date: 2012/08/10 $
20990 + * $Change: 2047372 $
20991 + *
20992 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20993 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20994 + * otherwise expressly agreed to in writing between Synopsys and you.
20995 + *
20996 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20997 + * any End User Software License Agreement or Agreement for Licensed Product
20998 + * with Synopsys or any supplement thereto. You are permitted to use and
20999 + * redistribute this Software in source and binary forms, with or without
21000 + * modification, provided that redistributions of source code must retain this
21001 + * notice. You may not view, use, disclose, copy or distribute this file or
21002 + * any information contained herein except pursuant to this license grant from
21003 + * Synopsys. If you do not agree with this notice, including the disclaimer
21004 + * below, then you are not authorized to use the Software.
21005 + *
21006 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
21007 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21008 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21009 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
21010 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21011 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21012 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21013 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21014 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21015 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
21016 + * DAMAGE.
21017 + * ========================================================================== */
21018 +
21019 +/** @file
21020 + *
21021 + * The Core Interface Layer provides basic services for accessing and
21022 + * managing the DWC_otg hardware. These services are used by both the
21023 + * Host Controller Driver and the Peripheral Controller Driver.
21024 + *
21025 + * The CIL manages the memory map for the core so that the HCD and PCD
21026 + * don't have to do this separately. It also handles basic tasks like
21027 + * reading/writing the registers and data FIFOs in the controller.
21028 + * Some of the data access functions provide encapsulation of several
21029 + * operations required to perform a task, such as writing multiple
21030 + * registers to start a transfer. Finally, the CIL performs basic
21031 + * services that are not specific to either the host or device modes
21032 + * of operation. These services include management of the OTG Host
21033 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
21034 + * Diagnostic API is also provided to allow testing of the controller
21035 + * hardware.
21036 + *
21037 + * The Core Interface Layer has the following requirements:
21038 + * - Provides basic controller operations.
21039 + * - Minimal use of OS services.
21040 + * - The OS services used will be abstracted by using inline functions
21041 + *      or macros.
21042 + *
21043 + */
21044 +
21045 +#include "dwc_os.h"
21046 +#include "dwc_otg_regs.h"
21047 +#include "dwc_otg_cil.h"
21048 +
21049 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
21050 +
21051 +/**
21052 + * This function is called to initialize the DWC_otg CSR data
21053 + * structures. The register addresses in the device and host
21054 + * structures are initialized from the base address supplied by the
21055 + * caller. The calling function must make the OS calls to get the
21056 + * base address of the DWC_otg controller registers. The core_params
21057 + * argument holds the parameters that specify how the core should be
21058 + * configured.
21059 + *
21060 + * @param reg_base_addr Base address of DWC_otg core registers
21061 + *
21062 + */
21063 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
21064 +{
21065 +       dwc_otg_core_if_t *core_if = 0;
21066 +       dwc_otg_dev_if_t *dev_if = 0;
21067 +       dwc_otg_host_if_t *host_if = 0;
21068 +       uint8_t *reg_base = (uint8_t *) reg_base_addr;
21069 +       int i = 0;
21070 +
21071 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
21072 +
21073 +       core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));
21074 +
21075 +       if (core_if == NULL) {
21076 +               DWC_DEBUGPL(DBG_CIL,
21077 +                           "Allocation of dwc_otg_core_if_t failed\n");
21078 +               return 0;
21079 +       }
21080 +       core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
21081 +
21082 +       /*
21083 +        * Allocate the Device Mode structures.
21084 +        */
21085 +       dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));
21086 +
21087 +       if (dev_if == NULL) {
21088 +               DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
21089 +               DWC_FREE(core_if);
21090 +               return 0;
21091 +       }
21092 +
21093 +       dev_if->dev_global_regs =
21094 +           (dwc_otg_device_global_regs_t *) (reg_base +
21095 +                                             DWC_DEV_GLOBAL_REG_OFFSET);
21096 +
21097 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21098 +               dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
21099 +                   (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
21100 +                    (i * DWC_EP_REG_OFFSET));
21101 +
21102 +               dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
21103 +                   (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
21104 +                    (i * DWC_EP_REG_OFFSET));
21105 +               DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
21106 +                           i, &dev_if->in_ep_regs[i]->diepctl);
21107 +               DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
21108 +                           i, &dev_if->out_ep_regs[i]->doepctl);
21109 +       }
21110 +
21111 +       dev_if->speed = 0;      // unknown
21112 +
21113 +       core_if->dev_if = dev_if;
21114 +
21115 +       /*
21116 +        * Allocate the Host Mode structures.
21117 +        */
21118 +       host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));
21119 +
21120 +       if (host_if == NULL) {
21121 +               DWC_DEBUGPL(DBG_CIL,
21122 +                           "Allocation of dwc_otg_host_if_t failed\n");
21123 +               DWC_FREE(dev_if);
21124 +               DWC_FREE(core_if);
21125 +               return 0;
21126 +       }
21127 +
21128 +       host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
21129 +           (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
21130 +
21131 +       host_if->hprt0 =
21132 +           (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
21133 +
21134 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21135 +               host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
21136 +                   (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
21137 +                    (i * DWC_OTG_CHAN_REGS_OFFSET));
21138 +               DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
21139 +                           i, &host_if->hc_regs[i]->hcchar);
21140 +       }
21141 +
21142 +       host_if->num_host_channels = MAX_EPS_CHANNELS;
21143 +       core_if->host_if = host_if;
21144 +
21145 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21146 +               core_if->data_fifo[i] =
21147 +                   (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
21148 +                                 (i * DWC_OTG_DATA_FIFO_SIZE));
21149 +               DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",
21150 +                           i, (unsigned long)core_if->data_fifo[i]);
21151 +       }
21152 +
21153 +       core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
21154 +
21155 +       /* Initiate lx_state to L3 disconnected state */
21156 +       core_if->lx_state = DWC_OTG_L3;
21157 +       /*
21158 +        * Store the contents of the hardware configuration registers here for
21159 +        * easy access later.
21160 +        */
21161 +       core_if->hwcfg1.d32 =
21162 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
21163 +       core_if->hwcfg2.d32 =
21164 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
21165 +       core_if->hwcfg3.d32 =
21166 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
21167 +       core_if->hwcfg4.d32 =
21168 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
21169 +
21170 +       /* Force host mode to get HPTXFSIZ exact power on value */
21171 +       {
21172 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
21173 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21174 +               gusbcfg.b.force_host_mode = 1;
21175 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21176 +               dwc_mdelay(100);
21177 +               core_if->hptxfsiz.d32 =
21178 +               DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21179 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21180 +               gusbcfg.b.force_host_mode = 0;
21181 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21182 +               dwc_mdelay(100);
21183 +       }
21184 +
21185 +       DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
21186 +       DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
21187 +       DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
21188 +       DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
21189 +
21190 +       core_if->hcfg.d32 =
21191 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21192 +       core_if->dcfg.d32 =
21193 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21194 +
21195 +       DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
21196 +       DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
21197 +
21198 +       DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
21199 +       DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
21200 +       DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
21201 +       DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
21202 +                   core_if->hwcfg2.b.num_host_chan);
21203 +       DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
21204 +                   core_if->hwcfg2.b.nonperio_tx_q_depth);
21205 +       DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
21206 +                   core_if->hwcfg2.b.host_perio_tx_q_depth);
21207 +       DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
21208 +                   core_if->hwcfg2.b.dev_token_q_depth);
21209 +
21210 +       DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
21211 +                   core_if->hwcfg3.b.dfifo_depth);
21212 +       DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
21213 +                   core_if->hwcfg3.b.xfer_size_cntr_width);
21214 +
21215 +       /*
21216 +        * Set the SRP sucess bit for FS-I2c
21217 +        */
21218 +       core_if->srp_success = 0;
21219 +       core_if->srp_timer_started = 0;
21220 +
21221 +       /*
21222 +        * Create new workqueue and init works
21223 +        */
21224 +       core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
21225 +       if (core_if->wq_otg == 0) {
21226 +               DWC_WARN("DWC_WORKQ_ALLOC failed\n");
21227 +               DWC_FREE(host_if);
21228 +               DWC_FREE(dev_if);
21229 +               DWC_FREE(core_if);
21230 +               return 0;
21231 +       }
21232 +
21233 +       core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
21234 +
21235 +       DWC_PRINTF("Core Release: %x.%x%x%x\n",
21236 +                  (core_if->snpsid >> 12 & 0xF),
21237 +                  (core_if->snpsid >> 8 & 0xF),
21238 +                  (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
21239 +
21240 +       core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
21241 +                                            w_wakeup_detected, core_if);
21242 +       if (core_if->wkp_timer == 0) {
21243 +               DWC_WARN("DWC_TIMER_ALLOC failed\n");
21244 +               DWC_FREE(host_if);
21245 +               DWC_FREE(dev_if);
21246 +               DWC_WORKQ_FREE(core_if->wq_otg);
21247 +               DWC_FREE(core_if);
21248 +               return 0;
21249 +       }
21250 +
21251 +       if (dwc_otg_setup_params(core_if)) {
21252 +               DWC_WARN("Error while setting core params\n");
21253 +       }
21254 +
21255 +       core_if->hibernation_suspend = 0;
21256 +
21257 +       /** ADP initialization */
21258 +       dwc_otg_adp_init(core_if);
21259 +
21260 +       return core_if;
21261 +}
21262 +
21263 +/**
21264 + * This function frees the structures allocated by dwc_otg_cil_init().
21265 + *
21266 + * @param core_if The core interface pointer returned from
21267 + *               dwc_otg_cil_init().
21268 + *
21269 + */
21270 +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
21271 +{
21272 +       dctl_data_t dctl = {.d32 = 0 };
21273 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
21274 +
21275 +       /* Disable all interrupts */
21276 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);
21277 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
21278 +
21279 +       dctl.b.sftdiscon = 1;
21280 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
21281 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,
21282 +                                dctl.d32);
21283 +       }
21284 +
21285 +       if (core_if->wq_otg) {
21286 +               DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
21287 +               DWC_WORKQ_FREE(core_if->wq_otg);
21288 +       }
21289 +       if (core_if->dev_if) {
21290 +               DWC_FREE(core_if->dev_if);
21291 +       }
21292 +       if (core_if->host_if) {
21293 +               DWC_FREE(core_if->host_if);
21294 +       }
21295 +
21296 +       /** Remove ADP Stuff  */
21297 +       dwc_otg_adp_remove(core_if);
21298 +       if (core_if->core_params) {
21299 +               DWC_FREE(core_if->core_params);
21300 +       }
21301 +       if (core_if->wkp_timer) {
21302 +               DWC_TIMER_FREE(core_if->wkp_timer);
21303 +       }
21304 +       if (core_if->srp_timer) {
21305 +               DWC_TIMER_FREE(core_if->srp_timer);
21306 +       }
21307 +       DWC_FREE(core_if);
21308 +}
21309 +
21310 +/**
21311 + * This function enables the controller's Global Interrupt in the AHB Config
21312 + * register.
21313 + *
21314 + * @param core_if Programming view of DWC_otg controller.
21315 + */
21316 +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
21317 +{
21318 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21319 +       ahbcfg.b.glblintrmsk = 1;       /* Enable interrupts */
21320 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
21321 +}
21322 +
21323 +/**
21324 + * This function disables the controller's Global Interrupt in the AHB Config
21325 + * register.
21326 + *
21327 + * @param core_if Programming view of DWC_otg controller.
21328 + */
21329 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
21330 +{
21331 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21332 +       ahbcfg.b.glblintrmsk = 1;       /* Disable interrupts */
21333 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
21334 +}
21335 +
21336 +/**
21337 + * This function initializes the commmon interrupts, used in both
21338 + * device and host modes.
21339 + *
21340 + * @param core_if Programming view of the DWC_otg controller
21341 + *
21342 + */
21343 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
21344 +{
21345 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
21346 +       gintmsk_data_t intr_mask = {.d32 = 0 };
21347 +
21348 +       /* Clear any pending OTG Interrupts */
21349 +       DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);
21350 +
21351 +       /* Clear any pending interrupts */
21352 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
21353 +
21354 +       /*
21355 +        * Enable the interrupts in the GINTMSK.
21356 +        */
21357 +       intr_mask.b.modemismatch = 1;
21358 +       intr_mask.b.otgintr = 1;
21359 +
21360 +       if (!core_if->dma_enable) {
21361 +               intr_mask.b.rxstsqlvl = 1;
21362 +       }
21363 +
21364 +       intr_mask.b.conidstschng = 1;
21365 +       intr_mask.b.wkupintr = 1;
21366 +       intr_mask.b.disconnect = 0;
21367 +       intr_mask.b.usbsuspend = 1;
21368 +       intr_mask.b.sessreqintr = 1;
21369 +#ifdef CONFIG_USB_DWC_OTG_LPM
21370 +       if (core_if->core_params->lpm_enable) {
21371 +               intr_mask.b.lpmtranrcvd = 1;
21372 +       }
21373 +#endif
21374 +       DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
21375 +}
21376 +
21377 +/*
21378 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21379 + * Hibernation. This function is for exiting from Device mode hibernation by
21380 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21381 + * @param core_if Programming view of DWC_otg controller.
21382 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21383 + * @param reset - indicates whether resume is initiated by Reset.
21384 + */
21385 +int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
21386 +                                      int rem_wakeup, int reset)
21387 +{
21388 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21389 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
21390 +       dctl_data_t dctl = {.d32 = 0 };
21391 +
21392 +       int timeout = 2000;
21393 +
21394 +       if (!core_if->hibernation_suspend) {
21395 +               DWC_PRINTF("Already exited from Hibernation\n");
21396 +               return 1;
21397 +       }
21398 +
21399 +       DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);
21400 +       /* Switch-on voltage to the core */
21401 +       gpwrdn.b.pwrdnswtch = 1;
21402 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21403 +       dwc_udelay(10);
21404 +
21405 +       /* Reset core */
21406 +       gpwrdn.d32 = 0;
21407 +       gpwrdn.b.pwrdnrstn = 1;
21408 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21409 +       dwc_udelay(10);
21410 +
21411 +       /* Assert Restore signal */
21412 +       gpwrdn.d32 = 0;
21413 +       gpwrdn.b.restore = 1;
21414 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21415 +       dwc_udelay(10);
21416 +
21417 +       /* Disable power clamps */
21418 +       gpwrdn.d32 = 0;
21419 +       gpwrdn.b.pwrdnclmp = 1;
21420 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21421 +
21422 +       if (rem_wakeup) {
21423 +               dwc_udelay(70);
21424 +       }
21425 +
21426 +       /* Deassert Reset core */
21427 +       gpwrdn.d32 = 0;
21428 +       gpwrdn.b.pwrdnrstn = 1;
21429 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21430 +       dwc_udelay(10);
21431 +
21432 +       /* Disable PMU interrupt */
21433 +       gpwrdn.d32 = 0;
21434 +       gpwrdn.b.pmuintsel = 1;
21435 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21436 +
21437 +       /* Mask interrupts from gpwrdn */
21438 +       gpwrdn.d32 = 0;
21439 +       gpwrdn.b.connect_det_msk = 1;
21440 +       gpwrdn.b.srp_det_msk = 1;
21441 +       gpwrdn.b.disconn_det_msk = 1;
21442 +       gpwrdn.b.rst_det_msk = 1;
21443 +       gpwrdn.b.lnstchng_msk = 1;
21444 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21445 +
21446 +       /* Indicates that we are going out from hibernation */
21447 +       core_if->hibernation_suspend = 0;
21448 +
21449 +       /*
21450 +        * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1
21451 +        * indicates restore from remote_wakeup
21452 +        */
21453 +       restore_essential_regs(core_if, rem_wakeup, 0);
21454 +
21455 +       /*
21456 +        * Wait a little for seeing new value of variable hibernation_suspend if
21457 +        * Restore done interrupt received before polling
21458 +        */
21459 +       dwc_udelay(10);
21460 +
21461 +       if (core_if->hibernation_suspend == 0) {
21462 +               /*
21463 +                * Wait For Restore_done Interrupt. This mechanism of polling the
21464 +                * interrupt is introduced to avoid any possible race conditions
21465 +                */
21466 +               do {
21467 +                       gintsts_data_t gintsts;
21468 +                       gintsts.d32 =
21469 +                           DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21470 +                       if (gintsts.b.restoredone) {
21471 +                               gintsts.d32 = 0;
21472 +                               gintsts.b.restoredone = 1;
21473 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
21474 +                                               gintsts, gintsts.d32);
21475 +                               DWC_PRINTF("Restore Done Interrupt seen\n");
21476 +                               break;
21477 +                       }
21478 +                       dwc_udelay(10);
21479 +               } while (--timeout);
21480 +               if (!timeout) {
21481 +                       DWC_PRINTF("Restore Done interrupt wasn't generated here\n");
21482 +               }
21483 +       }
21484 +       /* Clear all pending interupts */
21485 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21486 +
21487 +       /* De-assert Restore */
21488 +       gpwrdn.d32 = 0;
21489 +       gpwrdn.b.restore = 1;
21490 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21491 +       dwc_udelay(10);
21492 +
21493 +       if (!rem_wakeup) {
21494 +               pcgcctl.d32 = 0;
21495 +               pcgcctl.b.rstpdwnmodule = 1;
21496 +               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
21497 +       }
21498 +
21499 +       /* Restore GUSBCFG and DCFG */
21500 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21501 +                       core_if->gr_backup->gusbcfg_local);
21502 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
21503 +                       core_if->dr_backup->dcfg);
21504 +
21505 +       /* De-assert Wakeup Logic */
21506 +       gpwrdn.d32 = 0;
21507 +       gpwrdn.b.pmuactv = 1;
21508 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21509 +       dwc_udelay(10);
21510 +
21511 +       if (!rem_wakeup) {
21512 +               /* Set Device programming done bit */
21513 +               dctl.b.pwronprgdone = 1;
21514 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
21515 +       } else {
21516 +               /* Start Remote Wakeup Signaling */
21517 +               dctl.d32 = core_if->dr_backup->dctl;
21518 +               dctl.b.rmtwkupsig = 1;
21519 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
21520 +       }
21521 +
21522 +       dwc_mdelay(2);
21523 +       /* Clear all pending interupts */
21524 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21525 +
21526 +       /* Restore global registers */
21527 +       dwc_otg_restore_global_regs(core_if);
21528 +       /* Restore device global registers */
21529 +       dwc_otg_restore_dev_regs(core_if, rem_wakeup);
21530 +
21531 +       if (rem_wakeup) {
21532 +               dwc_mdelay(7);
21533 +               dctl.d32 = 0;
21534 +               dctl.b.rmtwkupsig = 1;
21535 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
21536 +       }
21537 +
21538 +       core_if->hibernation_suspend = 0;
21539 +       /* The core will be in ON STATE */
21540 +       core_if->lx_state = DWC_OTG_L0;
21541 +       DWC_PRINTF("Hibernation recovery completes here\n");
21542 +
21543 +       return 1;
21544 +}
21545 +
21546 +/*
21547 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21548 + * Hibernation. This function is for exiting from Host mode hibernation by
21549 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21550 + * @param core_if Programming view of DWC_otg controller.
21551 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21552 + * @param reset - indicates whether resume is initiated by Reset.
21553 + */
21554 +int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
21555 +                                    int rem_wakeup, int reset)
21556 +{
21557 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21558 +       hprt0_data_t hprt0 = {.d32 = 0 };
21559 +
21560 +       int timeout = 2000;
21561 +
21562 +       DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);
21563 +       /* Switch-on voltage to the core */
21564 +       gpwrdn.b.pwrdnswtch = 1;
21565 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21566 +       dwc_udelay(10);
21567 +
21568 +       /* Reset core */
21569 +       gpwrdn.d32 = 0;
21570 +       gpwrdn.b.pwrdnrstn = 1;
21571 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21572 +       dwc_udelay(10);
21573 +
21574 +       /* Assert Restore signal */
21575 +       gpwrdn.d32 = 0;
21576 +       gpwrdn.b.restore = 1;
21577 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21578 +       dwc_udelay(10);
21579 +
21580 +       /* Disable power clamps */
21581 +       gpwrdn.d32 = 0;
21582 +       gpwrdn.b.pwrdnclmp = 1;
21583 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21584 +
21585 +       if (!rem_wakeup) {
21586 +               dwc_udelay(50);
21587 +       }
21588 +
21589 +       /* Deassert Reset core */
21590 +       gpwrdn.d32 = 0;
21591 +       gpwrdn.b.pwrdnrstn = 1;
21592 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21593 +       dwc_udelay(10);
21594 +
21595 +       /* Disable PMU interrupt */
21596 +       gpwrdn.d32 = 0;
21597 +       gpwrdn.b.pmuintsel = 1;
21598 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21599 +
21600 +       gpwrdn.d32 = 0;
21601 +       gpwrdn.b.connect_det_msk = 1;
21602 +       gpwrdn.b.srp_det_msk = 1;
21603 +       gpwrdn.b.disconn_det_msk = 1;
21604 +       gpwrdn.b.rst_det_msk = 1;
21605 +       gpwrdn.b.lnstchng_msk = 1;
21606 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21607 +
21608 +       /* Indicates that we are going out from hibernation */
21609 +       core_if->hibernation_suspend = 0;
21610 +
21611 +       /* Set Restore Essential Regs bit in PCGCCTL register */
21612 +       restore_essential_regs(core_if, rem_wakeup, 1);
21613 +
21614 +       /* Wait a little for seeing new value of variable hibernation_suspend if
21615 +        * Restore done interrupt received before polling */
21616 +       dwc_udelay(10);
21617 +
21618 +       if (core_if->hibernation_suspend == 0) {
21619 +               /* Wait For Restore_done Interrupt. This mechanism of polling the
21620 +                * interrupt is introduced to avoid any possible race conditions
21621 +                */
21622 +               do {
21623 +                       gintsts_data_t gintsts;
21624 +                       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21625 +                       if (gintsts.b.restoredone) {
21626 +                               gintsts.d32 = 0;
21627 +                               gintsts.b.restoredone = 1;
21628 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
21629 +                               DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");
21630 +                               break;
21631 +                       }
21632 +                       dwc_udelay(10);
21633 +               } while (--timeout);
21634 +               if (!timeout) {
21635 +                       DWC_WARN("Restore Done interrupt wasn't generated\n");
21636 +               }
21637 +       }
21638 +
21639 +       /* Set the flag's value to 0 again after receiving restore done interrupt */
21640 +       core_if->hibernation_suspend = 0;
21641 +
21642 +       /* This step is not described in functional spec but if not wait for this
21643 +        * delay, mismatch interrupts occurred because just after restore core is
21644 +        * in Device mode(gintsts.curmode == 0) */
21645 +       dwc_mdelay(100);
21646 +
21647 +       /* Clear all pending interrupts */
21648 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21649 +
21650 +       /* De-assert Restore */
21651 +       gpwrdn.d32 = 0;
21652 +       gpwrdn.b.restore = 1;
21653 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21654 +       dwc_udelay(10);
21655 +
21656 +       /* Restore GUSBCFG and HCFG */
21657 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21658 +                       core_if->gr_backup->gusbcfg_local);
21659 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
21660 +                       core_if->hr_backup->hcfg_local);
21661 +
21662 +       /* De-assert Wakeup Logic */
21663 +       gpwrdn.d32 = 0;
21664 +       gpwrdn.b.pmuactv = 1;
21665 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21666 +       dwc_udelay(10);
21667 +
21668 +       /* Start the Resume operation by programming HPRT0 */
21669 +       hprt0.d32 = core_if->hr_backup->hprt0_local;
21670 +       hprt0.b.prtpwr = 1;
21671 +       hprt0.b.prtena = 0;
21672 +       hprt0.b.prtsusp = 0;
21673 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21674 +
21675 +       DWC_PRINTF("Resume Starts Now\n");
21676 +       if (!reset) {           // Indicates it is Resume Operation
21677 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21678 +               hprt0.b.prtres = 1;
21679 +               hprt0.b.prtpwr = 1;
21680 +               hprt0.b.prtena = 0;
21681 +               hprt0.b.prtsusp = 0;
21682 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21683 +
21684 +               if (!rem_wakeup)
21685 +                       hprt0.b.prtres = 0;
21686 +               /* Wait for Resume time and then program HPRT again */
21687 +               dwc_mdelay(100);
21688 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21689 +
21690 +       } else {                // Indicates it is Reset Operation
21691 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21692 +               hprt0.b.prtrst = 1;
21693 +               hprt0.b.prtpwr = 1;
21694 +               hprt0.b.prtena = 0;
21695 +               hprt0.b.prtsusp = 0;
21696 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21697 +               /* Wait for Reset time and then program HPRT again */
21698 +               dwc_mdelay(60);
21699 +               hprt0.b.prtrst = 0;
21700 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21701 +       }
21702 +       /* Clear all interrupt status */
21703 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
21704 +       hprt0.b.prtconndet = 1;
21705 +       hprt0.b.prtenchng = 1;
21706 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21707 +
21708 +       /* Clear all pending interupts */
21709 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21710 +
21711 +       /* Restore global registers */
21712 +       dwc_otg_restore_global_regs(core_if);
21713 +       /* Restore host global registers */
21714 +       dwc_otg_restore_host_regs(core_if, reset);
21715 +
21716 +       /* The core will be in ON STATE */
21717 +       core_if->lx_state = DWC_OTG_L0;
21718 +       DWC_PRINTF("Hibernation recovery is complete here\n");
21719 +       return 0;
21720 +}
21721 +
21722 +/** Saves some register values into system memory. */
21723 +int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)
21724 +{
21725 +       struct dwc_otg_global_regs_backup *gr;
21726 +       int i;
21727 +
21728 +       gr = core_if->gr_backup;
21729 +       if (!gr) {
21730 +               gr = DWC_ALLOC(sizeof(*gr));
21731 +               if (!gr) {
21732 +                       return -DWC_E_NO_MEMORY;
21733 +               }
21734 +               core_if->gr_backup = gr;
21735 +       }
21736 +
21737 +       gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
21738 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21739 +       gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
21740 +       gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21741 +       gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
21742 +       gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
21743 +       gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21744 +#ifdef CONFIG_USB_DWC_OTG_LPM
21745 +       gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
21746 +#endif
21747 +       gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);
21748 +       gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);
21749 +       gr->gdfifocfg_local =
21750 +           DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);
21751 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21752 +               gr->dtxfsiz_local[i] =
21753 +                   DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));
21754 +       }
21755 +
21756 +       DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");
21757 +       DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl   = %08x\n", gr->gotgctl_local);
21758 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21759 +       DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg   = %08x\n", gr->gahbcfg_local);
21760 +       DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg   = %08x\n", gr->gusbcfg_local);
21761 +       DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz   = %08x\n", gr->grxfsiz_local);
21762 +       DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",
21763 +                   gr->gnptxfsiz_local);
21764 +       DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz  = %08x\n",
21765 +                   gr->hptxfsiz_local);
21766 +#ifdef CONFIG_USB_DWC_OTG_LPM
21767 +       DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg   = %08x\n", gr->glpmcfg_local);
21768 +#endif
21769 +       DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl   = %08x\n", gr->gi2cctl_local);
21770 +       DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl   = %08x\n", gr->pcgcctl_local);
21771 +       DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg   = %08x\n",gr->gdfifocfg_local);
21772 +
21773 +       return 0;
21774 +}
21775 +
21776 +/** Saves GINTMSK register before setting the msk bits. */
21777 +int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)
21778 +{
21779 +       struct dwc_otg_global_regs_backup *gr;
21780 +
21781 +       gr = core_if->gr_backup;
21782 +       if (!gr) {
21783 +               gr = DWC_ALLOC(sizeof(*gr));
21784 +               if (!gr) {
21785 +                       return -DWC_E_NO_MEMORY;
21786 +               }
21787 +               core_if->gr_backup = gr;
21788 +       }
21789 +
21790 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21791 +
21792 +       DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");
21793 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21794 +
21795 +       return 0;
21796 +}
21797 +
21798 +int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)
21799 +{
21800 +       struct dwc_otg_dev_regs_backup *dr;
21801 +       int i;
21802 +
21803 +       dr = core_if->dr_backup;
21804 +       if (!dr) {
21805 +               dr = DWC_ALLOC(sizeof(*dr));
21806 +               if (!dr) {
21807 +                       return -DWC_E_NO_MEMORY;
21808 +               }
21809 +               core_if->dr_backup = dr;
21810 +       }
21811 +
21812 +       dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21813 +       dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
21814 +       dr->daintmsk =
21815 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
21816 +       dr->diepmsk =
21817 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);
21818 +       dr->doepmsk =
21819 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);
21820 +
21821 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21822 +               dr->diepctl[i] =
21823 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
21824 +               dr->dieptsiz[i] =
21825 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);
21826 +               dr->diepdma[i] =
21827 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
21828 +       }
21829 +
21830 +       DWC_DEBUGPL(DBG_ANY,
21831 +                   "=============Backing Host registers==============\n");
21832 +       DWC_DEBUGPL(DBG_ANY, "Backed up dcfg            = %08x\n", dr->dcfg);
21833 +       DWC_DEBUGPL(DBG_ANY, "Backed up dctl        = %08x\n", dr->dctl);
21834 +       DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk            = %08x\n",
21835 +                   dr->daintmsk);
21836 +       DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk        = %08x\n", dr->diepmsk);
21837 +       DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk        = %08x\n", dr->doepmsk);
21838 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21839 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d]        = %08x\n", i,
21840 +                           dr->diepctl[i]);
21841 +               DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d]        = %08x\n",
21842 +                           i, dr->dieptsiz[i]);
21843 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d]        = %08x\n", i,
21844 +                           dr->diepdma[i]);
21845 +       }
21846 +
21847 +       return 0;
21848 +}
21849 +
21850 +int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)
21851 +{
21852 +       struct dwc_otg_host_regs_backup *hr;
21853 +       int i;
21854 +
21855 +       hr = core_if->hr_backup;
21856 +       if (!hr) {
21857 +               hr = DWC_ALLOC(sizeof(*hr));
21858 +               if (!hr) {
21859 +                       return -DWC_E_NO_MEMORY;
21860 +               }
21861 +               core_if->hr_backup = hr;
21862 +       }
21863 +
21864 +       hr->hcfg_local =
21865 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21866 +       hr->haintmsk_local =
21867 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
21868 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21869 +               hr->hcintmsk_local[i] =
21870 +                   DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);
21871 +       }
21872 +       hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);
21873 +       hr->hfir_local =
21874 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
21875 +
21876 +       DWC_DEBUGPL(DBG_ANY,
21877 +                   "=============Backing Host registers===============\n");
21878 +       DWC_DEBUGPL(DBG_ANY, "Backed up hcfg            = %08x\n",
21879 +                   hr->hcfg_local);
21880 +       DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);
21881 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21882 +               DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,
21883 +                           hr->hcintmsk_local[i]);
21884 +       }
21885 +       DWC_DEBUGPL(DBG_ANY, "Backed up hprt0           = %08x\n",
21886 +                   hr->hprt0_local);
21887 +       DWC_DEBUGPL(DBG_ANY, "Backed up hfir           = %08x\n",
21888 +                   hr->hfir_local);
21889 +
21890 +       return 0;
21891 +}
21892 +
21893 +int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)
21894 +{
21895 +       struct dwc_otg_global_regs_backup *gr;
21896 +       int i;
21897 +
21898 +       gr = core_if->gr_backup;
21899 +       if (!gr) {
21900 +               return -DWC_E_INVALID;
21901 +       }
21902 +
21903 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
21904 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
21905 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
21906 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);
21907 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);
21908 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,
21909 +                       gr->gnptxfsiz_local);
21910 +       DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,
21911 +                       gr->hptxfsiz_local);
21912 +       DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,
21913 +                       gr->gdfifocfg_local);
21914 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21915 +               DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],
21916 +                               gr->dtxfsiz_local[i]);
21917 +       }
21918 +
21919 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21920 +       DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);
21921 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,
21922 +                       (gr->gahbcfg_local));
21923 +       return 0;
21924 +}
21925 +
21926 +int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)
21927 +{
21928 +       struct dwc_otg_dev_regs_backup *dr;
21929 +       int i;
21930 +
21931 +       dr = core_if->dr_backup;
21932 +
21933 +       if (!dr) {
21934 +               return -DWC_E_INVALID;
21935 +       }
21936 +
21937 +       if (!rem_wakeup) {
21938 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
21939 +                               dr->dctl);
21940 +       }
21941 +
21942 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
21943 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
21944 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
21945 +
21946 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21947 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
21948 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
21949 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);
21950 +       }
21951 +
21952 +       return 0;
21953 +}
21954 +
21955 +int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)
21956 +{
21957 +       struct dwc_otg_host_regs_backup *hr;
21958 +       int i;
21959 +       hr = core_if->hr_backup;
21960 +
21961 +       if (!hr) {
21962 +               return -DWC_E_INVALID;
21963 +       }
21964 +
21965 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);
21966 +       //if (!reset)
21967 +       //{
21968 +       //      DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);
21969 +       //}
21970 +
21971 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,
21972 +                       hr->haintmsk_local);
21973 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21974 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,
21975 +                               hr->hcintmsk_local[i]);
21976 +       }
21977 +
21978 +       return 0;
21979 +}
21980 +
21981 +int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)
21982 +{
21983 +       struct dwc_otg_global_regs_backup *gr;
21984 +
21985 +       gr = core_if->gr_backup;
21986 +
21987 +       /* Restore values for LPM and I2C */
21988 +#ifdef CONFIG_USB_DWC_OTG_LPM
21989 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);
21990 +#endif
21991 +       DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);
21992 +
21993 +       return 0;
21994 +}
21995 +
21996 +int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)
21997 +{
21998 +       struct dwc_otg_global_regs_backup *gr;
21999 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
22000 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
22001 +       gusbcfg_data_t gusbcfg = {.d32 = 0 };
22002 +       gintmsk_data_t gintmsk = {.d32 = 0 };
22003 +
22004 +       /* Restore LPM and I2C registers */
22005 +       restore_lpm_i2c_regs(core_if);
22006 +
22007 +       /* Set PCGCCTL to 0 */
22008 +       DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);
22009 +
22010 +       gr = core_if->gr_backup;
22011 +       /* Load restore values for [31:14] bits */
22012 +       DWC_WRITE_REG32(core_if->pcgcctl,
22013 +                       ((gr->pcgcctl_local & 0xffffc000) | 0x00020000));
22014 +
22015 +       /* Umnask global Interrupt in GAHBCFG and restore it */
22016 +       gahbcfg.d32 = gr->gahbcfg_local;
22017 +       gahbcfg.b.glblintrmsk = 1;
22018 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
22019 +
22020 +       /* Clear all pending interupts */
22021 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
22022 +
22023 +       /* Unmask restore done interrupt */
22024 +       gintmsk.b.restoredone = 1;
22025 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
22026 +
22027 +       /* Restore GUSBCFG and HCFG/DCFG */
22028 +       gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;
22029 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
22030 +
22031 +       if (is_host) {
22032 +               hcfg_data_t hcfg = {.d32 = 0 };
22033 +               hcfg.d32 = core_if->hr_backup->hcfg_local;
22034 +               DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
22035 +                               hcfg.d32);
22036 +
22037 +               /* Load restore values for [31:14] bits */
22038 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22039 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22040 +
22041 +               if (rmode)
22042 +                       pcgcctl.b.restoremode = 1;
22043 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22044 +               dwc_udelay(10);
22045 +
22046 +               /* Load restore values for [31:14] bits and set EssRegRestored bit */
22047 +               pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;
22048 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22049 +               pcgcctl.b.ess_reg_restored = 1;
22050 +               if (rmode)
22051 +                       pcgcctl.b.restoremode = 1;
22052 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22053 +       } else {
22054 +               dcfg_data_t dcfg = {.d32 = 0 };
22055 +               dcfg.d32 = core_if->dr_backup->dcfg;
22056 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22057 +
22058 +               /* Load restore values for [31:14] bits */
22059 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22060 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22061 +               if (!rmode) {
22062 +                       pcgcctl.d32 |= 0x208;
22063 +               }
22064 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22065 +               dwc_udelay(10);
22066 +
22067 +               /* Load restore values for [31:14] bits */
22068 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22069 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22070 +               pcgcctl.b.ess_reg_restored = 1;
22071 +               if (!rmode)
22072 +                       pcgcctl.d32 |= 0x208;
22073 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22074 +       }
22075 +
22076 +       return 0;
22077 +}
22078 +
22079 +/**
22080 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
22081 + * type.
22082 + */
22083 +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
22084 +{
22085 +       uint32_t val;
22086 +       hcfg_data_t hcfg;
22087 +
22088 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22089 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22090 +            (core_if->core_params->ulpi_fs_ls)) ||
22091 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22092 +               /* Full speed PHY */
22093 +               val = DWC_HCFG_48_MHZ;
22094 +       } else {
22095 +               /* High speed PHY running at full speed or high speed */
22096 +               val = DWC_HCFG_30_60_MHZ;
22097 +       }
22098 +
22099 +       DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
22100 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
22101 +       hcfg.b.fslspclksel = val;
22102 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
22103 +}
22104 +
22105 +/**
22106 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
22107 + * and the enumeration speed of the device.
22108 + */
22109 +static void init_devspd(dwc_otg_core_if_t * core_if)
22110 +{
22111 +       uint32_t val;
22112 +       dcfg_data_t dcfg;
22113 +
22114 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22115 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22116 +            (core_if->core_params->ulpi_fs_ls)) ||
22117 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22118 +               /* Full speed PHY */
22119 +               val = 0x3;
22120 +       } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
22121 +               /* High speed PHY running at full speed */
22122 +               val = 0x1;
22123 +       } else {
22124 +               /* High speed PHY running at high speed */
22125 +               val = 0x0;
22126 +       }
22127 +
22128 +       DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
22129 +
22130 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
22131 +       dcfg.b.devspd = val;
22132 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22133 +}
22134 +
22135 +/**
22136 + * This function calculates the number of IN EPS
22137 + * using GHWCFG1 and GHWCFG2 registers values
22138 + *
22139 + * @param core_if Programming view of the DWC_otg controller
22140 + */
22141 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
22142 +{
22143 +       uint32_t num_in_eps = 0;
22144 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22145 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
22146 +       uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
22147 +       int i;
22148 +
22149 +       for (i = 0; i < num_eps; ++i) {
22150 +               if (!(hwcfg1 & 0x1))
22151 +                       num_in_eps++;
22152 +
22153 +               hwcfg1 >>= 2;
22154 +       }
22155 +
22156 +       if (core_if->hwcfg4.b.ded_fifo_en) {
22157 +               num_in_eps =
22158 +                   (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
22159 +       }
22160 +
22161 +       return num_in_eps;
22162 +}
22163 +
22164 +/**
22165 + * This function calculates the number of OUT EPS
22166 + * using GHWCFG1 and GHWCFG2 registers values
22167 + *
22168 + * @param core_if Programming view of the DWC_otg controller
22169 + */
22170 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
22171 +{
22172 +       uint32_t num_out_eps = 0;
22173 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22174 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
22175 +       int i;
22176 +
22177 +       for (i = 0; i < num_eps; ++i) {
22178 +               if (!(hwcfg1 & 0x1))
22179 +                       num_out_eps++;
22180 +
22181 +               hwcfg1 >>= 2;
22182 +       }
22183 +       return num_out_eps;
22184 +}
22185 +
22186 +/**
22187 + * This function initializes the DWC_otg controller registers and
22188 + * prepares the core for device mode or host mode operation.
22189 + *
22190 + * @param core_if Programming view of the DWC_otg controller
22191 + *
22192 + */
22193 +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
22194 +{
22195 +       int i = 0;
22196 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22197 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22198 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
22199 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
22200 +       gi2cctl_data_t i2cctl = {.d32 = 0 };
22201 +
22202 +       DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
22203 +                    core_if, global_regs);
22204 +
22205 +       /* Common Initialization */
22206 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22207 +
22208 +       /* Program the ULPI External VBUS bit if needed */
22209 +       usbcfg.b.ulpi_ext_vbus_drv =
22210 +           (core_if->core_params->phy_ulpi_ext_vbus ==
22211 +            DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
22212 +
22213 +       /* Set external TS Dline pulsing */
22214 +       usbcfg.b.term_sel_dl_pulse =
22215 +           (core_if->core_params->ts_dline == 1) ? 1 : 0;
22216 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22217 +
22218 +       /* Reset the Controller */
22219 +       dwc_otg_core_reset(core_if);
22220 +
22221 +       core_if->adp_enable = core_if->core_params->adp_supp_enable;
22222 +       core_if->power_down = core_if->core_params->power_down;
22223 +       core_if->otg_sts = 0;
22224 +
22225 +       /* Initialize parameters from Hardware configuration registers. */
22226 +       dev_if->num_in_eps = calc_num_in_eps(core_if);
22227 +       dev_if->num_out_eps = calc_num_out_eps(core_if);
22228 +
22229 +       DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
22230 +                   core_if->hwcfg4.b.num_dev_perio_in_ep);
22231 +
22232 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22233 +               dev_if->perio_tx_fifo_size[i] =
22234 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22235 +               DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
22236 +                           i, dev_if->perio_tx_fifo_size[i]);
22237 +       }
22238 +
22239 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22240 +               dev_if->tx_fifo_size[i] =
22241 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22242 +               DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
22243 +                           i, dev_if->tx_fifo_size[i]);
22244 +       }
22245 +
22246 +       core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
22247 +       core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
22248 +       core_if->nperio_tx_fifo_size =
22249 +           DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
22250 +
22251 +       DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
22252 +       DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
22253 +       DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
22254 +                   core_if->nperio_tx_fifo_size);
22255 +
22256 +       /* This programming sequence needs to happen in FS mode before any other
22257 +        * programming occurs */
22258 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
22259 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22260 +               /* If FS mode with FS PHY */
22261 +
22262 +               /* core_init() is now called on every switch so only call the
22263 +                * following for the first time through. */
22264 +               if (!core_if->phy_init_done) {
22265 +                       core_if->phy_init_done = 1;
22266 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
22267 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22268 +                       usbcfg.b.physel = 1;
22269 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22270 +
22271 +                       /* Reset after a PHY select */
22272 +                       dwc_otg_core_reset(core_if);
22273 +               }
22274 +
22275 +               /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also
22276 +                * do this on HNP Dev/Host mode switches (done in dev_init and
22277 +                * host_init). */
22278 +               if (dwc_otg_is_host_mode(core_if)) {
22279 +                       init_fslspclksel(core_if);
22280 +               } else {
22281 +                       init_devspd(core_if);
22282 +               }
22283 +
22284 +               if (core_if->core_params->i2c_enable) {
22285 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
22286 +                       /* Program GUSBCFG.OtgUtmifsSel to I2C */
22287 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22288 +                       usbcfg.b.otgutmifssel = 1;
22289 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22290 +
22291 +                       /* Program GI2CCTL.I2CEn */
22292 +                       i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);
22293 +                       i2cctl.b.i2cdevaddr = 1;
22294 +                       i2cctl.b.i2cen = 0;
22295 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22296 +                       i2cctl.b.i2cen = 1;
22297 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22298 +               }
22299 +
22300 +       } /* endif speed == DWC_SPEED_PARAM_FULL */
22301 +       else {
22302 +               /* High speed PHY. */
22303 +               if (!core_if->phy_init_done) {
22304 +                       core_if->phy_init_done = 1;
22305 +                       /* HS PHY parameters.  These parameters are preserved
22306 +                        * during soft reset so only program the first time.  Do
22307 +                        * a soft reset immediately after setting phyif.  */
22308 +
22309 +                       if (core_if->core_params->phy_type == 2) {
22310 +                               /* ULPI interface */
22311 +                               usbcfg.b.ulpi_utmi_sel = 1;
22312 +                               usbcfg.b.phyif = 0;
22313 +                               usbcfg.b.ddrsel =
22314 +                                   core_if->core_params->phy_ulpi_ddr;
22315 +                       } else if (core_if->core_params->phy_type == 1) {
22316 +                               /* UTMI+ interface */
22317 +                               usbcfg.b.ulpi_utmi_sel = 0;
22318 +                               if (core_if->core_params->phy_utmi_width == 16) {
22319 +                                       usbcfg.b.phyif = 1;
22320 +
22321 +                               } else {
22322 +                                       usbcfg.b.phyif = 0;
22323 +                               }
22324 +                       } else {
22325 +                               DWC_ERROR("FS PHY TYPE\n");
22326 +                       }
22327 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22328 +                       /* Reset after setting the PHY parameters */
22329 +                       dwc_otg_core_reset(core_if);
22330 +               }
22331 +       }
22332 +
22333 +       if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
22334 +           (core_if->hwcfg2.b.fs_phy_type == 1) &&
22335 +           (core_if->core_params->ulpi_fs_ls)) {
22336 +               DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
22337 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22338 +               usbcfg.b.ulpi_fsls = 1;
22339 +               usbcfg.b.ulpi_clk_sus_m = 1;
22340 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22341 +       } else {
22342 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22343 +               usbcfg.b.ulpi_fsls = 0;
22344 +               usbcfg.b.ulpi_clk_sus_m = 0;
22345 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22346 +       }
22347 +
22348 +       /* Program the GAHBCFG Register. */
22349 +       switch (core_if->hwcfg2.b.architecture) {
22350 +
22351 +       case DWC_SLAVE_ONLY_ARCH:
22352 +               DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
22353 +               ahbcfg.b.nptxfemplvl_txfemplvl =
22354 +                   DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22355 +               ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22356 +               core_if->dma_enable = 0;
22357 +               core_if->dma_desc_enable = 0;
22358 +               break;
22359 +
22360 +       case DWC_EXT_DMA_ARCH:
22361 +               DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
22362 +               {
22363 +                       uint8_t brst_sz = core_if->core_params->dma_burst_size;
22364 +                       ahbcfg.b.hburstlen = 0;
22365 +                       while (brst_sz > 1) {
22366 +                               ahbcfg.b.hburstlen++;
22367 +                               brst_sz >>= 1;
22368 +                       }
22369 +               }
22370 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22371 +               core_if->dma_desc_enable =
22372 +                   (core_if->core_params->dma_desc_enable != 0);
22373 +               break;
22374 +
22375 +       case DWC_INT_DMA_ARCH:
22376 +               DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
22377 +               /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
22378 +                 Host mode ISOC in issue fix - vahrama */
22379 +               /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */
22380 +               ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;
22381 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22382 +               core_if->dma_desc_enable =
22383 +                   (core_if->core_params->dma_desc_enable != 0);
22384 +               break;
22385 +
22386 +       }
22387 +       if (core_if->dma_enable) {
22388 +               if (core_if->dma_desc_enable) {
22389 +                       DWC_PRINTF("Using Descriptor DMA mode\n");
22390 +               } else {
22391 +                       DWC_PRINTF("Using Buffer DMA mode\n");
22392 +
22393 +               }
22394 +       } else {
22395 +               DWC_PRINTF("Using Slave mode\n");
22396 +               core_if->dma_desc_enable = 0;
22397 +       }
22398 +
22399 +       if (core_if->core_params->ahb_single) {
22400 +               ahbcfg.b.ahbsingle = 1;
22401 +       }
22402 +
22403 +       ahbcfg.b.dmaenable = core_if->dma_enable;
22404 +       DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
22405 +
22406 +       core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
22407 +
22408 +       core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
22409 +       core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
22410 +       DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
22411 +                  ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
22412 +       DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
22413 +                  ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
22414 +
22415 +       /*
22416 +        * Program the GUSBCFG register.
22417 +        */
22418 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22419 +
22420 +       switch (core_if->hwcfg2.b.op_mode) {
22421 +       case DWC_MODE_HNP_SRP_CAPABLE:
22422 +               usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
22423 +                                  DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
22424 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22425 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22426 +               break;
22427 +
22428 +       case DWC_MODE_SRP_ONLY_CAPABLE:
22429 +               usbcfg.b.hnpcap = 0;
22430 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22431 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22432 +               break;
22433 +
22434 +       case DWC_MODE_NO_HNP_SRP_CAPABLE:
22435 +               usbcfg.b.hnpcap = 0;
22436 +               usbcfg.b.srpcap = 0;
22437 +               break;
22438 +
22439 +       case DWC_MODE_SRP_CAPABLE_DEVICE:
22440 +               usbcfg.b.hnpcap = 0;
22441 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22442 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22443 +               break;
22444 +
22445 +       case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
22446 +               usbcfg.b.hnpcap = 0;
22447 +               usbcfg.b.srpcap = 0;
22448 +               break;
22449 +
22450 +       case DWC_MODE_SRP_CAPABLE_HOST:
22451 +               usbcfg.b.hnpcap = 0;
22452 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22453 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22454 +               break;
22455 +
22456 +       case DWC_MODE_NO_SRP_CAPABLE_HOST:
22457 +               usbcfg.b.hnpcap = 0;
22458 +               usbcfg.b.srpcap = 0;
22459 +               break;
22460 +       }
22461 +
22462 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22463 +
22464 +#ifdef CONFIG_USB_DWC_OTG_LPM
22465 +       if (core_if->core_params->lpm_enable) {
22466 +               glpmcfg_data_t lpmcfg = {.d32 = 0 };
22467 +
22468 +               /* To enable LPM support set lpm_cap_en bit */
22469 +               lpmcfg.b.lpm_cap_en = 1;
22470 +
22471 +               /* Make AppL1Res ACK */
22472 +               lpmcfg.b.appl_resp = 1;
22473 +
22474 +               /* Retry 3 times */
22475 +               lpmcfg.b.retry_count = 3;
22476 +
22477 +               DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,
22478 +                                0, lpmcfg.d32);
22479 +
22480 +       }
22481 +#endif
22482 +       if (core_if->core_params->ic_usb_cap) {
22483 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
22484 +               gusbcfg.b.ic_usb_cap = 1;
22485 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,
22486 +                                0, gusbcfg.d32);
22487 +       }
22488 +       {
22489 +               gotgctl_data_t gotgctl = {.d32 = 0 };
22490 +               gotgctl.b.otgver = core_if->core_params->otg_ver;
22491 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,
22492 +                                gotgctl.d32);
22493 +               /* Set OTG version supported */
22494 +               core_if->otg_ver = core_if->core_params->otg_ver;
22495 +               DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
22496 +                          core_if->core_params->otg_ver, core_if->otg_ver);
22497 +       }
22498 +
22499 +
22500 +       /* Enable common interrupts */
22501 +       dwc_otg_enable_common_interrupts(core_if);
22502 +
22503 +       /* Do device or host intialization based on mode during PCD
22504 +        * and HCD initialization  */
22505 +       if (dwc_otg_is_host_mode(core_if)) {
22506 +               DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
22507 +               core_if->op_state = A_HOST;
22508 +       } else {
22509 +               DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
22510 +               core_if->op_state = B_PERIPHERAL;
22511 +#ifdef DWC_DEVICE_ONLY
22512 +               dwc_otg_core_dev_init(core_if);
22513 +#endif
22514 +       }
22515 +}
22516 +
22517 +/**
22518 + * This function enables the Device mode interrupts.
22519 + *
22520 + * @param core_if Programming view of DWC_otg controller
22521 + */
22522 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
22523 +{
22524 +       gintmsk_data_t intr_mask = {.d32 = 0 };
22525 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22526 +
22527 +       DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
22528 +
22529 +       /* Disable all interrupts. */
22530 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22531 +
22532 +       /* Clear any pending interrupts */
22533 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22534 +
22535 +       /* Enable the common interrupts */
22536 +       dwc_otg_enable_common_interrupts(core_if);
22537 +
22538 +       /* Enable interrupts */
22539 +       intr_mask.b.usbreset = 1;
22540 +       intr_mask.b.enumdone = 1;
22541 +       /* Disable Disconnect interrupt in Device mode */
22542 +       intr_mask.b.disconnect = 0;
22543 +
22544 +       if (!core_if->multiproc_int_enable) {
22545 +               intr_mask.b.inepintr = 1;
22546 +               intr_mask.b.outepintr = 1;
22547 +       }
22548 +
22549 +       intr_mask.b.erlysuspend = 1;
22550 +
22551 +       if (core_if->en_multiple_tx_fifo == 0) {
22552 +               intr_mask.b.epmismatch = 1;
22553 +       }
22554 +
22555 +       //intr_mask.b.incomplisoout = 1;
22556 +       intr_mask.b.incomplisoin = 1;
22557 +
22558 +/* Enable the ignore frame number for ISOC xfers - MAS */
22559 +/* Disable to support high bandwith ISOC transfers - manukz */
22560 +#if 0
22561 +#ifdef DWC_UTE_PER_IO
22562 +       if (core_if->dma_enable) {
22563 +               if (core_if->dma_desc_enable) {
22564 +                       dctl_data_t dctl1 = {.d32 = 0 };
22565 +                       dctl1.b.ifrmnum = 1;
22566 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
22567 +                                        dctl, 0, dctl1.d32);
22568 +                       DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",
22569 +                                 DWC_READ_REG32(&core_if->dev_if->
22570 +                                                dev_global_regs->dctl));
22571 +               }
22572 +       }
22573 +#endif
22574 +#endif
22575 +#ifdef DWC_EN_ISOC
22576 +       if (core_if->dma_enable) {
22577 +               if (core_if->dma_desc_enable == 0) {
22578 +                       if (core_if->pti_enh_enable) {
22579 +                               dctl_data_t dctl = {.d32 = 0 };
22580 +                               dctl.b.ifrmnum = 1;
22581 +                               DWC_MODIFY_REG32(&core_if->
22582 +                                                dev_if->dev_global_regs->dctl,
22583 +                                                0, dctl.d32);
22584 +                       } else {
22585 +                               intr_mask.b.incomplisoin = 1;
22586 +                               intr_mask.b.incomplisoout = 1;
22587 +                       }
22588 +               }
22589 +       } else {
22590 +               intr_mask.b.incomplisoin = 1;
22591 +               intr_mask.b.incomplisoout = 1;
22592 +       }
22593 +#endif /* DWC_EN_ISOC */
22594 +
22595 +       /** @todo NGS: Should this be a module parameter? */
22596 +#ifdef USE_PERIODIC_EP
22597 +       intr_mask.b.isooutdrop = 1;
22598 +       intr_mask.b.eopframe = 1;
22599 +       intr_mask.b.incomplisoin = 1;
22600 +       intr_mask.b.incomplisoout = 1;
22601 +#endif
22602 +
22603 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
22604 +
22605 +       DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
22606 +                   DWC_READ_REG32(&global_regs->gintmsk));
22607 +}
22608 +
22609 +/**
22610 + * This function initializes the DWC_otg controller registers for
22611 + * device mode.
22612 + *
22613 + * @param core_if Programming view of DWC_otg controller
22614 + *
22615 + */
22616 +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
22617 +{
22618 +       int i;
22619 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22620 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22621 +       dwc_otg_core_params_t *params = core_if->core_params;
22622 +       dcfg_data_t dcfg = {.d32 = 0 };
22623 +       depctl_data_t diepctl = {.d32 = 0 };
22624 +       grstctl_t resetctl = {.d32 = 0 };
22625 +       uint32_t rx_fifo_size;
22626 +       fifosize_data_t nptxfifosize;
22627 +       fifosize_data_t txfifosize;
22628 +       dthrctl_data_t dthrctl;
22629 +       fifosize_data_t ptxfifosize;
22630 +       uint16_t rxfsiz, nptxfsiz;
22631 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
22632 +       hwcfg3_data_t hwcfg3 = {.d32 = 0 };
22633 +
22634 +       /* Restart the Phy Clock */
22635 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
22636 +
22637 +       /* Device configuration register */
22638 +       init_devspd(core_if);
22639 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22640 +       dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
22641 +       dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
22642 +       /* Enable Device OUT NAK in case of DDMA mode*/
22643 +       if (core_if->core_params->dev_out_nak) {
22644 +               dcfg.b.endevoutnak = 1;
22645 +       }
22646 +
22647 +       if (core_if->core_params->cont_on_bna) {
22648 +               dctl_data_t dctl = {.d32 = 0 };
22649 +               dctl.b.encontonbna = 1;
22650 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22651 +       }
22652 +
22653 +
22654 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22655 +
22656 +       /* Configure data FIFO sizes */
22657 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
22658 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
22659 +                           core_if->total_fifo_size);
22660 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
22661 +                           params->dev_rx_fifo_size);
22662 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
22663 +                           params->dev_nperio_tx_fifo_size);
22664 +
22665 +               /* Rx FIFO */
22666 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
22667 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22668 +
22669 +#ifdef DWC_UTE_CFI
22670 +               core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);
22671 +               core_if->init_rxfsiz = params->dev_rx_fifo_size;
22672 +#endif
22673 +               rx_fifo_size = params->dev_rx_fifo_size;
22674 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
22675 +
22676 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
22677 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22678 +
22679 +               /** Set Periodic Tx FIFO Mask all bits 0 */
22680 +               core_if->p_tx_msk = 0;
22681 +
22682 +               /** Set Tx FIFO Mask all bits 0 */
22683 +               core_if->tx_msk = 0;
22684 +
22685 +               if (core_if->en_multiple_tx_fifo == 0) {
22686 +                       /* Non-periodic Tx FIFO */
22687 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22688 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22689 +
22690 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22691 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22692 +
22693 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22694 +                                       nptxfifosize.d32);
22695 +
22696 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22697 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22698 +
22699 +                       /**@todo NGS: Fix Periodic FIFO Sizing! */
22700 +                       /*
22701 +                        * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
22702 +                        * Indexes of the FIFO size module parameters in the
22703 +                        * dev_perio_tx_fifo_size array and the FIFO size registers in
22704 +                        * the dptxfsiz array run from 0 to 14.
22705 +                        */
22706 +                       /** @todo Finish debug of this */
22707 +                       ptxfifosize.b.startaddr =
22708 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22709 +                       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22710 +                               ptxfifosize.b.depth =
22711 +                                   params->dev_perio_tx_fifo_size[i];
22712 +                               DWC_DEBUGPL(DBG_CIL,
22713 +                                           "initial dtxfsiz[%d]=%08x\n", i,
22714 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22715 +                                                          [i]));
22716 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22717 +                                               ptxfifosize.d32);
22718 +                               DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",
22719 +                                           i,
22720 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22721 +                                                          [i]));
22722 +                               ptxfifosize.b.startaddr += ptxfifosize.b.depth;
22723 +                       }
22724 +               } else {
22725 +                       /*
22726 +                        * Tx FIFOs These FIFOs are numbered from 1 to 15.
22727 +                        * Indexes of the FIFO size module parameters in the
22728 +                        * dev_tx_fifo_size array and the FIFO size registers in
22729 +                        * the dtxfsiz array run from 0 to 14.
22730 +                        */
22731 +
22732 +                       /* Non-periodic Tx FIFO */
22733 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22734 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22735 +
22736 +#ifdef DWC_UTE_CFI
22737 +                       core_if->pwron_gnptxfsiz =
22738 +                           (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22739 +                       core_if->init_gnptxfsiz =
22740 +                           params->dev_nperio_tx_fifo_size;
22741 +#endif
22742 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22743 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22744 +
22745 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22746 +                                       nptxfifosize.d32);
22747 +
22748 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22749 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22750 +
22751 +                       txfifosize.b.startaddr =
22752 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22753 +
22754 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22755 +
22756 +                               txfifosize.b.depth =
22757 +                                   params->dev_tx_fifo_size[i];
22758 +
22759 +                               DWC_DEBUGPL(DBG_CIL,
22760 +                                           "initial dtxfsiz[%d]=%08x\n",
22761 +                                           i,
22762 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22763 +                                                          [i]));
22764 +
22765 +#ifdef DWC_UTE_CFI
22766 +                               core_if->pwron_txfsiz[i] =
22767 +                                   (DWC_READ_REG32
22768 +                                    (&global_regs->dtxfsiz[i]) >> 16);
22769 +                               core_if->init_txfsiz[i] =
22770 +                                   params->dev_tx_fifo_size[i];
22771 +#endif
22772 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22773 +                                               txfifosize.d32);
22774 +
22775 +                               DWC_DEBUGPL(DBG_CIL,
22776 +                                           "new dtxfsiz[%d]=%08x\n",
22777 +                                           i,
22778 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22779 +                                                          [i]));
22780 +
22781 +                               txfifosize.b.startaddr += txfifosize.b.depth;
22782 +                       }
22783 +                       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
22784 +                               /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */
22785 +                               gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
22786 +                               hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);
22787 +                               gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);
22788 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22789 +                               rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
22790 +                               nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22791 +                               gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;
22792 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22793 +                       }
22794 +               }
22795 +
22796 +               /* Flush the FIFOs */
22797 +               dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
22798 +               dwc_otg_flush_rx_fifo(core_if);
22799 +
22800 +               /* Flush the Learning Queue. */
22801 +               resetctl.b.intknqflsh = 1;
22802 +               DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
22803 +
22804 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
22805 +                       core_if->start_predict = 0;
22806 +                       for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
22807 +                               core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
22808 +                       }
22809 +                       core_if->nextep_seq[0] = 0;
22810 +                       core_if->first_in_nextep_seq = 0;
22811 +                       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
22812 +                       diepctl.b.nextep = 0;
22813 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
22814 +
22815 +                       /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
22816 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22817 +                       dcfg.b.epmscnt = 2;
22818 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22819 +
22820 +                       DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
22821 +                               __func__, core_if->first_in_nextep_seq);
22822 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
22823 +                               DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
22824 +                       }
22825 +                       DWC_DEBUGPL(DBG_CILV,"\n");
22826 +               }
22827 +
22828 +               /* Clear all pending Device Interrupts */
22829 +               /** @todo - if the condition needed to be checked
22830 +                *  or in any case all pending interrutps should be cleared?
22831 +            */
22832 +               if (core_if->multiproc_int_enable) {
22833 +                       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22834 +                               DWC_WRITE_REG32(&dev_if->
22835 +                                               dev_global_regs->diepeachintmsk[i], 0);
22836 +                       }
22837 +               }
22838 +
22839 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
22840 +                       DWC_WRITE_REG32(&dev_if->
22841 +                                       dev_global_regs->doepeachintmsk[i], 0);
22842 +               }
22843 +
22844 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
22845 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);
22846 +       } else {
22847 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
22848 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
22849 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
22850 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
22851 +       }
22852 +
22853 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
22854 +               depctl_data_t depctl;
22855 +               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
22856 +               if (depctl.b.epena) {
22857 +                       depctl.d32 = 0;
22858 +                       depctl.b.epdis = 1;
22859 +                       depctl.b.snak = 1;
22860 +               } else {
22861 +                       depctl.d32 = 0;
22862 +               }
22863 +
22864 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
22865 +
22866 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
22867 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
22868 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
22869 +       }
22870 +
22871 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
22872 +               depctl_data_t depctl;
22873 +               depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
22874 +               if (depctl.b.epena) {
22875 +                       dctl_data_t dctl = {.d32 = 0 };
22876 +                       gintmsk_data_t gintsts = {.d32 = 0 };
22877 +                       doepint_data_t doepint = {.d32 = 0 };
22878 +                       dctl.b.sgoutnak = 1;
22879 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22880 +                       do {
22881 +                               dwc_udelay(10);
22882 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
22883 +                       } while (!gintsts.b.goutnakeff);
22884 +                       gintsts.d32 = 0;
22885 +                       gintsts.b.goutnakeff = 1;
22886 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
22887 +
22888 +                       depctl.d32 = 0;
22889 +                       depctl.b.epdis = 1;
22890 +                       depctl.b.snak = 1;
22891 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);
22892 +                       do {
22893 +                               dwc_udelay(10);
22894 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
22895 +                                       out_ep_regs[i]->doepint);
22896 +                       } while (!doepint.b.epdisabled);
22897 +
22898 +                       doepint.b.epdisabled = 1;
22899 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);
22900 +
22901 +                       dctl.d32 = 0;
22902 +                       dctl.b.cgoutnak = 1;
22903 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22904 +               } else {
22905 +                       depctl.d32 = 0;
22906 +               }
22907 +
22908 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
22909 +
22910 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
22911 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
22912 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
22913 +       }
22914 +
22915 +       if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
22916 +               dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
22917 +               dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
22918 +               dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
22919 +
22920 +               dev_if->rx_thr_length = params->rx_thr_length;
22921 +               dev_if->tx_thr_length = params->tx_thr_length;
22922 +
22923 +               dev_if->setup_desc_index = 0;
22924 +
22925 +               dthrctl.d32 = 0;
22926 +               dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
22927 +               dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
22928 +               dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
22929 +               dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
22930 +               dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
22931 +               dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
22932 +
22933 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
22934 +                               dthrctl.d32);
22935 +
22936 +               DWC_DEBUGPL(DBG_CIL,
22937 +                           "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
22938 +                           dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
22939 +                           dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
22940 +                           dthrctl.b.rx_thr_len);
22941 +
22942 +       }
22943 +
22944 +       dwc_otg_enable_device_interrupts(core_if);
22945 +
22946 +       {
22947 +               diepmsk_data_t msk = {.d32 = 0 };
22948 +               msk.b.txfifoundrn = 1;
22949 +               if (core_if->multiproc_int_enable) {
22950 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->
22951 +                                        diepeachintmsk[0], msk.d32, msk.d32);
22952 +               } else {
22953 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,
22954 +                                        msk.d32, msk.d32);
22955 +               }
22956 +       }
22957 +
22958 +       if (core_if->multiproc_int_enable) {
22959 +               /* Set NAK on Babble */
22960 +               dctl_data_t dctl = {.d32 = 0 };
22961 +               dctl.b.nakonbble = 1;
22962 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22963 +       }
22964 +
22965 +       if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
22966 +               dctl_data_t dctl = {.d32 = 0 };
22967 +               dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
22968 +               dctl.b.sftdiscon = 0;
22969 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
22970 +       }
22971 +}
22972 +
22973 +/**
22974 + * This function enables the Host mode interrupts.
22975 + *
22976 + * @param core_if Programming view of DWC_otg controller
22977 + */
22978 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
22979 +{
22980 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22981 +       gintmsk_data_t intr_mask = {.d32 = 0 };
22982 +
22983 +       DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
22984 +
22985 +       /* Disable all interrupts. */
22986 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22987 +
22988 +       /* Clear any pending interrupts. */
22989 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22990 +
22991 +       /* Enable the common interrupts */
22992 +       dwc_otg_enable_common_interrupts(core_if);
22993 +
22994 +       /*
22995 +        * Enable host mode interrupts without disturbing common
22996 +        * interrupts.
22997 +        */
22998 +
22999 +       intr_mask.b.disconnect = 1;
23000 +       intr_mask.b.portintr = 1;
23001 +       intr_mask.b.hcintr = 1;
23002 +
23003 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
23004 +}
23005 +
23006 +/**
23007 + * This function disables the Host Mode interrupts.
23008 + *
23009 + * @param core_if Programming view of DWC_otg controller
23010 + */
23011 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
23012 +{
23013 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23014 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23015 +
23016 +       DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
23017 +
23018 +       /*
23019 +        * Disable host mode interrupts without disturbing common
23020 +        * interrupts.
23021 +        */
23022 +       intr_mask.b.sofintr = 1;
23023 +       intr_mask.b.portintr = 1;
23024 +       intr_mask.b.hcintr = 1;
23025 +       intr_mask.b.ptxfempty = 1;
23026 +       intr_mask.b.nptxfempty = 1;
23027 +
23028 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);
23029 +}
23030 +
23031 +/**
23032 + * This function initializes the DWC_otg controller registers for
23033 + * host mode.
23034 + *
23035 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
23036 + * request queues. Host channels are reset to ensure that they are ready for
23037 + * performing transfers.
23038 + *
23039 + * @param core_if Programming view of DWC_otg controller
23040 + *
23041 + */
23042 +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
23043 +{
23044 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23045 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23046 +       dwc_otg_core_params_t *params = core_if->core_params;
23047 +       hprt0_data_t hprt0 = {.d32 = 0 };
23048 +       fifosize_data_t nptxfifosize;
23049 +       fifosize_data_t ptxfifosize;
23050 +       uint16_t rxfsiz, nptxfsiz, hptxfsiz;
23051 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
23052 +       int i;
23053 +       hcchar_data_t hcchar;
23054 +       hcfg_data_t hcfg;
23055 +       hfir_data_t hfir;
23056 +       dwc_otg_hc_regs_t *hc_regs;
23057 +       int num_channels;
23058 +       gotgctl_data_t gotgctl = {.d32 = 0 };
23059 +
23060 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
23061 +
23062 +       /* Restart the Phy Clock */
23063 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
23064 +
23065 +       /* Initialize Host Configuration Register */
23066 +       init_fslspclksel(core_if);
23067 +       if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
23068 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23069 +               hcfg.b.fslssupp = 1;
23070 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23071 +
23072 +       }
23073 +
23074 +       /* This bit allows dynamic reloading of the HFIR register
23075 +        * during runtime. This bit needs to be programmed during
23076 +        * initial configuration and its value must not be changed
23077 +        * during runtime.*/
23078 +       if (core_if->core_params->reload_ctl == 1) {
23079 +               hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
23080 +               hfir.b.hfirrldctrl = 1;
23081 +               DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
23082 +       }
23083 +
23084 +       if (core_if->core_params->dma_desc_enable) {
23085 +               uint8_t op_mode = core_if->hwcfg2.b.op_mode;
23086 +               if (!
23087 +                   (core_if->hwcfg4.b.desc_dma
23088 +                    && (core_if->snpsid >= OTG_CORE_REV_2_90a)
23089 +                    && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
23090 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
23091 +                        || (op_mode ==
23092 +                            DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)
23093 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
23094 +                        || (op_mode ==
23095 +                            DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
23096 +
23097 +                       DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
23098 +                                 "Either core version is below 2.90a or "
23099 +                                 "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
23100 +                                 "To run the driver in Buffer DMA host mode set dma_desc_enable "
23101 +                                 "module parameter to 0.\n");
23102 +                       return;
23103 +               }
23104 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23105 +               hcfg.b.descdma = 1;
23106 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23107 +       }
23108 +
23109 +       /* Configure data FIFO sizes */
23110 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
23111 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
23112 +                           core_if->total_fifo_size);
23113 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
23114 +                           params->host_rx_fifo_size);
23115 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
23116 +                           params->host_nperio_tx_fifo_size);
23117 +               DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
23118 +                           params->host_perio_tx_fifo_size);
23119 +
23120 +               /* Rx FIFO */
23121 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
23122 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23123 +               DWC_WRITE_REG32(&global_regs->grxfsiz,
23124 +                               params->host_rx_fifo_size);
23125 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
23126 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23127 +
23128 +               /* Non-periodic Tx FIFO */
23129 +               DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
23130 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23131 +               nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
23132 +               nptxfifosize.b.startaddr = params->host_rx_fifo_size;
23133 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
23134 +               DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
23135 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23136 +
23137 +               /* Periodic Tx FIFO */
23138 +               DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
23139 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23140 +               ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
23141 +               ptxfifosize.b.startaddr =
23142 +                   nptxfifosize.b.startaddr + nptxfifosize.b.depth;
23143 +               DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
23144 +               DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
23145 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23146 +
23147 +               if (core_if->en_multiple_tx_fifo
23148 +                   && core_if->snpsid <= OTG_CORE_REV_2_94a) {
23149 +                       /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
23150 +                       gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
23151 +                       rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
23152 +                       nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
23153 +                       hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);
23154 +                       gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;
23155 +                       DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
23156 +               }
23157 +       }
23158 +
23159 +       /* TODO - check this */
23160 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23161 +       gotgctl.b.hstsethnpen = 1;
23162 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23163 +       /* Make sure the FIFOs are flushed. */
23164 +       dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );
23165 +       dwc_otg_flush_rx_fifo(core_if);
23166 +
23167 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23168 +       gotgctl.b.hstsethnpen = 1;
23169 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23170 +
23171 +       if (!core_if->core_params->dma_desc_enable) {
23172 +               /* Flush out any leftover queued requests. */
23173 +               num_channels = core_if->core_params->host_channels;
23174 +
23175 +               for (i = 0; i < num_channels; i++) {
23176 +                       hc_regs = core_if->host_if->hc_regs[i];
23177 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23178 +                       hcchar.b.chen = 0;
23179 +                       hcchar.b.chdis = 1;
23180 +                       hcchar.b.epdir = 0;
23181 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23182 +               }
23183 +
23184 +               /* Halt all channels to put them into a known state. */
23185 +               for (i = 0; i < num_channels; i++) {
23186 +                       int count = 0;
23187 +                       hc_regs = core_if->host_if->hc_regs[i];
23188 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23189 +                       hcchar.b.chen = 1;
23190 +                       hcchar.b.chdis = 1;
23191 +                       hcchar.b.epdir = 0;
23192 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23193 +                       DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
23194 +                       do {
23195 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23196 +                               if (++count > 1000) {
23197 +                                       DWC_ERROR
23198 +                                           ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
23199 +                                            __func__, i, hcchar.d32, &hc_regs->hcchar);
23200 +                                       break;
23201 +                               }
23202 +                               dwc_udelay(1);
23203 +                       } while (hcchar.b.chen);
23204 +               }
23205 +       }
23206 +
23207 +       /* Turn on the vbus power. */
23208 +       DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
23209 +       if (core_if->op_state == A_HOST) {
23210 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
23211 +               DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
23212 +               if (hprt0.b.prtpwr == 0) {
23213 +                       hprt0.b.prtpwr = 1;
23214 +                       DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);
23215 +               }
23216 +       }
23217 +
23218 +       dwc_otg_enable_host_interrupts(core_if);
23219 +}
23220 +
23221 +/**
23222 + * Prepares a host channel for transferring packets to/from a specific
23223 + * endpoint. The HCCHARn register is set up with the characteristics specified
23224 + * in _hc. Host channel interrupts that may need to be serviced while this
23225 + * transfer is in progress are enabled.
23226 + *
23227 + * @param core_if Programming view of DWC_otg controller
23228 + * @param hc Information needed to initialize the host channel
23229 + */
23230 +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23231 +{
23232 +       uint32_t intr_enable;
23233 +       hcintmsk_data_t hc_intr_mask;
23234 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23235 +       hcchar_data_t hcchar;
23236 +       hcsplt_data_t hcsplt;
23237 +
23238 +       uint8_t hc_num = hc->hc_num;
23239 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23240 +       dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
23241 +
23242 +       /* Clear old interrupt conditions for this host channel. */
23243 +       hc_intr_mask.d32 = 0xFFFFFFFF;
23244 +       hc_intr_mask.b.reserved14_31 = 0;
23245 +       DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);
23246 +
23247 +       /* Enable channel interrupts required for this transfer. */
23248 +       hc_intr_mask.d32 = 0;
23249 +       hc_intr_mask.b.chhltd = 1;
23250 +       if (core_if->dma_enable) {
23251 +               /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
23252 +               if (!core_if->dma_desc_enable)
23253 +                       hc_intr_mask.b.ahberr = 1;
23254 +               else {
23255 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23256 +                               hc_intr_mask.b.xfercompl = 1;
23257 +               }
23258 +
23259 +               if (hc->error_state && !hc->do_split &&
23260 +                   hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
23261 +                       hc_intr_mask.b.ack = 1;
23262 +                       if (hc->ep_is_in) {
23263 +                               hc_intr_mask.b.datatglerr = 1;
23264 +                               if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23265 +                                       hc_intr_mask.b.nak = 1;
23266 +                               }
23267 +                       }
23268 +               }
23269 +       } else {
23270 +               switch (hc->ep_type) {
23271 +               case DWC_OTG_EP_TYPE_CONTROL:
23272 +               case DWC_OTG_EP_TYPE_BULK:
23273 +                       hc_intr_mask.b.xfercompl = 1;
23274 +                       hc_intr_mask.b.stall = 1;
23275 +                       hc_intr_mask.b.xacterr = 1;
23276 +                       hc_intr_mask.b.datatglerr = 1;
23277 +                       if (hc->ep_is_in) {
23278 +                               hc_intr_mask.b.bblerr = 1;
23279 +                       } else {
23280 +                               hc_intr_mask.b.nak = 1;
23281 +                               hc_intr_mask.b.nyet = 1;
23282 +                               if (hc->do_ping) {
23283 +                                       hc_intr_mask.b.ack = 1;
23284 +                               }
23285 +                       }
23286 +
23287 +                       if (hc->do_split) {
23288 +                               hc_intr_mask.b.nak = 1;
23289 +                               if (hc->complete_split) {
23290 +                                       hc_intr_mask.b.nyet = 1;
23291 +                               } else {
23292 +                                       hc_intr_mask.b.ack = 1;
23293 +                               }
23294 +                       }
23295 +
23296 +                       if (hc->error_state) {
23297 +                               hc_intr_mask.b.ack = 1;
23298 +                       }
23299 +                       break;
23300 +               case DWC_OTG_EP_TYPE_INTR:
23301 +                       hc_intr_mask.b.xfercompl = 1;
23302 +                       hc_intr_mask.b.nak = 1;
23303 +                       hc_intr_mask.b.stall = 1;
23304 +                       hc_intr_mask.b.xacterr = 1;
23305 +                       hc_intr_mask.b.datatglerr = 1;
23306 +                       hc_intr_mask.b.frmovrun = 1;
23307 +
23308 +                       if (hc->ep_is_in) {
23309 +                               hc_intr_mask.b.bblerr = 1;
23310 +                       }
23311 +                       if (hc->error_state) {
23312 +                               hc_intr_mask.b.ack = 1;
23313 +                       }
23314 +                       if (hc->do_split) {
23315 +                               if (hc->complete_split) {
23316 +                                       hc_intr_mask.b.nyet = 1;
23317 +                               } else {
23318 +                                       hc_intr_mask.b.ack = 1;
23319 +                               }
23320 +                       }
23321 +                       break;
23322 +               case DWC_OTG_EP_TYPE_ISOC:
23323 +                       hc_intr_mask.b.xfercompl = 1;
23324 +                       hc_intr_mask.b.frmovrun = 1;
23325 +                       hc_intr_mask.b.ack = 1;
23326 +
23327 +                       if (hc->ep_is_in) {
23328 +                               hc_intr_mask.b.xacterr = 1;
23329 +                               hc_intr_mask.b.bblerr = 1;
23330 +                       }
23331 +                       break;
23332 +               }
23333 +       }
23334 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
23335 +
23336 +       /* Enable the top level host channel interrupt. */
23337 +       intr_enable = (1 << hc_num);
23338 +       DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
23339 +
23340 +       /* Make sure host channel interrupts are enabled. */
23341 +       gintmsk.b.hcintr = 1;
23342 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
23343 +
23344 +       /*
23345 +        * Program the HCCHARn register with the endpoint characteristics for
23346 +        * the current transfer.
23347 +        */
23348 +       hcchar.d32 = 0;
23349 +       hcchar.b.devaddr = hc->dev_addr;
23350 +       hcchar.b.epnum = hc->ep_num;
23351 +       hcchar.b.epdir = hc->ep_is_in;
23352 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
23353 +       hcchar.b.eptype = hc->ep_type;
23354 +       hcchar.b.mps = hc->max_packet;
23355 +
23356 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
23357 +
23358 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",
23359 +                    __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);
23360 +       DWC_DEBUGPL(DBG_HCDV, "  Is In %d, Is Low Speed %d, EP Type %d, "
23361 +                                "Max Pkt %d, Multi Cnt %d\n",
23362 +                    hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,
23363 +                    hcchar.b.mps, hcchar.b.multicnt);
23364 +
23365 +       /*
23366 +        * Program the HCSPLIT register for SPLITs
23367 +        */
23368 +       hcsplt.d32 = 0;
23369 +       if (hc->do_split) {
23370 +               DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
23371 +                           hc->hc_num,
23372 +                           hc->complete_split ? "CSPLIT" : "SSPLIT");
23373 +               hcsplt.b.compsplt = hc->complete_split;
23374 +               hcsplt.b.xactpos = hc->xact_pos;
23375 +               hcsplt.b.hubaddr = hc->hub_addr;
23376 +               hcsplt.b.prtaddr = hc->port_addr;
23377 +               DWC_DEBUGPL(DBG_HCDV, "\t  comp split %d\n", hc->complete_split);
23378 +               DWC_DEBUGPL(DBG_HCDV, "\t  xact pos %d\n", hc->xact_pos);
23379 +               DWC_DEBUGPL(DBG_HCDV, "\t  hub addr %d\n", hc->hub_addr);
23380 +               DWC_DEBUGPL(DBG_HCDV, "\t  port addr %d\n", hc->port_addr);
23381 +               DWC_DEBUGPL(DBG_HCDV, "\t  is_in %d\n", hc->ep_is_in);
23382 +               DWC_DEBUGPL(DBG_HCDV, "\t  Max Pkt: %d\n", hcchar.b.mps);
23383 +               DWC_DEBUGPL(DBG_HCDV, "\t  xferlen: %d\n", hc->xfer_len);
23384 +       }
23385 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
23386 +
23387 +}
23388 +
23389 +/**
23390 + * Attempts to halt a host channel. This function should only be called in
23391 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
23392 + * normal circumstances in DMA mode, the controller halts the channel when the
23393 + * transfer is complete or a condition occurs that requires application
23394 + * intervention.
23395 + *
23396 + * In slave mode, checks for a free request queue entry, then sets the Channel
23397 + * Enable and Channel Disable bits of the Host Channel Characteristics
23398 + * register of the specified channel to intiate the halt. If there is no free
23399 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
23400 + * register to flush requests for this channel. In the latter case, sets a
23401 + * flag to indicate that the host channel needs to be halted when a request
23402 + * queue slot is open.
23403 + *
23404 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
23405 + * HCCHARn register. The controller ensures there is space in the request
23406 + * queue before submitting the halt request.
23407 + *
23408 + * Some time may elapse before the core flushes any posted requests for this
23409 + * host channel and halts. The Channel Halted interrupt handler completes the
23410 + * deactivation of the host channel.
23411 + *
23412 + * @param core_if Controller register interface.
23413 + * @param hc Host channel to halt.
23414 + * @param halt_status Reason for halting the channel.
23415 + */
23416 +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
23417 +                    dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
23418 +{
23419 +       gnptxsts_data_t nptxsts;
23420 +       hptxsts_data_t hptxsts;
23421 +       hcchar_data_t hcchar;
23422 +       dwc_otg_hc_regs_t *hc_regs;
23423 +       dwc_otg_core_global_regs_t *global_regs;
23424 +       dwc_otg_host_global_regs_t *host_global_regs;
23425 +
23426 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23427 +       global_regs = core_if->core_global_regs;
23428 +       host_global_regs = core_if->host_if->host_global_regs;
23429 +
23430 +       DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
23431 +                  "halt_status = %d\n", halt_status);
23432 +
23433 +       if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
23434 +           halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
23435 +               /*
23436 +                * Disable all channel interrupts except Ch Halted. The QTD
23437 +                * and QH state associated with this transfer has been cleared
23438 +                * (in the case of URB_DEQUEUE), so the channel needs to be
23439 +                * shut down carefully to prevent crashes.
23440 +                */
23441 +               hcintmsk_data_t hcintmsk;
23442 +               hcintmsk.d32 = 0;
23443 +               hcintmsk.b.chhltd = 1;
23444 +               DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);
23445 +
23446 +               /*
23447 +                * Make sure no other interrupts besides halt are currently
23448 +                * pending. Handling another interrupt could cause a crash due
23449 +                * to the QTD and QH state.
23450 +                */
23451 +               DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);
23452 +
23453 +               /*
23454 +                * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
23455 +                * even if the channel was already halted for some other
23456 +                * reason.
23457 +                */
23458 +               hc->halt_status = halt_status;
23459 +
23460 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23461 +               if (hcchar.b.chen == 0) {
23462 +                       /*
23463 +                        * The channel is either already halted or it hasn't
23464 +                        * started yet. In DMA mode, the transfer may halt if
23465 +                        * it finishes normally or a condition occurs that
23466 +                        * requires driver intervention. Don't want to halt
23467 +                        * the channel again. In either Slave or DMA mode,
23468 +                        * it's possible that the transfer has been assigned
23469 +                        * to a channel, but not started yet when an URB is
23470 +                        * dequeued. Don't want to halt a channel that hasn't
23471 +                        * started yet.
23472 +                        */
23473 +                       return;
23474 +               }
23475 +       }
23476 +       if (hc->halt_pending) {
23477 +               /*
23478 +                * A halt has already been issued for this channel. This might
23479 +                * happen when a transfer is aborted by a higher level in
23480 +                * the stack.
23481 +                */
23482 +#ifdef DEBUG
23483 +               DWC_PRINTF
23484 +                   ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
23485 +                    __func__, hc->hc_num);
23486 +
23487 +#endif
23488 +               return;
23489 +       }
23490 +
23491 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23492 +
23493 +       /* No need to set the bit in DDMA for disabling the channel */
23494 +       //TODO check it everywhere channel is disabled
23495 +       if (!core_if->core_params->dma_desc_enable)
23496 +               hcchar.b.chen = 1;
23497 +       hcchar.b.chdis = 1;
23498 +
23499 +       if (!core_if->dma_enable) {
23500 +               /* Check for space in the request queue to issue the halt. */
23501 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
23502 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
23503 +                       nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
23504 +                       if (nptxsts.b.nptxqspcavail == 0) {
23505 +                               hcchar.b.chen = 0;
23506 +                       }
23507 +               } else {
23508 +                       hptxsts.d32 =
23509 +                           DWC_READ_REG32(&host_global_regs->hptxsts);
23510 +                       if ((hptxsts.b.ptxqspcavail == 0)
23511 +                           || (core_if->queuing_high_bandwidth)) {
23512 +                               hcchar.b.chen = 0;
23513 +                       }
23514 +               }
23515 +       }
23516 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23517 +
23518 +       hc->halt_status = halt_status;
23519 +
23520 +       if (hcchar.b.chen) {
23521 +               hc->halt_pending = 1;
23522 +               hc->halt_on_queue = 0;
23523 +       } else {
23524 +               hc->halt_on_queue = 1;
23525 +       }
23526 +
23527 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23528 +       DWC_DEBUGPL(DBG_HCDV, "  hcchar: 0x%08x\n", hcchar.d32);
23529 +       DWC_DEBUGPL(DBG_HCDV, "  halt_pending: %d\n", hc->halt_pending);
23530 +       DWC_DEBUGPL(DBG_HCDV, "  halt_on_queue: %d\n", hc->halt_on_queue);
23531 +       DWC_DEBUGPL(DBG_HCDV, "  halt_status: %d\n", hc->halt_status);
23532 +
23533 +       return;
23534 +}
23535 +
23536 +/**
23537 + * Clears the transfer state for a host channel. This function is normally
23538 + * called after a transfer is done and the host channel is being released.
23539 + *
23540 + * @param core_if Programming view of DWC_otg controller.
23541 + * @param hc Identifies the host channel to clean up.
23542 + */
23543 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23544 +{
23545 +       dwc_otg_hc_regs_t *hc_regs;
23546 +
23547 +       hc->xfer_started = 0;
23548 +
23549 +       /*
23550 +        * Clear channel interrupt enables and any unhandled channel interrupt
23551 +        * conditions.
23552 +        */
23553 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23554 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);
23555 +       DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);
23556 +#ifdef DEBUG
23557 +       DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
23558 +#endif
23559 +}
23560 +
23561 +/**
23562 + * Sets the channel property that indicates in which frame a periodic transfer
23563 + * should occur. This is always set to the _next_ frame. This function has no
23564 + * effect on non-periodic transfers.
23565 + *
23566 + * @param core_if Programming view of DWC_otg controller.
23567 + * @param hc Identifies the host channel to set up and its properties.
23568 + * @param hcchar Current value of the HCCHAR register for the specified host
23569 + * channel.
23570 + */
23571 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
23572 +                                        dwc_hc_t * hc, hcchar_data_t * hcchar)
23573 +{
23574 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23575 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23576 +               hfnum_data_t hfnum;
23577 +               hfnum.d32 =
23578 +                   DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);
23579 +
23580 +               /* 1 if _next_ frame is odd, 0 if it's even */
23581 +               hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
23582 +#ifdef DEBUG
23583 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
23584 +                   && !hc->complete_split) {
23585 +                       switch (hfnum.b.frnum & 0x7) {
23586 +                       case 7:
23587 +                               core_if->hfnum_7_samples++;
23588 +                               core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
23589 +                               break;
23590 +                       case 0:
23591 +                               core_if->hfnum_0_samples++;
23592 +                               core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
23593 +                               break;
23594 +                       default:
23595 +                               core_if->hfnum_other_samples++;
23596 +                               core_if->hfnum_other_frrem_accum +=
23597 +                                   hfnum.b.frrem;
23598 +                               break;
23599 +                       }
23600 +               }
23601 +#endif
23602 +       }
23603 +}
23604 +
23605 +#ifdef DEBUG
23606 +void hc_xfer_timeout(void *ptr)
23607 +{
23608 +       hc_xfer_info_t *xfer_info = NULL;
23609 +       int hc_num = 0;
23610 +
23611 +       if (ptr)
23612 +               xfer_info = (hc_xfer_info_t *) ptr;
23613 +
23614 +       if (!xfer_info->hc) {
23615 +               DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);
23616 +               return;
23617 +       }
23618 +
23619 +       hc_num = xfer_info->hc->hc_num;
23620 +       DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
23621 +       DWC_WARN("      start_hcchar_val 0x%08x\n",
23622 +                xfer_info->core_if->start_hcchar_val[hc_num]);
23623 +}
23624 +#endif
23625 +
23626 +void ep_xfer_timeout(void *ptr)
23627 +{
23628 +       ep_xfer_info_t *xfer_info = NULL;
23629 +       int ep_num = 0;
23630 +       dctl_data_t dctl = {.d32 = 0 };
23631 +       gintsts_data_t gintsts = {.d32 = 0 };
23632 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23633 +
23634 +       if (ptr)
23635 +               xfer_info = (ep_xfer_info_t *) ptr;
23636 +
23637 +       if (!xfer_info->ep) {
23638 +               DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);
23639 +               return;
23640 +       }
23641 +
23642 +       ep_num = xfer_info->ep->num;
23643 +       DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);
23644 +       /* Put the sate to 2 as it was time outed */
23645 +       xfer_info->state = 2;
23646 +
23647 +       dctl.d32 =
23648 +           DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);
23649 +       gintsts.d32 =
23650 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);
23651 +       gintmsk.d32 =
23652 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);
23653 +
23654 +       if (!gintmsk.b.goutnakeff) {
23655 +               /* Unmask it */
23656 +               gintmsk.b.goutnakeff = 1;
23657 +               DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,
23658 +                               gintmsk.d32);
23659 +
23660 +       }
23661 +
23662 +       if (!gintsts.b.goutnakeff) {
23663 +               dctl.b.sgoutnak = 1;
23664 +       }
23665 +       DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,
23666 +                       dctl.d32);
23667 +
23668 +}
23669 +
23670 +void set_pid_isoc(dwc_hc_t * hc)
23671 +{
23672 +       /* Set up the initial PID for the transfer. */
23673 +       if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
23674 +               if (hc->ep_is_in) {
23675 +                       if (hc->multi_count == 1) {
23676 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23677 +                       } else if (hc->multi_count == 2) {
23678 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
23679 +                       } else {
23680 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
23681 +                       }
23682 +               } else {
23683 +                       if (hc->multi_count == 1) {
23684 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23685 +                       } else {
23686 +                               hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
23687 +                       }
23688 +               }
23689 +       } else {
23690 +               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23691 +       }
23692 +}
23693 +
23694 +/**
23695 + * This function does the setup for a data transfer for a host channel and
23696 + * starts the transfer. May be called in either Slave mode or DMA mode. In
23697 + * Slave mode, the caller must ensure that there is sufficient space in the
23698 + * request queue and Tx Data FIFO.
23699 + *
23700 + * For an OUT transfer in Slave mode, it loads a data packet into the
23701 + * appropriate FIFO. If necessary, additional data packets will be loaded in
23702 + * the Host ISR.
23703 + *
23704 + * For an IN transfer in Slave mode, a data packet is requested. The data
23705 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
23706 + * additional data packets are requested in the Host ISR.
23707 + *
23708 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
23709 + * register along with a packet count of 1 and the channel is enabled. This
23710 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
23711 + * simply set to 0 since no data transfer occurs in this case.
23712 + *
23713 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
23714 + * all the information required to perform the subsequent data transfer. In
23715 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
23716 + * controller performs the entire PING protocol, then starts the data
23717 + * transfer.
23718 + *
23719 + * @param core_if Programming view of DWC_otg controller.
23720 + * @param hc Information needed to initialize the host channel. The xfer_len
23721 + * value may be reduced to accommodate the max widths of the XferSize and
23722 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
23723 + * to reflect the final xfer_len value.
23724 + */
23725 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23726 +{
23727 +       hcchar_data_t hcchar;
23728 +       hctsiz_data_t hctsiz;
23729 +       uint16_t num_packets;
23730 +       uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
23731 +       uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
23732 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23733 +
23734 +       hctsiz.d32 = 0;
23735 +
23736 +       if (hc->do_ping) {
23737 +               if (!core_if->dma_enable) {
23738 +                       dwc_otg_hc_do_ping(core_if, hc);
23739 +                       hc->xfer_started = 1;
23740 +                       return;
23741 +               } else {
23742 +                       hctsiz.b.dopng = 1;
23743 +               }
23744 +       }
23745 +
23746 +       if (hc->do_split) {
23747 +               num_packets = 1;
23748 +
23749 +               if (hc->complete_split && !hc->ep_is_in) {
23750 +                       /* For CSPLIT OUT Transfer, set the size to 0 so the
23751 +                        * core doesn't expect any data written to the FIFO */
23752 +                       hc->xfer_len = 0;
23753 +               } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
23754 +                       hc->xfer_len = hc->max_packet;
23755 +               } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
23756 +                       hc->xfer_len = 188;
23757 +               }
23758 +
23759 +               hctsiz.b.xfersize = hc->xfer_len;
23760 +       } else {
23761 +               /*
23762 +                * Ensure that the transfer length and packet count will fit
23763 +                * in the widths allocated for them in the HCTSIZn register.
23764 +                */
23765 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23766 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23767 +                       /*
23768 +                        * Make sure the transfer size is no larger than one
23769 +                        * (micro)frame's worth of data. (A check was done
23770 +                        * when the periodic transfer was accepted to ensure
23771 +                        * that a (micro)frame's worth of data can be
23772 +                        * programmed into a channel.)
23773 +                        */
23774 +                       uint32_t max_periodic_len =
23775 +                           hc->multi_count * hc->max_packet;
23776 +                       if (hc->xfer_len > max_periodic_len) {
23777 +                               hc->xfer_len = max_periodic_len;
23778 +                       } else {
23779 +                       }
23780 +               } else if (hc->xfer_len > max_hc_xfer_size) {
23781 +                       /* Make sure that xfer_len is a multiple of max packet size. */
23782 +                       hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
23783 +               }
23784 +
23785 +               if (hc->xfer_len > 0) {
23786 +                       num_packets =
23787 +                           (hc->xfer_len + hc->max_packet -
23788 +                            1) / hc->max_packet;
23789 +                       if (num_packets > max_hc_pkt_count) {
23790 +                               num_packets = max_hc_pkt_count;
23791 +                               hc->xfer_len = num_packets * hc->max_packet;
23792 +                       }
23793 +               } else {
23794 +                       /* Need 1 packet for transfer length of 0. */
23795 +                       num_packets = 1;
23796 +               }
23797 +
23798 +               if (hc->ep_is_in) {
23799 +                       /* Always program an integral # of max packets for IN transfers. */
23800 +                       hc->xfer_len = num_packets * hc->max_packet;
23801 +               }
23802 +
23803 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23804 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23805 +                       /*
23806 +                        * Make sure that the multi_count field matches the
23807 +                        * actual transfer length.
23808 +                        */
23809 +                       hc->multi_count = num_packets;
23810 +               }
23811 +
23812 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23813 +                       set_pid_isoc(hc);
23814 +
23815 +               hctsiz.b.xfersize = hc->xfer_len;
23816 +       }
23817 +
23818 +       hc->start_pkt_count = num_packets;
23819 +       hctsiz.b.pktcnt = num_packets;
23820 +       hctsiz.b.pid = hc->data_pid_start;
23821 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23822 +
23823 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23824 +       DWC_DEBUGPL(DBG_HCDV, "  Xfer Size: %d\n", hctsiz.b.xfersize);
23825 +       DWC_DEBUGPL(DBG_HCDV, "  Num Pkts: %d\n", hctsiz.b.pktcnt);
23826 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
23827 +
23828 +       if (core_if->dma_enable) {
23829 +               dwc_dma_t dma_addr;
23830 +               if (hc->align_buff) {
23831 +                       dma_addr = hc->align_buff;
23832 +               } else {
23833 +                       dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);
23834 +               }
23835 +               DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);
23836 +       }
23837 +
23838 +       /* Start the split */
23839 +       if (hc->do_split) {
23840 +               hcsplt_data_t hcsplt;
23841 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
23842 +               hcsplt.b.spltena = 1;
23843 +               DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);
23844 +       }
23845 +
23846 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23847 +       hcchar.b.multicnt = hc->multi_count;
23848 +       hc_set_even_odd_frame(core_if, hc, &hcchar);
23849 +#ifdef DEBUG
23850 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23851 +       if (hcchar.b.chdis) {
23852 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23853 +                        __func__, hc->hc_num, hcchar.d32);
23854 +       }
23855 +#endif
23856 +
23857 +       /* Set host channel enable after all other setup is complete. */
23858 +       hcchar.b.chen = 1;
23859 +       hcchar.b.chdis = 0;
23860 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23861 +
23862 +       hc->xfer_started = 1;
23863 +       hc->requests++;
23864 +
23865 +       if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
23866 +               /* Load OUT packet into the appropriate Tx FIFO. */
23867 +               dwc_otg_hc_write_packet(core_if, hc);
23868 +       }
23869 +#ifdef DEBUG
23870 +       if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23871 +                DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
23872 +                            hc->hc_num, core_if);//GRAYG
23873 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23874 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
23875 +
23876 +               /* Start a timer for this transfer. */
23877 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23878 +       }
23879 +#endif
23880 +}
23881 +
23882 +/**
23883 + * This function does the setup for a data transfer for a host channel
23884 + * and starts the transfer in Descriptor DMA mode.
23885 + *
23886 + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
23887 + * Sets PID and NTD values. For periodic transfers
23888 + * initializes SCHED_INFO field with micro-frame bitmap.
23889 + *
23890 + * Initializes HCDMA register with descriptor list address and CTD value
23891 + * then starts the transfer via enabling the channel.
23892 + *
23893 + * @param core_if Programming view of DWC_otg controller.
23894 + * @param hc Information needed to initialize the host channel.
23895 + */
23896 +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23897 +{
23898 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23899 +       hcchar_data_t hcchar;
23900 +       hctsiz_data_t hctsiz;
23901 +       hcdma_data_t hcdma;
23902 +
23903 +       hctsiz.d32 = 0;
23904 +
23905 +       if (hc->do_ping)
23906 +               hctsiz.b_ddma.dopng = 1;
23907 +
23908 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23909 +               set_pid_isoc(hc);
23910 +
23911 +       /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
23912 +       hctsiz.b_ddma.pid = hc->data_pid_start;
23913 +       hctsiz.b_ddma.ntd = hc->ntd - 1;        /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
23914 +       hctsiz.b_ddma.schinfo = hc->schinfo;    /* Non-zero only for high-speed interrupt endpoints */
23915 +
23916 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23917 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
23918 +       DWC_DEBUGPL(DBG_HCDV, "  NTD: %d\n", hctsiz.b_ddma.ntd);
23919 +
23920 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23921 +
23922 +       hcdma.d32 = 0;
23923 +       hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;
23924 +
23925 +       /* Always start from first descriptor. */
23926 +       hcdma.b.ctd = 0;
23927 +       DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);
23928 +
23929 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23930 +       hcchar.b.multicnt = hc->multi_count;
23931 +
23932 +#ifdef DEBUG
23933 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23934 +       if (hcchar.b.chdis) {
23935 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23936 +                        __func__, hc->hc_num, hcchar.d32);
23937 +       }
23938 +#endif
23939 +
23940 +       /* Set host channel enable after all other setup is complete. */
23941 +       hcchar.b.chen = 1;
23942 +       hcchar.b.chdis = 0;
23943 +
23944 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23945 +
23946 +       hc->xfer_started = 1;
23947 +       hc->requests++;
23948 +
23949 +#ifdef DEBUG
23950 +       if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)
23951 +           && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
23952 +                DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
23953 +                            hc->hc_num, core_if);//GRAYG
23954 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23955 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
23956 +               /* Start a timer for this transfer. */
23957 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23958 +       }
23959 +#endif
23960 +
23961 +}
23962 +
23963 +/**
23964 + * This function continues a data transfer that was started by previous call
23965 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
23966 + * sufficient space in the request queue and Tx Data FIFO. This function
23967 + * should only be called in Slave mode. In DMA mode, the controller acts
23968 + * autonomously to complete transfers programmed to a host channel.
23969 + *
23970 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
23971 + * if there is any data remaining to be queued. For an IN transfer, another
23972 + * data packet is always requested. For the SETUP phase of a control transfer,
23973 + * this function does nothing.
23974 + *
23975 + * @return 1 if a new request is queued, 0 if no more requests are required
23976 + * for this transfer.
23977 + */
23978 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23979 +{
23980 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23981 +
23982 +       if (hc->do_split) {
23983 +               /* SPLITs always queue just once per channel */
23984 +               return 0;
23985 +       } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
23986 +               /* SETUPs are queued only once since they can't be NAKed. */
23987 +               return 0;
23988 +       } else if (hc->ep_is_in) {
23989 +               /*
23990 +                * Always queue another request for other IN transfers. If
23991 +                * back-to-back INs are issued and NAKs are received for both,
23992 +                * the driver may still be processing the first NAK when the
23993 +                * second NAK is received. When the interrupt handler clears
23994 +                * the NAK interrupt for the first NAK, the second NAK will
23995 +                * not be seen. So we can't depend on the NAK interrupt
23996 +                * handler to requeue a NAKed request. Instead, IN requests
23997 +                * are issued each time this function is called. When the
23998 +                * transfer completes, the extra requests for the channel will
23999 +                * be flushed.
24000 +                */
24001 +               hcchar_data_t hcchar;
24002 +               dwc_otg_hc_regs_t *hc_regs =
24003 +                   core_if->host_if->hc_regs[hc->hc_num];
24004 +
24005 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24006 +               hc_set_even_odd_frame(core_if, hc, &hcchar);
24007 +               hcchar.b.chen = 1;
24008 +               hcchar.b.chdis = 0;
24009 +               DWC_DEBUGPL(DBG_HCDV, "  IN xfer: hcchar = 0x%08x\n",
24010 +                           hcchar.d32);
24011 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24012 +               hc->requests++;
24013 +               return 1;
24014 +       } else {
24015 +               /* OUT transfers. */
24016 +               if (hc->xfer_count < hc->xfer_len) {
24017 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
24018 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
24019 +                               hcchar_data_t hcchar;
24020 +                               dwc_otg_hc_regs_t *hc_regs;
24021 +                               hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24022 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24023 +                               hc_set_even_odd_frame(core_if, hc, &hcchar);
24024 +                       }
24025 +
24026 +                       /* Load OUT packet into the appropriate Tx FIFO. */
24027 +                       dwc_otg_hc_write_packet(core_if, hc);
24028 +                       hc->requests++;
24029 +                       return 1;
24030 +               } else {
24031 +                       return 0;
24032 +               }
24033 +       }
24034 +}
24035 +
24036 +/**
24037 + * Starts a PING transfer. This function should only be called in Slave mode.
24038 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
24039 + */
24040 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24041 +{
24042 +       hcchar_data_t hcchar;
24043 +       hctsiz_data_t hctsiz;
24044 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24045 +
24046 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24047 +
24048 +       hctsiz.d32 = 0;
24049 +       hctsiz.b.dopng = 1;
24050 +       hctsiz.b.pktcnt = 1;
24051 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
24052 +
24053 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24054 +       hcchar.b.chen = 1;
24055 +       hcchar.b.chdis = 0;
24056 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24057 +}
24058 +
24059 +/*
24060 + * This function writes a packet into the Tx FIFO associated with the Host
24061 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
24062 + * Tx FIFO is written. For a channel associated with a periodic EP, the
24063 + * periodic Tx FIFO is written. This function should only be called in Slave
24064 + * mode.
24065 + *
24066 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
24067 + * then number of bytes written to the Tx FIFO.
24068 + */
24069 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24070 +{
24071 +       uint32_t i;
24072 +       uint32_t remaining_count;
24073 +       uint32_t byte_count;
24074 +       uint32_t dword_count;
24075 +
24076 +       uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
24077 +       uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
24078 +
24079 +       remaining_count = hc->xfer_len - hc->xfer_count;
24080 +       if (remaining_count > hc->max_packet) {
24081 +               byte_count = hc->max_packet;
24082 +       } else {
24083 +               byte_count = remaining_count;
24084 +       }
24085 +
24086 +       dword_count = (byte_count + 3) / 4;
24087 +
24088 +       if ((((unsigned long)data_buff) & 0x3) == 0) {
24089 +               /* xfer_buff is DWORD aligned. */
24090 +               for (i = 0; i < dword_count; i++, data_buff++) {
24091 +                       DWC_WRITE_REG32(data_fifo, *data_buff);
24092 +               }
24093 +       } else {
24094 +               /* xfer_buff is not DWORD aligned. */
24095 +               for (i = 0; i < dword_count; i++, data_buff++) {
24096 +                       uint32_t data;
24097 +                       data =
24098 +                           (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
24099 +                            16 | data_buff[3] << 24);
24100 +                       DWC_WRITE_REG32(data_fifo, data);
24101 +               }
24102 +       }
24103 +
24104 +       hc->xfer_count += byte_count;
24105 +       hc->xfer_buff += byte_count;
24106 +}
24107 +
24108 +/**
24109 + * Gets the current USB frame number. This is the frame number from the last
24110 + * SOF packet.
24111 + */
24112 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
24113 +{
24114 +       dsts_data_t dsts;
24115 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
24116 +
24117 +       /* read current frame/microframe number from DSTS register */
24118 +       return dsts.b.soffn;
24119 +}
24120 +
24121 +/**
24122 + * Calculates and gets the frame Interval value of HFIR register according PHY
24123 + * type and speed.The application can modify a value of HFIR register only after
24124 + * the Port Enable bit of the Host Port Control and Status register
24125 + * (HPRT.PrtEnaPort) has been set.
24126 +*/
24127 +
24128 +uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)
24129 +{
24130 +       gusbcfg_data_t usbcfg;
24131 +       hwcfg2_data_t hwcfg2;
24132 +       hprt0_data_t hprt0;
24133 +       int clock = 60;         // default value
24134 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
24135 +       hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
24136 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
24137 +       if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24138 +               clock = 60;
24139 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)
24140 +               clock = 48;
24141 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24142 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24143 +               clock = 30;
24144 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24145 +           !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24146 +               clock = 60;
24147 +       if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24148 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24149 +               clock = 48;
24150 +       if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)
24151 +               clock = 48;
24152 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)
24153 +               clock = 48;
24154 +       if (hprt0.b.prtspd == 0)
24155 +               /* High speed case */
24156 +               return 125 * clock;
24157 +       else
24158 +               /* FS/LS case */
24159 +               return 1000 * clock;
24160 +}
24161 +
24162 +/**
24163 + * This function reads a setup packet from the Rx FIFO into the destination
24164 + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
24165 + * Interrupt routine when a SETUP packet has been received in Slave mode.
24166 + *
24167 + * @param core_if Programming view of DWC_otg controller.
24168 + * @param dest Destination buffer for packet data.
24169 + */
24170 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
24171 +{
24172 +       device_grxsts_data_t status;
24173 +       /* Get the 8 bytes of a setup transaction data */
24174 +
24175 +       /* Pop 2 DWORDS off the receive data FIFO into memory */
24176 +       dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
24177 +       dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
24178 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
24179 +               status.d32 =
24180 +                   DWC_READ_REG32(&core_if->core_global_regs->grxstsp);
24181 +               DWC_DEBUGPL(DBG_ANY,
24182 +                           "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",
24183 +                           status.b.epnum, status.b.bcnt, status.b.pktsts,
24184 +                           status.b.fn, status.b.fn);
24185 +       }
24186 +}
24187 +
24188 +/**
24189 + * This function enables EP0 OUT to receive SETUP packets and configures EP0
24190 + * IN for transmitting packets. It is normally called when the
24191 + * "Enumeration Done" interrupt occurs.
24192 + *
24193 + * @param core_if Programming view of DWC_otg controller.
24194 + * @param ep The EP0 data.
24195 + */
24196 +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24197 +{
24198 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24199 +       dsts_data_t dsts;
24200 +       depctl_data_t diepctl;
24201 +       depctl_data_t doepctl;
24202 +       dctl_data_t dctl = {.d32 = 0 };
24203 +
24204 +       ep->stp_rollover = 0;
24205 +       /* Read the Device Status and Endpoint 0 Control registers */
24206 +       dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
24207 +       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
24208 +       doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
24209 +
24210 +       /* Set the MPS of the IN EP based on the enumeration speed */
24211 +       switch (dsts.b.enumspd) {
24212 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
24213 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
24214 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
24215 +               diepctl.b.mps = DWC_DEP0CTL_MPS_64;
24216 +               break;
24217 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
24218 +               diepctl.b.mps = DWC_DEP0CTL_MPS_8;
24219 +               break;
24220 +       }
24221 +
24222 +       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
24223 +
24224 +       /* Enable OUT EP for receive */
24225 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
24226 +       doepctl.b.epena = 1;
24227 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
24228 +       }
24229 +#ifdef VERBOSE
24230 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
24231 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
24232 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
24233 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
24234 +#endif
24235 +       dctl.b.cgnpinnak = 1;
24236 +
24237 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
24238 +       DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
24239 +                   DWC_READ_REG32(&dev_if->dev_global_regs->dctl));
24240 +
24241 +}
24242 +
24243 +/**
24244 + * This function activates an EP.  The Device EP control register for
24245 + * the EP is configured as defined in the ep structure. Note: This
24246 + * function is not used for EP0.
24247 + *
24248 + * @param core_if Programming view of DWC_otg controller.
24249 + * @param ep The EP to activate.
24250 + */
24251 +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24252 +{
24253 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24254 +       depctl_data_t depctl;
24255 +       volatile uint32_t *addr;
24256 +       daint_data_t daintmsk = {.d32 = 0 };
24257 +       dcfg_data_t dcfg;
24258 +       uint8_t i;
24259 +
24260 +       DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
24261 +                   (ep->is_in ? "IN" : "OUT"));
24262 +
24263 +#ifdef DWC_UTE_PER_IO
24264 +       ep->xiso_frame_num = 0xFFFFFFFF;
24265 +       ep->xiso_active_xfers = 0;
24266 +       ep->xiso_queued_xfers = 0;
24267 +#endif
24268 +       /* Read DEPCTLn register */
24269 +       if (ep->is_in == 1) {
24270 +               addr = &dev_if->in_ep_regs[ep->num]->diepctl;
24271 +               daintmsk.ep.in = 1 << ep->num;
24272 +       } else {
24273 +               addr = &dev_if->out_ep_regs[ep->num]->doepctl;
24274 +               daintmsk.ep.out = 1 << ep->num;
24275 +       }
24276 +
24277 +       /* If the EP is already active don't change the EP Control
24278 +        * register. */
24279 +       depctl.d32 = DWC_READ_REG32(addr);
24280 +       if (!depctl.b.usbactep) {
24281 +               depctl.b.mps = ep->maxpacket;
24282 +               depctl.b.eptype = ep->type;
24283 +               depctl.b.txfnum = ep->tx_fifo_num;
24284 +
24285 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24286 +                       depctl.b.setd0pid = 1;  // ???
24287 +               } else {
24288 +                       depctl.b.setd0pid = 1;
24289 +               }
24290 +               depctl.b.usbactep = 1;
24291 +
24292 +               /* Update nextep_seq array and EPMSCNT in DCFG*/
24293 +               if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) {       // NP IN EP
24294 +                       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24295 +                               if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
24296 +                               break;
24297 +                       }
24298 +                       core_if->nextep_seq[i] = ep->num;
24299 +                       core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
24300 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24301 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
24302 +                       dcfg.b.epmscnt++;
24303 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
24304 +
24305 +                       DWC_DEBUGPL(DBG_PCDV,
24306 +                                   "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24307 +                               __func__, core_if->first_in_nextep_seq);
24308 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24309 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n",
24310 +                                           core_if->nextep_seq[i]);
24311 +                       }
24312 +
24313 +               }
24314 +
24315 +
24316 +               DWC_WRITE_REG32(addr, depctl.d32);
24317 +               DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));
24318 +       }
24319 +
24320 +       /* Enable the Interrupt for this EP */
24321 +       if (core_if->multiproc_int_enable) {
24322 +               if (ep->is_in == 1) {
24323 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
24324 +                       diepmsk.b.xfercompl = 1;
24325 +                       diepmsk.b.timeout = 1;
24326 +                       diepmsk.b.epdisabled = 1;
24327 +                       diepmsk.b.ahberr = 1;
24328 +                       diepmsk.b.intknepmis = 1;
24329 +                       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
24330 +                               diepmsk.b.intknepmis = 0;
24331 +                       diepmsk.b.txfifoundrn = 1;      //?????
24332 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24333 +                               diepmsk.b.nak = 1;
24334 +                       }
24335 +
24336 +
24337 +
24338 +/*
24339 +                       if (core_if->dma_desc_enable) {
24340 +                               diepmsk.b.bna = 1;
24341 +                       }
24342 +*/
24343 +/*
24344 +                       if (core_if->dma_enable) {
24345 +                               doepmsk.b.nak = 1;
24346 +                       }
24347 +*/
24348 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24349 +                                       diepeachintmsk[ep->num], diepmsk.d32);
24350 +
24351 +               } else {
24352 +                       doepmsk_data_t doepmsk = {.d32 = 0 };
24353 +                       doepmsk.b.xfercompl = 1;
24354 +                       doepmsk.b.ahberr = 1;
24355 +                       doepmsk.b.epdisabled = 1;
24356 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24357 +                               doepmsk.b.outtknepdis = 1;
24358 +
24359 +/*
24360 +
24361 +                       if (core_if->dma_desc_enable) {
24362 +                               doepmsk.b.bna = 1;
24363 +                       }
24364 +*/
24365 +/*
24366 +                       doepmsk.b.babble = 1;
24367 +                       doepmsk.b.nyet = 1;
24368 +                       doepmsk.b.nak = 1;
24369 +*/
24370 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24371 +                                       doepeachintmsk[ep->num], doepmsk.d32);
24372 +               }
24373 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
24374 +                                0, daintmsk.d32);
24375 +       } else {
24376 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24377 +                       if (ep->is_in) {
24378 +                               diepmsk_data_t diepmsk = {.d32 = 0 };
24379 +                               diepmsk.b.nak = 1;
24380 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
24381 +                       } else {
24382 +                               doepmsk_data_t doepmsk = {.d32 = 0 };
24383 +                               doepmsk.b.outtknepdis = 1;
24384 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
24385 +                       }
24386 +               }
24387 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
24388 +                                0, daintmsk.d32);
24389 +       }
24390 +
24391 +       DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
24392 +                   DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));
24393 +
24394 +       ep->stall_clear_flag = 0;
24395 +
24396 +       return;
24397 +}
24398 +
24399 +/**
24400 + * This function deactivates an EP. This is done by clearing the USB Active
24401 + * EP bit in the Device EP control register. Note: This function is not used
24402 + * for EP0. EP0 cannot be deactivated.
24403 + *
24404 + * @param core_if Programming view of DWC_otg controller.
24405 + * @param ep The EP to deactivate.
24406 + */
24407 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24408 +{
24409 +       depctl_data_t depctl = {.d32 = 0 };
24410 +       volatile uint32_t *addr;
24411 +       daint_data_t daintmsk = {.d32 = 0 };
24412 +       dcfg_data_t dcfg;
24413 +       uint8_t i = 0;
24414 +
24415 +#ifdef DWC_UTE_PER_IO
24416 +       ep->xiso_frame_num = 0xFFFFFFFF;
24417 +       ep->xiso_active_xfers = 0;
24418 +       ep->xiso_queued_xfers = 0;
24419 +#endif
24420 +
24421 +       /* Read DEPCTLn register */
24422 +       if (ep->is_in == 1) {
24423 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
24424 +               daintmsk.ep.in = 1 << ep->num;
24425 +       } else {
24426 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
24427 +               daintmsk.ep.out = 1 << ep->num;
24428 +       }
24429 +
24430 +       depctl.d32 = DWC_READ_REG32(addr);
24431 +
24432 +       depctl.b.usbactep = 0;
24433 +
24434 +       /* Update nextep_seq array and EPMSCNT in DCFG*/
24435 +       if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN
24436 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24437 +                       if (core_if->nextep_seq[i] == ep->num)
24438 +                       break;
24439 +               }
24440 +               core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];
24441 +               if (core_if->first_in_nextep_seq == ep->num)
24442 +                       core_if->first_in_nextep_seq = i;
24443 +               core_if->nextep_seq[ep->num] = 0xff;
24444 +               depctl.b.nextep = 0;
24445 +               dcfg.d32 =
24446 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
24447 +               dcfg.b.epmscnt--;
24448 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
24449 +                               dcfg.d32);
24450 +
24451 +               DWC_DEBUGPL(DBG_PCDV,
24452 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24453 +                               __func__, core_if->first_in_nextep_seq);
24454 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24455 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
24456 +                       }
24457 +       }
24458 +
24459 +       if (ep->is_in == 1)
24460 +               depctl.b.txfnum = 0;
24461 +
24462 +       if (core_if->dma_desc_enable)
24463 +               depctl.b.epdis = 1;
24464 +
24465 +       DWC_WRITE_REG32(addr, depctl.d32);
24466 +       depctl.d32 = DWC_READ_REG32(addr);
24467 +       if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC
24468 +           && depctl.b.epena) {
24469 +               depctl_data_t depctl = {.d32 = 0};
24470 +               if (ep->is_in) {
24471 +                       diepint_data_t diepint = {.d32 = 0};
24472 +
24473 +                       depctl.b.snak = 1;
24474 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24475 +                                       diepctl, depctl.d32);
24476 +                       do {
24477 +                               dwc_udelay(10);
24478 +                               diepint.d32 =
24479 +                                   DWC_READ_REG32(&core_if->
24480 +                                                  dev_if->in_ep_regs[ep->num]->
24481 +                                                  diepint);
24482 +                       } while (!diepint.b.inepnakeff);
24483 +                       diepint.b.inepnakeff = 1;
24484 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24485 +                                       diepint, diepint.d32);
24486 +                       depctl.d32 = 0;
24487 +                       depctl.b.epdis = 1;
24488 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24489 +                                       diepctl, depctl.d32);
24490 +                       do {
24491 +                               dwc_udelay(10);
24492 +                               diepint.d32 =
24493 +                                   DWC_READ_REG32(&core_if->
24494 +                                                  dev_if->in_ep_regs[ep->num]->
24495 +                                                  diepint);
24496 +                       } while (!diepint.b.epdisabled);
24497 +                       diepint.b.epdisabled = 1;
24498 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24499 +                                       diepint, diepint.d32);
24500 +               } else {
24501 +                       dctl_data_t dctl = {.d32 = 0};
24502 +                       gintmsk_data_t gintsts = {.d32 = 0};
24503 +                       doepint_data_t doepint = {.d32 = 0};
24504 +                       dctl.b.sgoutnak = 1;
24505 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
24506 +                                        dctl, 0, dctl.d32);
24507 +                       do {
24508 +                               dwc_udelay(10);
24509 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
24510 +                       } while (!gintsts.b.goutnakeff);
24511 +                       gintsts.d32 = 0;
24512 +                       gintsts.b.goutnakeff = 1;
24513 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
24514 +
24515 +                       depctl.d32 = 0;
24516 +                       depctl.b.epdis = 1;
24517 +                       depctl.b.snak = 1;
24518 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
24519 +                       do
24520 +                       {
24521 +                               dwc_udelay(10);
24522 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
24523 +                                                                                       out_ep_regs[ep->num]->doepint);
24524 +                       } while (!doepint.b.epdisabled);
24525 +
24526 +                       doepint.b.epdisabled = 1;
24527 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
24528 +
24529 +                       dctl.d32 = 0;
24530 +                       dctl.b.cgoutnak = 1;
24531 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
24532 +               }
24533 +       }
24534 +
24535 +       /* Disable the Interrupt for this EP */
24536 +       if (core_if->multiproc_int_enable) {
24537 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
24538 +                                daintmsk.d32, 0);
24539 +
24540 +               if (ep->is_in == 1) {
24541 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24542 +                                       diepeachintmsk[ep->num], 0);
24543 +               } else {
24544 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24545 +                                       doepeachintmsk[ep->num], 0);
24546 +               }
24547 +       } else {
24548 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,
24549 +                                daintmsk.d32, 0);
24550 +       }
24551 +
24552 +}
24553 +
24554 +/**
24555 + * This function initializes dma descriptor chain.
24556 + *
24557 + * @param core_if Programming view of DWC_otg controller.
24558 + * @param ep The EP to start the transfer on.
24559 + */
24560 +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24561 +{
24562 +       dwc_otg_dev_dma_desc_t *dma_desc;
24563 +       uint32_t offset;
24564 +       uint32_t xfer_est;
24565 +       int i;
24566 +       unsigned maxxfer_local, total_len;
24567 +
24568 +       if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&
24569 +                                       (ep->maxpacket%4)) {
24570 +               maxxfer_local = ep->maxpacket;
24571 +               total_len = ep->xfer_len;
24572 +       } else {
24573 +               maxxfer_local = ep->maxxfer;
24574 +               total_len = ep->total_len;
24575 +       }
24576 +
24577 +       ep->desc_cnt = (total_len / maxxfer_local) +
24578 +            ((total_len % maxxfer_local) ? 1 : 0);
24579 +
24580 +       if (!ep->desc_cnt)
24581 +               ep->desc_cnt = 1;
24582 +
24583 +       if (ep->desc_cnt > MAX_DMA_DESC_CNT)
24584 +               ep->desc_cnt = MAX_DMA_DESC_CNT;
24585 +
24586 +       dma_desc = ep->desc_addr;
24587 +       if (maxxfer_local == ep->maxpacket) {
24588 +               if ((total_len % maxxfer_local) &&
24589 +                               (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
24590 +                       xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
24591 +                                       (total_len % maxxfer_local);
24592 +               } else
24593 +                       xfer_est = ep->desc_cnt * maxxfer_local;
24594 +       } else
24595 +               xfer_est = total_len;
24596 +       offset = 0;
24597 +       for (i = 0; i < ep->desc_cnt; ++i) {
24598 +               /** DMA Descriptor Setup */
24599 +               if (xfer_est > maxxfer_local) {
24600 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24601 +                       dma_desc->status.b.l = 0;
24602 +                       dma_desc->status.b.ioc = 0;
24603 +                       dma_desc->status.b.sp = 0;
24604 +                       dma_desc->status.b.bytes = maxxfer_local;
24605 +                       dma_desc->buf = ep->dma_addr + offset;
24606 +                       dma_desc->status.b.sts = 0;
24607 +                       dma_desc->status.b.bs = BS_HOST_READY;
24608 +
24609 +                       xfer_est -= maxxfer_local;
24610 +                       offset += maxxfer_local;
24611 +               } else {
24612 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24613 +                       dma_desc->status.b.l = 1;
24614 +                       dma_desc->status.b.ioc = 1;
24615 +                       if (ep->is_in) {
24616 +                               dma_desc->status.b.sp =
24617 +                                   (xfer_est %
24618 +                                    ep->maxpacket) ? 1 : ((ep->
24619 +                                                           sent_zlp) ? 1 : 0);
24620 +                               dma_desc->status.b.bytes = xfer_est;
24621 +                       } else {
24622 +                               if (maxxfer_local == ep->maxpacket)
24623 +                                       dma_desc->status.b.bytes = xfer_est;
24624 +                               else
24625 +                                       dma_desc->status.b.bytes =
24626 +                                               xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
24627 +                       }
24628 +
24629 +                       dma_desc->buf = ep->dma_addr + offset;
24630 +                       dma_desc->status.b.sts = 0;
24631 +                       dma_desc->status.b.bs = BS_HOST_READY;
24632 +               }
24633 +               dma_desc++;
24634 +       }
24635 +}
24636 +/**
24637 + * This function is called when to write ISOC data into appropriate dedicated
24638 + * periodic FIFO.
24639 + */
24640 +static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
24641 +{
24642 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24643 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
24644 +       dtxfsts_data_t txstatus = {.d32 = 0 };
24645 +       uint32_t len = 0;
24646 +       int epnum = dwc_ep->num;
24647 +       int dwords;
24648 +
24649 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
24650 +
24651 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
24652 +
24653 +       len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24654 +
24655 +       if (len > dwc_ep->maxpacket) {
24656 +               len = dwc_ep->maxpacket;
24657 +       }
24658 +
24659 +       dwords = (len + 3) / 4;
24660 +
24661 +       /* While there is space in the queue and space in the FIFO and
24662 +        * More data to tranfer, Write packets to the Tx FIFO */
24663 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24664 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
24665 +
24666 +       while (txstatus.b.txfspcavail > dwords &&
24667 +              dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {
24668 +               /* Write the FIFO */
24669 +               dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
24670 +
24671 +               len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24672 +               if (len > dwc_ep->maxpacket) {
24673 +                       len = dwc_ep->maxpacket;
24674 +               }
24675 +
24676 +               dwords = (len + 3) / 4;
24677 +               txstatus.d32 =
24678 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24679 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
24680 +                           txstatus.d32);
24681 +       }
24682 +
24683 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
24684 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
24685 +
24686 +       return 1;
24687 +}
24688 +/**
24689 + * This function does the setup for a data transfer for an EP and
24690 + * starts the transfer. For an IN transfer, the packets will be
24691 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
24692 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
24693 + *
24694 + * @param core_if Programming view of DWC_otg controller.
24695 + * @param ep The EP to start the transfer on.
24696 + */
24697 +
24698 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24699 +{
24700 +       depctl_data_t depctl;
24701 +       deptsiz_data_t deptsiz;
24702 +       gintmsk_data_t intr_mask = {.d32 = 0 };
24703 +
24704 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24705 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
24706 +                   "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
24707 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
24708 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
24709 +                   ep->total_len);
24710 +       /* IN endpoint */
24711 +       if (ep->is_in == 1) {
24712 +               dwc_otg_dev_in_ep_regs_t *in_regs =
24713 +                   core_if->dev_if->in_ep_regs[ep->num];
24714 +
24715 +               gnptxsts_data_t gtxstatus;
24716 +
24717 +               gtxstatus.d32 =
24718 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
24719 +
24720 +               if (core_if->en_multiple_tx_fifo == 0
24721 +                   && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {
24722 +#ifdef DEBUG
24723 +                       DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
24724 +#endif
24725 +                       return;
24726 +               }
24727 +
24728 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
24729 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
24730 +
24731 +               if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24732 +                       ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24733 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24734 +               else
24735 +                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
24736 +                                MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24737 +
24738 +
24739 +               /* Zero Length Packet? */
24740 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24741 +                       deptsiz.b.xfersize = 0;
24742 +                       deptsiz.b.pktcnt = 1;
24743 +               } else {
24744 +                       /* Program the transfer size and packet count
24745 +                        *      as follows: xfersize = N * maxpacket +
24746 +                        *      short_packet pktcnt = N + (short_packet
24747 +                        *      exist ? 1 : 0)
24748 +                        */
24749 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24750 +                       deptsiz.b.pktcnt =
24751 +                           (ep->xfer_len - ep->xfer_count - 1 +
24752 +                            ep->maxpacket) / ep->maxpacket;
24753 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24754 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24755 +                               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
24756 +                       }
24757 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24758 +                               deptsiz.b.mc = deptsiz.b.pktcnt;
24759 +               }
24760 +
24761 +               /* Write the DMA register */
24762 +               if (core_if->dma_enable) {
24763 +                       if (core_if->dma_desc_enable == 0) {
24764 +                               if (ep->type != DWC_OTG_EP_TYPE_ISOC)
24765 +                                       deptsiz.b.mc = 1;
24766 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
24767 +                                               deptsiz.d32);
24768 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
24769 +                                               (uint32_t) ep->dma_addr);
24770 +                       } else {
24771 +#ifdef DWC_UTE_CFI
24772 +                               /* The descriptor chain should be already initialized by now */
24773 +                               if (ep->buff_mode != BM_STANDARD) {
24774 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24775 +                                                       ep->descs_dma_addr);
24776 +                               } else {
24777 +#endif
24778 +                                       init_dma_desc_chain(core_if, ep);
24779 +                               /** DIEPDMAn Register write */
24780 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24781 +                                                       ep->dma_desc_addr);
24782 +#ifdef DWC_UTE_CFI
24783 +                               }
24784 +#endif
24785 +                       }
24786 +               } else {
24787 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
24788 +                       if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
24789 +                               /**
24790 +                                * Enable the Non-Periodic Tx FIFO empty interrupt,
24791 +                                * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
24792 +                                * the data will be written into the fifo by the ISR.
24793 +                                */
24794 +                               if (core_if->en_multiple_tx_fifo == 0) {
24795 +                                       intr_mask.b.nptxfempty = 1;
24796 +                                       DWC_MODIFY_REG32
24797 +                                           (&core_if->core_global_regs->gintmsk,
24798 +                                            intr_mask.d32, intr_mask.d32);
24799 +                               } else {
24800 +                                       /* Enable the Tx FIFO Empty Interrupt for this EP */
24801 +                                       if (ep->xfer_len > 0) {
24802 +                                               uint32_t fifoemptymsk = 0;
24803 +                                               fifoemptymsk = 1 << ep->num;
24804 +                                               DWC_MODIFY_REG32
24805 +                                                   (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
24806 +                                                    0, fifoemptymsk);
24807 +
24808 +                                       }
24809 +                               }
24810 +                       }  else {
24811 +                                        write_isoc_tx_fifo(core_if, ep);
24812 +                       }
24813 +               }
24814 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
24815 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24816 +
24817 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24818 +                       dsts_data_t dsts = {.d32 = 0};
24819 +                       if (ep->bInterval == 1) {
24820 +                               dsts.d32 =
24821 +                                   DWC_READ_REG32(&core_if->dev_if->
24822 +                                                  dev_global_regs->dsts);
24823 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
24824 +                               if (ep->frame_num > 0x3FFF) {
24825 +                                       ep->frm_overrun = 1;
24826 +                                       ep->frame_num &= 0x3FFF;
24827 +                               } else
24828 +                                       ep->frm_overrun = 0;
24829 +                               if (ep->frame_num & 0x1) {
24830 +                                       depctl.b.setd1pid = 1;
24831 +                               } else {
24832 +                                       depctl.b.setd0pid = 1;
24833 +                               }
24834 +                       }
24835 +               }
24836 +               /* EP enable, IN data in FIFO */
24837 +               depctl.b.cnak = 1;
24838 +               depctl.b.epena = 1;
24839 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
24840 +
24841 +       } else {
24842 +               /* OUT endpoint */
24843 +               dwc_otg_dev_out_ep_regs_t *out_regs =
24844 +                   core_if->dev_if->out_ep_regs[ep->num];
24845 +
24846 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
24847 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
24848 +
24849 +               if (!core_if->dma_desc_enable) {
24850 +                       if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24851 +                               ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24852 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24853 +                else
24854 +                                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len
24855 +                                       - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24856 +               }
24857 +
24858 +               /* Program the transfer size and packet count as follows:
24859 +                *
24860 +                *      pktcnt = N
24861 +                *      xfersize = N * maxpacket
24862 +                */
24863 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24864 +                       /* Zero Length Packet */
24865 +                       deptsiz.b.xfersize = ep->maxpacket;
24866 +                       deptsiz.b.pktcnt = 1;
24867 +               } else {
24868 +                       deptsiz.b.pktcnt =
24869 +                           (ep->xfer_len - ep->xfer_count +
24870 +                            (ep->maxpacket - 1)) / ep->maxpacket;
24871 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24872 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24873 +                       }
24874 +                       if (!core_if->dma_desc_enable) {
24875 +                               ep->xfer_len =
24876 +                                       deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
24877 +                       }
24878 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24879 +               }
24880 +
24881 +               DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
24882 +                           ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
24883 +
24884 +               if (core_if->dma_enable) {
24885 +                       if (!core_if->dma_desc_enable) {
24886 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
24887 +                                               deptsiz.d32);
24888 +
24889 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
24890 +                                               (uint32_t) ep->dma_addr);
24891 +                       } else {
24892 +#ifdef DWC_UTE_CFI
24893 +                               /* The descriptor chain should be already initialized by now */
24894 +                               if (ep->buff_mode != BM_STANDARD) {
24895 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
24896 +                                                       ep->descs_dma_addr);
24897 +                               } else {
24898 +#endif
24899 +                                       /** This is used for interrupt out transfers*/
24900 +                                       if (!ep->xfer_len)
24901 +                                               ep->xfer_len = ep->total_len;
24902 +                                       init_dma_desc_chain(core_if, ep);
24903 +
24904 +                                       if (core_if->core_params->dev_out_nak) {
24905 +                                               if (ep->type == DWC_OTG_EP_TYPE_BULK) {
24906 +                                                       deptsiz.b.pktcnt = (ep->total_len +
24907 +                                                               (ep->maxpacket - 1)) / ep->maxpacket;
24908 +                                                       deptsiz.b.xfersize = ep->total_len;
24909 +                                                       /* Remember initial value of doeptsiz */
24910 +                                                       core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
24911 +                                                       DWC_WRITE_REG32(&out_regs->doeptsiz,
24912 +                                                               deptsiz.d32);
24913 +                                               }
24914 +                                       }
24915 +                               /** DOEPDMAn Register write */
24916 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
24917 +                                                       ep->dma_desc_addr);
24918 +#ifdef DWC_UTE_CFI
24919 +                               }
24920 +#endif
24921 +                       }
24922 +               } else {
24923 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
24924 +               }
24925 +
24926 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24927 +                       dsts_data_t dsts = {.d32 = 0};
24928 +                       if (ep->bInterval == 1) {
24929 +                               dsts.d32 =
24930 +                                   DWC_READ_REG32(&core_if->dev_if->
24931 +                                                  dev_global_regs->dsts);
24932 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
24933 +                               if (ep->frame_num > 0x3FFF) {
24934 +                                       ep->frm_overrun = 1;
24935 +                                       ep->frame_num &= 0x3FFF;
24936 +                               } else
24937 +                                       ep->frm_overrun = 0;
24938 +
24939 +                               if (ep->frame_num & 0x1) {
24940 +                                       depctl.b.setd1pid = 1;
24941 +                               } else {
24942 +                                       depctl.b.setd0pid = 1;
24943 +                               }
24944 +                       }
24945 +               }
24946 +
24947 +               /* EP enable */
24948 +               depctl.b.cnak = 1;
24949 +               depctl.b.epena = 1;
24950 +
24951 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
24952 +
24953 +               DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
24954 +                           DWC_READ_REG32(&out_regs->doepctl),
24955 +                           DWC_READ_REG32(&out_regs->doeptsiz));
24956 +               DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
24957 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
24958 +                                          daintmsk),
24959 +                           DWC_READ_REG32(&core_if->core_global_regs->
24960 +                                          gintmsk));
24961 +
24962 +               /* Timer is scheduling only for out bulk transfers for
24963 +                * "Device DDMA OUT NAK Enhancement" feature to inform user
24964 +                * about received data payload in case of timeout
24965 +                */
24966 +               if (core_if->core_params->dev_out_nak) {
24967 +                       if (ep->type == DWC_OTG_EP_TYPE_BULK) {
24968 +                               core_if->ep_xfer_info[ep->num].core_if = core_if;
24969 +                               core_if->ep_xfer_info[ep->num].ep = ep;
24970 +                               core_if->ep_xfer_info[ep->num].state = 1;
24971 +
24972 +                               /* Start a timer for this transfer. */
24973 +                               DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);
24974 +                       }
24975 +               }
24976 +       }
24977 +}
24978 +
24979 +/**
24980 + * This function setup a zero length transfer in Buffer DMA and
24981 + * Slave modes for usb requests with zero field set
24982 + *
24983 + * @param core_if Programming view of DWC_otg controller.
24984 + * @param ep The EP to start the transfer on.
24985 + *
24986 + */
24987 +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24988 +{
24989 +
24990 +       depctl_data_t depctl;
24991 +       deptsiz_data_t deptsiz;
24992 +       gintmsk_data_t intr_mask = {.d32 = 0 };
24993 +
24994 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24995 +       DWC_PRINTF("zero length transfer is called\n");
24996 +
24997 +       /* IN endpoint */
24998 +       if (ep->is_in == 1) {
24999 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25000 +                   core_if->dev_if->in_ep_regs[ep->num];
25001 +
25002 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
25003 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
25004 +
25005 +               deptsiz.b.xfersize = 0;
25006 +               deptsiz.b.pktcnt = 1;
25007 +
25008 +               /* Write the DMA register */
25009 +               if (core_if->dma_enable) {
25010 +                       if (core_if->dma_desc_enable == 0) {
25011 +                               deptsiz.b.mc = 1;
25012 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25013 +                                               deptsiz.d32);
25014 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25015 +                                               (uint32_t) ep->dma_addr);
25016 +                       }
25017 +               } else {
25018 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25019 +                       /**
25020 +                        * Enable the Non-Periodic Tx FIFO empty interrupt,
25021 +                        * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
25022 +                        * the data will be written into the fifo by the ISR.
25023 +                        */
25024 +                       if (core_if->en_multiple_tx_fifo == 0) {
25025 +                               intr_mask.b.nptxfempty = 1;
25026 +                               DWC_MODIFY_REG32(&core_if->
25027 +                                                core_global_regs->gintmsk,
25028 +                                                intr_mask.d32, intr_mask.d32);
25029 +                       } else {
25030 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25031 +                               if (ep->xfer_len > 0) {
25032 +                                       uint32_t fifoemptymsk = 0;
25033 +                                       fifoemptymsk = 1 << ep->num;
25034 +                                       DWC_MODIFY_REG32(&core_if->
25035 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25036 +                                                        0, fifoemptymsk);
25037 +                               }
25038 +                       }
25039 +               }
25040 +
25041 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25042 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25043 +               /* EP enable, IN data in FIFO */
25044 +               depctl.b.cnak = 1;
25045 +               depctl.b.epena = 1;
25046 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25047 +
25048 +       } else {
25049 +               /* OUT endpoint */
25050 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25051 +                   core_if->dev_if->out_ep_regs[ep->num];
25052 +
25053 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
25054 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
25055 +
25056 +               /* Zero Length Packet */
25057 +               deptsiz.b.xfersize = ep->maxpacket;
25058 +               deptsiz.b.pktcnt = 1;
25059 +
25060 +               if (core_if->dma_enable) {
25061 +                       if (!core_if->dma_desc_enable) {
25062 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25063 +                                               deptsiz.d32);
25064 +
25065 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25066 +                                               (uint32_t) ep->dma_addr);
25067 +                       }
25068 +               } else {
25069 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25070 +               }
25071 +
25072 +               /* EP enable */
25073 +               depctl.b.cnak = 1;
25074 +               depctl.b.epena = 1;
25075 +
25076 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25077 +
25078 +       }
25079 +}
25080 +
25081 +/**
25082 + * This function does the setup for a data transfer for EP0 and starts
25083 + * the transfer.  For an IN transfer, the packets will be loaded into
25084 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
25085 + * unloaded from the Rx FIFO in the ISR.
25086 + *
25087 + * @param core_if Programming view of DWC_otg controller.
25088 + * @param ep The EP0 data.
25089 + */
25090 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25091 +{
25092 +       depctl_data_t depctl;
25093 +       deptsiz0_data_t deptsiz;
25094 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25095 +       dwc_otg_dev_dma_desc_t *dma_desc;
25096 +
25097 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
25098 +                   "xfer_buff=%p start_xfer_buff=%p \n",
25099 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
25100 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
25101 +
25102 +       ep->total_len = ep->xfer_len;
25103 +
25104 +       /* IN endpoint */
25105 +       if (ep->is_in == 1) {
25106 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25107 +                   core_if->dev_if->in_ep_regs[0];
25108 +
25109 +               gnptxsts_data_t gtxstatus;
25110 +
25111 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25112 +                       depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25113 +                       if (depctl.b.epena)
25114 +                               return;
25115 +               }
25116 +
25117 +               gtxstatus.d32 =
25118 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25119 +
25120 +               /* If dedicated FIFO every time flush fifo before enable ep*/
25121 +               if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)
25122 +                       dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
25123 +
25124 +               if (core_if->en_multiple_tx_fifo == 0
25125 +                   && gtxstatus.b.nptxqspcavail == 0
25126 +                   && !core_if->dma_enable) {
25127 +#ifdef DEBUG
25128 +                       deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25129 +                       DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
25130 +                                   DWC_READ_REG32(&in_regs->diepctl));
25131 +                       DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
25132 +                                   deptsiz.d32,
25133 +                                   deptsiz.b.xfersize, deptsiz.b.pktcnt);
25134 +                       DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
25135 +                                  gtxstatus.d32);
25136 +#endif
25137 +                       return;
25138 +               }
25139 +
25140 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25141 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25142 +
25143 +               /* Zero Length Packet? */
25144 +               if (ep->xfer_len == 0) {
25145 +                       deptsiz.b.xfersize = 0;
25146 +                       deptsiz.b.pktcnt = 1;
25147 +               } else {
25148 +                       /* Program the transfer size and packet count
25149 +                        *      as follows: xfersize = N * maxpacket +
25150 +                        *      short_packet pktcnt = N + (short_packet
25151 +                        *      exist ? 1 : 0)
25152 +                        */
25153 +                       if (ep->xfer_len > ep->maxpacket) {
25154 +                               ep->xfer_len = ep->maxpacket;
25155 +                               deptsiz.b.xfersize = ep->maxpacket;
25156 +                       } else {
25157 +                               deptsiz.b.xfersize = ep->xfer_len;
25158 +                       }
25159 +                       deptsiz.b.pktcnt = 1;
25160 +
25161 +               }
25162 +               DWC_DEBUGPL(DBG_PCDV,
25163 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25164 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25165 +                           deptsiz.d32);
25166 +
25167 +               /* Write the DMA register */
25168 +               if (core_if->dma_enable) {
25169 +                       if (core_if->dma_desc_enable == 0) {
25170 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25171 +                                               deptsiz.d32);
25172 +
25173 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25174 +                                               (uint32_t) ep->dma_addr);
25175 +                       } else {
25176 +                               dma_desc = core_if->dev_if->in_desc_addr;
25177 +
25178 +                               /** DMA Descriptor Setup */
25179 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25180 +                               dma_desc->status.b.l = 1;
25181 +                               dma_desc->status.b.ioc = 1;
25182 +                               dma_desc->status.b.sp =
25183 +                                   (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25184 +                               dma_desc->status.b.bytes = ep->xfer_len;
25185 +                               dma_desc->buf = ep->dma_addr;
25186 +                               dma_desc->status.b.sts = 0;
25187 +                               dma_desc->status.b.bs = BS_HOST_READY;
25188 +
25189 +                               /** DIEPDMA0 Register write */
25190 +                               DWC_WRITE_REG32(&in_regs->diepdma,
25191 +                                               core_if->
25192 +                                               dev_if->dma_in_desc_addr);
25193 +                       }
25194 +               } else {
25195 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25196 +               }
25197 +
25198 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25199 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25200 +               /* EP enable, IN data in FIFO */
25201 +               depctl.b.cnak = 1;
25202 +               depctl.b.epena = 1;
25203 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25204 +
25205 +               /**
25206 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25207 +                * data will be written into the fifo by the ISR.
25208 +                */
25209 +               if (!core_if->dma_enable) {
25210 +                       if (core_if->en_multiple_tx_fifo == 0) {
25211 +                               intr_mask.b.nptxfempty = 1;
25212 +                               DWC_MODIFY_REG32(&core_if->
25213 +                                                core_global_regs->gintmsk,
25214 +                                                intr_mask.d32, intr_mask.d32);
25215 +                       } else {
25216 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25217 +                               if (ep->xfer_len > 0) {
25218 +                                       uint32_t fifoemptymsk = 0;
25219 +                                       fifoemptymsk |= 1 << ep->num;
25220 +                                       DWC_MODIFY_REG32(&core_if->
25221 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25222 +                                                        0, fifoemptymsk);
25223 +                               }
25224 +                       }
25225 +               }
25226 +       } else {
25227 +               /* OUT endpoint */
25228 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25229 +                   core_if->dev_if->out_ep_regs[0];
25230 +
25231 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25232 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25233 +
25234 +               /* Program the transfer size and packet count as follows:
25235 +                *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))
25236 +                *      pktcnt = N                                                                                      */
25237 +               /* Zero Length Packet */
25238 +               deptsiz.b.xfersize = ep->maxpacket;
25239 +               deptsiz.b.pktcnt = 1;
25240 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
25241 +                       deptsiz.b.supcnt = 3;
25242 +
25243 +               DWC_DEBUGPL(DBG_PCDV, "len=%d  xfersize=%d pktcnt=%d\n",
25244 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
25245 +
25246 +               if (core_if->dma_enable) {
25247 +                       if (!core_if->dma_desc_enable) {
25248 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25249 +                                               deptsiz.d32);
25250 +
25251 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25252 +                                               (uint32_t) ep->dma_addr);
25253 +                       } else {
25254 +                               dma_desc = core_if->dev_if->out_desc_addr;
25255 +
25256 +                               /** DMA Descriptor Setup */
25257 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25258 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25259 +                                       dma_desc->status.b.mtrf = 0;
25260 +                                       dma_desc->status.b.sr = 0;
25261 +                               }
25262 +                               dma_desc->status.b.l = 1;
25263 +                               dma_desc->status.b.ioc = 1;
25264 +                               dma_desc->status.b.bytes = ep->maxpacket;
25265 +                               dma_desc->buf = ep->dma_addr;
25266 +                               dma_desc->status.b.sts = 0;
25267 +                               dma_desc->status.b.bs = BS_HOST_READY;
25268 +
25269 +                               /** DOEPDMA0 Register write */
25270 +                               DWC_WRITE_REG32(&out_regs->doepdma,
25271 +                                               core_if->dev_if->
25272 +                                               dma_out_desc_addr);
25273 +                       }
25274 +               } else {
25275 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25276 +               }
25277 +
25278 +               /* EP enable */
25279 +               depctl.b.cnak = 1;
25280 +               depctl.b.epena = 1;
25281 +               DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
25282 +       }
25283 +}
25284 +
25285 +/**
25286 + * This function continues control IN transfers started by
25287 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
25288 + * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
25289 + * bit for the packet count.
25290 + *
25291 + * @param core_if Programming view of DWC_otg controller.
25292 + * @param ep The EP0 data.
25293 + */
25294 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25295 +{
25296 +       depctl_data_t depctl;
25297 +       deptsiz0_data_t deptsiz;
25298 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25299 +       dwc_otg_dev_dma_desc_t *dma_desc;
25300 +
25301 +       if (ep->is_in == 1) {
25302 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25303 +                   core_if->dev_if->in_ep_regs[0];
25304 +               gnptxsts_data_t tx_status = {.d32 = 0 };
25305 +
25306 +               tx_status.d32 =
25307 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25308 +               /** @todo Should there be check for room in the Tx
25309 +                * Status Queue.  If not remove the code above this comment. */
25310 +
25311 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25312 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25313 +
25314 +               /* Program the transfer size and packet count
25315 +                *      as follows: xfersize = N * maxpacket +
25316 +                *      short_packet pktcnt = N + (short_packet
25317 +                *      exist ? 1 : 0)
25318 +                */
25319 +
25320 +               if (core_if->dma_desc_enable == 0) {
25321 +                       deptsiz.b.xfersize =
25322 +                           (ep->total_len - ep->xfer_count) >
25323 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25324 +                                                            ep->xfer_count);
25325 +                       deptsiz.b.pktcnt = 1;
25326 +                       if (core_if->dma_enable == 0) {
25327 +                               ep->xfer_len += deptsiz.b.xfersize;
25328 +                       } else {
25329 +                               ep->xfer_len = deptsiz.b.xfersize;
25330 +                       }
25331 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25332 +               } else {
25333 +                       ep->xfer_len =
25334 +                           (ep->total_len - ep->xfer_count) >
25335 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25336 +                                                            ep->xfer_count);
25337 +
25338 +                       dma_desc = core_if->dev_if->in_desc_addr;
25339 +
25340 +                       /** DMA Descriptor Setup */
25341 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25342 +                       dma_desc->status.b.l = 1;
25343 +                       dma_desc->status.b.ioc = 1;
25344 +                       dma_desc->status.b.sp =
25345 +                           (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25346 +                       dma_desc->status.b.bytes = ep->xfer_len;
25347 +                       dma_desc->buf = ep->dma_addr;
25348 +                       dma_desc->status.b.sts = 0;
25349 +                       dma_desc->status.b.bs = BS_HOST_READY;
25350 +
25351 +                       /** DIEPDMA0 Register write */
25352 +                       DWC_WRITE_REG32(&in_regs->diepdma,
25353 +                                       core_if->dev_if->dma_in_desc_addr);
25354 +               }
25355 +
25356 +               DWC_DEBUGPL(DBG_PCDV,
25357 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25358 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25359 +                           deptsiz.d32);
25360 +
25361 +               /* Write the DMA register */
25362 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25363 +                       if (core_if->dma_desc_enable == 0)
25364 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25365 +                                               (uint32_t) ep->dma_addr);
25366 +               }
25367 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25368 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25369 +               /* EP enable, IN data in FIFO */
25370 +               depctl.b.cnak = 1;
25371 +               depctl.b.epena = 1;
25372 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25373 +
25374 +               /**
25375 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25376 +                * data will be written into the fifo by the ISR.
25377 +                */
25378 +               if (!core_if->dma_enable) {
25379 +                       if (core_if->en_multiple_tx_fifo == 0) {
25380 +                               /* First clear it from GINTSTS */
25381 +                               intr_mask.b.nptxfempty = 1;
25382 +                               DWC_MODIFY_REG32(&core_if->
25383 +                                                core_global_regs->gintmsk,
25384 +                                                intr_mask.d32, intr_mask.d32);
25385 +
25386 +                       } else {
25387 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25388 +                               if (ep->xfer_len > 0) {
25389 +                                       uint32_t fifoemptymsk = 0;
25390 +                                       fifoemptymsk |= 1 << ep->num;
25391 +                                       DWC_MODIFY_REG32(&core_if->
25392 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25393 +                                                        0, fifoemptymsk);
25394 +                               }
25395 +                       }
25396 +               }
25397 +       } else {
25398 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25399 +                   core_if->dev_if->out_ep_regs[0];
25400 +
25401 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25402 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25403 +
25404 +               /* Program the transfer size and packet count
25405 +                *      as follows: xfersize = N * maxpacket +
25406 +                *      short_packet pktcnt = N + (short_packet
25407 +                *      exist ? 1 : 0)
25408 +                */
25409 +               deptsiz.b.xfersize = ep->maxpacket;
25410 +               deptsiz.b.pktcnt = 1;
25411 +
25412 +               if (core_if->dma_desc_enable == 0) {
25413 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25414 +               } else {
25415 +                       dma_desc = core_if->dev_if->out_desc_addr;
25416 +
25417 +                       /** DMA Descriptor Setup */
25418 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25419 +                       dma_desc->status.b.l = 1;
25420 +                       dma_desc->status.b.ioc = 1;
25421 +                       dma_desc->status.b.bytes = ep->maxpacket;
25422 +                       dma_desc->buf = ep->dma_addr;
25423 +                       dma_desc->status.b.sts = 0;
25424 +                       dma_desc->status.b.bs = BS_HOST_READY;
25425 +
25426 +                       /** DOEPDMA0 Register write */
25427 +                       DWC_WRITE_REG32(&out_regs->doepdma,
25428 +                                       core_if->dev_if->dma_out_desc_addr);
25429 +               }
25430 +
25431 +               DWC_DEBUGPL(DBG_PCDV,
25432 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25433 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25434 +                           deptsiz.d32);
25435 +
25436 +               /* Write the DMA register */
25437 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25438 +                       if (core_if->dma_desc_enable == 0)
25439 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25440 +                                               (uint32_t) ep->dma_addr);
25441 +
25442 +               }
25443 +
25444 +               /* EP enable, IN data in FIFO */
25445 +               depctl.b.cnak = 1;
25446 +               depctl.b.epena = 1;
25447 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25448 +
25449 +       }
25450 +}
25451 +
25452 +#ifdef DEBUG
25453 +void dump_msg(const u8 * buf, unsigned int length)
25454 +{
25455 +       unsigned int start, num, i;
25456 +       char line[52], *p;
25457 +
25458 +       if (length >= 512)
25459 +               return;
25460 +       start = 0;
25461 +       while (length > 0) {
25462 +               num = length < 16u ? length : 16u;
25463 +               p = line;
25464 +               for (i = 0; i < num; ++i) {
25465 +                       if (i == 8)
25466 +                               *p++ = ' ';
25467 +                       DWC_SPRINTF(p, " %02x", buf[i]);
25468 +                       p += 3;
25469 +               }
25470 +               *p = 0;
25471 +               DWC_PRINTF("%6x: %s\n", start, line);
25472 +               buf += num;
25473 +               start += num;
25474 +               length -= num;
25475 +       }
25476 +}
25477 +#else
25478 +static inline void dump_msg(const u8 * buf, unsigned int length)
25479 +{
25480 +}
25481 +#endif
25482 +
25483 +/**
25484 + * This function writes a packet into the Tx FIFO associated with the
25485 + * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For
25486 + * periodic EPs the periodic Tx FIFO associated with the EP is written
25487 + * with all packets for the next micro-frame.
25488 + *
25489 + * @param core_if Programming view of DWC_otg controller.
25490 + * @param ep The EP to write packet for.
25491 + * @param dma Indicates if DMA is being used.
25492 + */
25493 +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
25494 +                            int dma)
25495 +{
25496 +       /**
25497 +        * The buffer is padded to DWORD on a per packet basis in
25498 +        * slave/dma mode if the MPS is not DWORD aligned. The last
25499 +        * packet, if short, is also padded to a multiple of DWORD.
25500 +        *
25501 +        * ep->xfer_buff always starts DWORD aligned in memory and is a
25502 +        * multiple of DWORD in length
25503 +        *
25504 +        * ep->xfer_len can be any number of bytes
25505 +        *
25506 +        * ep->xfer_count is a multiple of ep->maxpacket until the last
25507 +        *      packet
25508 +        *
25509 +        * FIFO access is DWORD */
25510 +
25511 +       uint32_t i;
25512 +       uint32_t byte_count;
25513 +       uint32_t dword_count;
25514 +       uint32_t *fifo;
25515 +       uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
25516 +
25517 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
25518 +                   ep);
25519 +       if (ep->xfer_count >= ep->xfer_len) {
25520 +               DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
25521 +               return;
25522 +       }
25523 +
25524 +       /* Find the byte length of the packet either short packet or MPS */
25525 +       if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
25526 +               byte_count = ep->xfer_len - ep->xfer_count;
25527 +       } else {
25528 +               byte_count = ep->maxpacket;
25529 +       }
25530 +
25531 +       /* Find the DWORD length, padded by extra bytes as neccessary if MPS
25532 +        * is not a multiple of DWORD */
25533 +       dword_count = (byte_count + 3) / 4;
25534 +
25535 +#ifdef VERBOSE
25536 +       dump_msg(ep->xfer_buff, byte_count);
25537 +#endif
25538 +
25539 +       /**@todo NGS Where are the Periodic Tx FIFO addresses
25540 +        * intialized?  What should this be? */
25541 +
25542 +       fifo = core_if->data_fifo[ep->num];
25543 +
25544 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
25545 +                   fifo, data_buff, *data_buff, byte_count);
25546 +
25547 +       if (!dma) {
25548 +               for (i = 0; i < dword_count; i++, data_buff++) {
25549 +                       DWC_WRITE_REG32(fifo, *data_buff);
25550 +               }
25551 +       }
25552 +
25553 +       ep->xfer_count += byte_count;
25554 +       ep->xfer_buff += byte_count;
25555 +       ep->dma_addr += byte_count;
25556 +}
25557 +
25558 +/**
25559 + * Set the EP STALL.
25560 + *
25561 + * @param core_if Programming view of DWC_otg controller.
25562 + * @param ep The EP to set the stall on.
25563 + */
25564 +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25565 +{
25566 +       depctl_data_t depctl;
25567 +       volatile uint32_t *depctl_addr;
25568 +
25569 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25570 +                   (ep->is_in ? "IN" : "OUT"));
25571 +
25572 +       if (ep->is_in == 1) {
25573 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25574 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25575 +
25576 +               /* set the disable and stall bits */
25577 +               if (depctl.b.epena) {
25578 +                       depctl.b.epdis = 1;
25579 +               }
25580 +               depctl.b.stall = 1;
25581 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25582 +       } else {
25583 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25584 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25585 +
25586 +               /* set the stall bit */
25587 +               depctl.b.stall = 1;
25588 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25589 +       }
25590 +
25591 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25592 +
25593 +       return;
25594 +}
25595 +
25596 +/**
25597 + * Clear the EP STALL.
25598 + *
25599 + * @param core_if Programming view of DWC_otg controller.
25600 + * @param ep The EP to clear stall from.
25601 + */
25602 +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25603 +{
25604 +       depctl_data_t depctl;
25605 +       volatile uint32_t *depctl_addr;
25606 +
25607 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25608 +                   (ep->is_in ? "IN" : "OUT"));
25609 +
25610 +       if (ep->is_in == 1) {
25611 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25612 +       } else {
25613 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25614 +       }
25615 +
25616 +       depctl.d32 = DWC_READ_REG32(depctl_addr);
25617 +
25618 +       /* clear the stall bits */
25619 +       depctl.b.stall = 0;
25620 +
25621 +       /*
25622 +        * USB Spec 9.4.5: For endpoints using data toggle, regardless
25623 +        * of whether an endpoint has the Halt feature set, a
25624 +        * ClearFeature(ENDPOINT_HALT) request always results in the
25625 +        * data toggle being reinitialized to DATA0.
25626 +        */
25627 +       if (ep->type == DWC_OTG_EP_TYPE_INTR ||
25628 +           ep->type == DWC_OTG_EP_TYPE_BULK) {
25629 +               depctl.b.setd0pid = 1;  /* DATA0 */
25630 +       }
25631 +
25632 +       DWC_WRITE_REG32(depctl_addr, depctl.d32);
25633 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25634 +       return;
25635 +}
25636 +
25637 +/**
25638 + * This function reads a packet from the Rx FIFO into the destination
25639 + * buffer. To read SETUP data use dwc_otg_read_setup_packet.
25640 + *
25641 + * @param core_if Programming view of DWC_otg controller.
25642 + * @param dest   Destination buffer for the packet.
25643 + * @param bytes  Number of bytes to copy to the destination.
25644 + */
25645 +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
25646 +                        uint8_t * dest, uint16_t bytes)
25647 +{
25648 +       int i;
25649 +       int word_count = (bytes + 3) / 4;
25650 +
25651 +       volatile uint32_t *fifo = core_if->data_fifo[0];
25652 +       uint32_t *data_buff = (uint32_t *) dest;
25653 +
25654 +       /**
25655 +        * @todo Account for the case where _dest is not dword aligned. This
25656 +        * requires reading data from the FIFO into a uint32_t temp buffer,
25657 +        * then moving it into the data buffer.
25658 +        */
25659 +
25660 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
25661 +                   core_if, dest, bytes);
25662 +
25663 +       for (i = 0; i < word_count; i++, data_buff++) {
25664 +               *data_buff = DWC_READ_REG32(fifo);
25665 +       }
25666 +
25667 +       return;
25668 +}
25669 +
25670 +/**
25671 + * This functions reads the device registers and prints them
25672 + *
25673 + * @param core_if Programming view of DWC_otg controller.
25674 + */
25675 +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
25676 +{
25677 +       int i;
25678 +       volatile uint32_t *addr;
25679 +
25680 +       DWC_PRINTF("Device Global Registers\n");
25681 +       addr = &core_if->dev_if->dev_global_regs->dcfg;
25682 +       DWC_PRINTF("DCFG                 @0x%08lX : 0x%08X\n",
25683 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25684 +       addr = &core_if->dev_if->dev_global_regs->dctl;
25685 +       DWC_PRINTF("DCTL                 @0x%08lX : 0x%08X\n",
25686 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25687 +       addr = &core_if->dev_if->dev_global_regs->dsts;
25688 +       DWC_PRINTF("DSTS                 @0x%08lX : 0x%08X\n",
25689 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25690 +       addr = &core_if->dev_if->dev_global_regs->diepmsk;
25691 +       DWC_PRINTF("DIEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25692 +                  DWC_READ_REG32(addr));
25693 +       addr = &core_if->dev_if->dev_global_regs->doepmsk;
25694 +       DWC_PRINTF("DOEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25695 +                  DWC_READ_REG32(addr));
25696 +       addr = &core_if->dev_if->dev_global_regs->daint;
25697 +       DWC_PRINTF("DAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25698 +                  DWC_READ_REG32(addr));
25699 +       addr = &core_if->dev_if->dev_global_regs->daintmsk;
25700 +       DWC_PRINTF("DAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25701 +                  DWC_READ_REG32(addr));
25702 +       addr = &core_if->dev_if->dev_global_regs->dtknqr1;
25703 +       DWC_PRINTF("DTKNQR1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25704 +                  DWC_READ_REG32(addr));
25705 +       if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
25706 +               addr = &core_if->dev_if->dev_global_regs->dtknqr2;
25707 +               DWC_PRINTF("DTKNQR2      @0x%08lX : 0x%08X\n",
25708 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25709 +       }
25710 +
25711 +       addr = &core_if->dev_if->dev_global_regs->dvbusdis;
25712 +       DWC_PRINTF("DVBUSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25713 +                  DWC_READ_REG32(addr));
25714 +
25715 +       addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
25716 +       DWC_PRINTF("DVBUSPULSE  @0x%08lX : 0x%08X\n",
25717 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25718 +
25719 +       addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
25720 +       DWC_PRINTF("DTKNQR3_DTHRCTL      @0x%08lX : 0x%08X\n",
25721 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25722 +
25723 +       if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
25724 +               addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25725 +               DWC_PRINTF("DTKNQR4      @0x%08lX : 0x%08X\n",
25726 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25727 +       }
25728 +
25729 +       addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25730 +       DWC_PRINTF("FIFOEMPMSK   @0x%08lX : 0x%08X\n", (unsigned long)addr,
25731 +                  DWC_READ_REG32(addr));
25732 +
25733 +       if (core_if->hwcfg2.b.multi_proc_int) {
25734 +
25735 +               addr = &core_if->dev_if->dev_global_regs->deachint;
25736 +               DWC_PRINTF("DEACHINT     @0x%08lX : 0x%08X\n",
25737 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25738 +               addr = &core_if->dev_if->dev_global_regs->deachintmsk;
25739 +               DWC_PRINTF("DEACHINTMSK  @0x%08lX : 0x%08X\n",
25740 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25741 +
25742 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25743 +                       addr =
25744 +                           &core_if->dev_if->
25745 +                           dev_global_regs->diepeachintmsk[i];
25746 +                       DWC_PRINTF("DIEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25747 +                                  i, (unsigned long)addr,
25748 +                                  DWC_READ_REG32(addr));
25749 +               }
25750 +
25751 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25752 +                       addr =
25753 +                           &core_if->dev_if->
25754 +                           dev_global_regs->doepeachintmsk[i];
25755 +                       DWC_PRINTF("DOEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25756 +                                  i, (unsigned long)addr,
25757 +                                  DWC_READ_REG32(addr));
25758 +               }
25759 +       }
25760 +
25761 +       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25762 +               DWC_PRINTF("Device IN EP %d Registers\n", i);
25763 +               addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
25764 +               DWC_PRINTF("DIEPCTL      @0x%08lX : 0x%08X\n",
25765 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25766 +               addr = &core_if->dev_if->in_ep_regs[i]->diepint;
25767 +               DWC_PRINTF("DIEPINT      @0x%08lX : 0x%08X\n",
25768 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25769 +               addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
25770 +               DWC_PRINTF("DIETSIZ      @0x%08lX : 0x%08X\n",
25771 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25772 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
25773 +               DWC_PRINTF("DIEPDMA      @0x%08lX : 0x%08X\n",
25774 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25775 +               addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
25776 +               DWC_PRINTF("DTXFSTS      @0x%08lX : 0x%08X\n",
25777 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25778 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
25779 +               DWC_PRINTF("DIEPDMAB     @0x%08lX : 0x%08X\n",
25780 +                          (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );
25781 +       }
25782 +
25783 +       for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25784 +               DWC_PRINTF("Device OUT EP %d Registers\n", i);
25785 +               addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
25786 +               DWC_PRINTF("DOEPCTL      @0x%08lX : 0x%08X\n",
25787 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25788 +               addr = &core_if->dev_if->out_ep_regs[i]->doepint;
25789 +               DWC_PRINTF("DOEPINT      @0x%08lX : 0x%08X\n",
25790 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25791 +               addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
25792 +               DWC_PRINTF("DOETSIZ      @0x%08lX : 0x%08X\n",
25793 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25794 +               addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
25795 +               DWC_PRINTF("DOEPDMA      @0x%08lX : 0x%08X\n",
25796 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25797 +               if (core_if->dma_enable) {      /* Don't access this register in SLAVE mode */
25798 +                       addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
25799 +                       DWC_PRINTF("DOEPDMAB     @0x%08lX : 0x%08X\n",
25800 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
25801 +               }
25802 +
25803 +       }
25804 +}
25805 +
25806 +/**
25807 + * This functions reads the SPRAM and prints its content
25808 + *
25809 + * @param core_if Programming view of DWC_otg controller.
25810 + */
25811 +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
25812 +{
25813 +       volatile uint8_t *addr, *start_addr, *end_addr;
25814 +
25815 +       DWC_PRINTF("SPRAM Data:\n");
25816 +       start_addr = (void *)core_if->core_global_regs;
25817 +       DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);
25818 +       start_addr += 0x00028000;
25819 +       end_addr = (void *)core_if->core_global_regs;
25820 +       end_addr += 0x000280e0;
25821 +
25822 +       for (addr = start_addr; addr < end_addr; addr += 16) {
25823 +               DWC_PRINTF
25824 +                   ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
25825 +                    (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],
25826 +                    addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
25827 +                    addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
25828 +                   );
25829 +       }
25830 +
25831 +       return;
25832 +}
25833 +
25834 +/**
25835 + * This function reads the host registers and prints them
25836 + *
25837 + * @param core_if Programming view of DWC_otg controller.
25838 + */
25839 +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
25840 +{
25841 +       int i;
25842 +       volatile uint32_t *addr;
25843 +
25844 +       DWC_PRINTF("Host Global Registers\n");
25845 +       addr = &core_if->host_if->host_global_regs->hcfg;
25846 +       DWC_PRINTF("HCFG                 @0x%08lX : 0x%08X\n",
25847 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25848 +       addr = &core_if->host_if->host_global_regs->hfir;
25849 +       DWC_PRINTF("HFIR                 @0x%08lX : 0x%08X\n",
25850 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25851 +       addr = &core_if->host_if->host_global_regs->hfnum;
25852 +       DWC_PRINTF("HFNUM        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25853 +                  DWC_READ_REG32(addr));
25854 +       addr = &core_if->host_if->host_global_regs->hptxsts;
25855 +       DWC_PRINTF("HPTXSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25856 +                  DWC_READ_REG32(addr));
25857 +       addr = &core_if->host_if->host_global_regs->haint;
25858 +       DWC_PRINTF("HAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25859 +                  DWC_READ_REG32(addr));
25860 +       addr = &core_if->host_if->host_global_regs->haintmsk;
25861 +       DWC_PRINTF("HAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25862 +                  DWC_READ_REG32(addr));
25863 +       if (core_if->dma_desc_enable) {
25864 +               addr = &core_if->host_if->host_global_regs->hflbaddr;
25865 +               DWC_PRINTF("HFLBADDR     @0x%08lX : 0x%08X\n",
25866 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25867 +       }
25868 +
25869 +       addr = core_if->host_if->hprt0;
25870 +       DWC_PRINTF("HPRT0        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25871 +                  DWC_READ_REG32(addr));
25872 +
25873 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
25874 +               DWC_PRINTF("Host Channel %d Specific Registers\n", i);
25875 +               addr = &core_if->host_if->hc_regs[i]->hcchar;
25876 +               DWC_PRINTF("HCCHAR       @0x%08lX : 0x%08X\n",
25877 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25878 +               addr = &core_if->host_if->hc_regs[i]->hcsplt;
25879 +               DWC_PRINTF("HCSPLT       @0x%08lX : 0x%08X\n",
25880 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25881 +               addr = &core_if->host_if->hc_regs[i]->hcint;
25882 +               DWC_PRINTF("HCINT        @0x%08lX : 0x%08X\n",
25883 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25884 +               addr = &core_if->host_if->hc_regs[i]->hcintmsk;
25885 +               DWC_PRINTF("HCINTMSK     @0x%08lX : 0x%08X\n",
25886 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25887 +               addr = &core_if->host_if->hc_regs[i]->hctsiz;
25888 +               DWC_PRINTF("HCTSIZ       @0x%08lX : 0x%08X\n",
25889 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25890 +               addr = &core_if->host_if->hc_regs[i]->hcdma;
25891 +               DWC_PRINTF("HCDMA        @0x%08lX : 0x%08X\n",
25892 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25893 +               if (core_if->dma_desc_enable) {
25894 +                       addr = &core_if->host_if->hc_regs[i]->hcdmab;
25895 +                       DWC_PRINTF("HCDMAB       @0x%08lX : 0x%08X\n",
25896 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
25897 +               }
25898 +
25899 +       }
25900 +       return;
25901 +}
25902 +
25903 +/**
25904 + * This function reads the core global registers and prints them
25905 + *
25906 + * @param core_if Programming view of DWC_otg controller.
25907 + */
25908 +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
25909 +{
25910 +       int i, ep_num;
25911 +       volatile uint32_t *addr;
25912 +       char *txfsiz;
25913 +
25914 +       DWC_PRINTF("Core Global Registers\n");
25915 +       addr = &core_if->core_global_regs->gotgctl;
25916 +       DWC_PRINTF("GOTGCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25917 +                  DWC_READ_REG32(addr));
25918 +       addr = &core_if->core_global_regs->gotgint;
25919 +       DWC_PRINTF("GOTGINT      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25920 +                  DWC_READ_REG32(addr));
25921 +       addr = &core_if->core_global_regs->gahbcfg;
25922 +       DWC_PRINTF("GAHBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25923 +                  DWC_READ_REG32(addr));
25924 +       addr = &core_if->core_global_regs->gusbcfg;
25925 +       DWC_PRINTF("GUSBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25926 +                  DWC_READ_REG32(addr));
25927 +       addr = &core_if->core_global_regs->grstctl;
25928 +       DWC_PRINTF("GRSTCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25929 +                  DWC_READ_REG32(addr));
25930 +       addr = &core_if->core_global_regs->gintsts;
25931 +       DWC_PRINTF("GINTSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25932 +                  DWC_READ_REG32(addr));
25933 +       addr = &core_if->core_global_regs->gintmsk;
25934 +       DWC_PRINTF("GINTMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25935 +                  DWC_READ_REG32(addr));
25936 +       addr = &core_if->core_global_regs->grxstsr;
25937 +       DWC_PRINTF("GRXSTSR      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25938 +                  DWC_READ_REG32(addr));
25939 +       addr = &core_if->core_global_regs->grxfsiz;
25940 +       DWC_PRINTF("GRXFSIZ      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25941 +                  DWC_READ_REG32(addr));
25942 +       addr = &core_if->core_global_regs->gnptxfsiz;
25943 +       DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
25944 +                  DWC_READ_REG32(addr));
25945 +       addr = &core_if->core_global_regs->gnptxsts;
25946 +       DWC_PRINTF("GNPTXSTS     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25947 +                  DWC_READ_REG32(addr));
25948 +       addr = &core_if->core_global_regs->gi2cctl;
25949 +       DWC_PRINTF("GI2CCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25950 +                  DWC_READ_REG32(addr));
25951 +       addr = &core_if->core_global_regs->gpvndctl;
25952 +       DWC_PRINTF("GPVNDCTL     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25953 +                  DWC_READ_REG32(addr));
25954 +       addr = &core_if->core_global_regs->ggpio;
25955 +       DWC_PRINTF("GGPIO        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25956 +                  DWC_READ_REG32(addr));
25957 +       addr = &core_if->core_global_regs->guid;
25958 +       DWC_PRINTF("GUID                 @0x%08lX : 0x%08X\n",
25959 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25960 +       addr = &core_if->core_global_regs->gsnpsid;
25961 +       DWC_PRINTF("GSNPSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25962 +                  DWC_READ_REG32(addr));
25963 +       addr = &core_if->core_global_regs->ghwcfg1;
25964 +       DWC_PRINTF("GHWCFG1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25965 +                  DWC_READ_REG32(addr));
25966 +       addr = &core_if->core_global_regs->ghwcfg2;
25967 +       DWC_PRINTF("GHWCFG2      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25968 +                  DWC_READ_REG32(addr));
25969 +       addr = &core_if->core_global_regs->ghwcfg3;
25970 +       DWC_PRINTF("GHWCFG3      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25971 +                  DWC_READ_REG32(addr));
25972 +       addr = &core_if->core_global_regs->ghwcfg4;
25973 +       DWC_PRINTF("GHWCFG4      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25974 +                  DWC_READ_REG32(addr));
25975 +       addr = &core_if->core_global_regs->glpmcfg;
25976 +       DWC_PRINTF("GLPMCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25977 +                  DWC_READ_REG32(addr));
25978 +       addr = &core_if->core_global_regs->gpwrdn;
25979 +       DWC_PRINTF("GPWRDN       @0x%08lX : 0x%08X\n", (unsigned long)addr,
25980 +                  DWC_READ_REG32(addr));
25981 +       addr = &core_if->core_global_regs->gdfifocfg;
25982 +       DWC_PRINTF("GDFIFOCFG    @0x%08lX : 0x%08X\n", (unsigned long)addr,
25983 +                  DWC_READ_REG32(addr));
25984 +       addr = &core_if->core_global_regs->adpctl;
25985 +       DWC_PRINTF("ADPCTL       @0x%08lX : 0x%08X\n", (unsigned long)addr,
25986 +                  dwc_otg_adp_read_reg(core_if));
25987 +       addr = &core_if->core_global_regs->hptxfsiz;
25988 +       DWC_PRINTF("HPTXFSIZ     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25989 +                  DWC_READ_REG32(addr));
25990 +
25991 +       if (core_if->en_multiple_tx_fifo == 0) {
25992 +               ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;
25993 +               txfsiz = "DPTXFSIZ";
25994 +       } else {
25995 +               ep_num = core_if->hwcfg4.b.num_in_eps;
25996 +               txfsiz = "DIENPTXF";
25997 +       }
25998 +       for (i = 0; i < ep_num; i++) {
25999 +               addr = &core_if->core_global_regs->dtxfsiz[i];
26000 +               DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
26001 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26002 +       }
26003 +       addr = core_if->pcgcctl;
26004 +       DWC_PRINTF("PCGCCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26005 +                  DWC_READ_REG32(addr));
26006 +}
26007 +
26008 +/**
26009 + * Flush a Tx FIFO.
26010 + *
26011 + * @param core_if Programming view of DWC_otg controller.
26012 + * @param num Tx FIFO to flush.
26013 + */
26014 +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
26015 +{
26016 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26017 +       volatile grstctl_t greset = {.d32 = 0 };
26018 +       int count = 0;
26019 +
26020 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
26021 +
26022 +       greset.b.txfflsh = 1;
26023 +       greset.b.txfnum = num;
26024 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26025 +
26026 +       do {
26027 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26028 +               if (++count > 10000) {
26029 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
26030 +                                __func__, greset.d32,
26031 +                                DWC_READ_REG32(&global_regs->gnptxsts));
26032 +                       break;
26033 +               }
26034 +               dwc_udelay(1);
26035 +       } while (greset.b.txfflsh == 1);
26036 +
26037 +       /* Wait for 3 PHY Clocks */
26038 +       dwc_udelay(1);
26039 +}
26040 +
26041 +/**
26042 + * Flush Rx FIFO.
26043 + *
26044 + * @param core_if Programming view of DWC_otg controller.
26045 + */
26046 +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
26047 +{
26048 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26049 +       volatile grstctl_t greset = {.d32 = 0 };
26050 +       int count = 0;
26051 +
26052 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
26053 +       /*
26054 +        *
26055 +        */
26056 +       greset.b.rxfflsh = 1;
26057 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26058 +
26059 +       do {
26060 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26061 +               if (++count > 10000) {
26062 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
26063 +                                greset.d32);
26064 +                       break;
26065 +               }
26066 +               dwc_udelay(1);
26067 +       } while (greset.b.rxfflsh == 1);
26068 +
26069 +       /* Wait for 3 PHY Clocks */
26070 +       dwc_udelay(1);
26071 +}
26072 +
26073 +/**
26074 + * Do core a soft reset of the core.  Be careful with this because it
26075 + * resets all the internal state machines of the core.
26076 + */
26077 +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
26078 +{
26079 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26080 +       volatile grstctl_t greset = {.d32 = 0 };
26081 +       int count = 0;
26082 +
26083 +       DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
26084 +       /* Wait for AHB master IDLE state. */
26085 +       do {
26086 +               dwc_udelay(10);
26087 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26088 +               if (++count > 100000) {
26089 +                       DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
26090 +                                greset.d32);
26091 +                       return;
26092 +               }
26093 +       }
26094 +       while (greset.b.ahbidle == 0);
26095 +
26096 +       /* Core Soft Reset */
26097 +       count = 0;
26098 +       greset.b.csftrst = 1;
26099 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26100 +       do {
26101 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26102 +               if (++count > 10000) {
26103 +                       DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
26104 +                                __func__, greset.d32);
26105 +                       break;
26106 +               }
26107 +               dwc_udelay(1);
26108 +       }
26109 +       while (greset.b.csftrst == 1);
26110 +
26111 +       /* Wait for 3 PHY Clocks */
26112 +       dwc_mdelay(100);
26113 +}
26114 +
26115 +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
26116 +{
26117 +       return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
26118 +}
26119 +
26120 +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
26121 +{
26122 +       return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
26123 +}
26124 +
26125 +/**
26126 + * Register HCD callbacks. The callbacks are used to start and stop
26127 + * the HCD for interrupt processing.
26128 + *
26129 + * @param core_if Programming view of DWC_otg controller.
26130 + * @param cb the HCD callback structure.
26131 + * @param p pointer to be passed to callback function (usb_hcd*).
26132 + */
26133 +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
26134 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26135 +{
26136 +       core_if->hcd_cb = cb;
26137 +       cb->p = p;
26138 +}
26139 +
26140 +/**
26141 + * Register PCD callbacks. The callbacks are used to start and stop
26142 + * the PCD for interrupt processing.
26143 + *
26144 + * @param core_if Programming view of DWC_otg controller.
26145 + * @param cb the PCD callback structure.
26146 + * @param p pointer to be passed to callback function (pcd*).
26147 + */
26148 +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
26149 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26150 +{
26151 +       core_if->pcd_cb = cb;
26152 +       cb->p = p;
26153 +}
26154 +
26155 +#ifdef DWC_EN_ISOC
26156 +
26157 +/**
26158 + * This function writes isoc data per 1 (micro)frame into tx fifo
26159 + *
26160 + * @param core_if Programming view of DWC_otg controller.
26161 + * @param ep The EP to start the transfer on.
26162 + *
26163 + */
26164 +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
26165 +{
26166 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
26167 +       dtxfsts_data_t txstatus = {.d32 = 0 };
26168 +       uint32_t len = 0;
26169 +       uint32_t dwords;
26170 +
26171 +       ep->xfer_len = ep->data_per_frame;
26172 +       ep->xfer_count = 0;
26173 +
26174 +       ep_regs = core_if->dev_if->in_ep_regs[ep->num];
26175 +
26176 +       len = ep->xfer_len - ep->xfer_count;
26177 +
26178 +       if (len > ep->maxpacket) {
26179 +               len = ep->maxpacket;
26180 +       }
26181 +
26182 +       dwords = (len + 3) / 4;
26183 +
26184 +       /* While there is space in the queue and space in the FIFO and
26185 +        * More data to tranfer, Write packets to the Tx FIFO */
26186 +       txstatus.d32 =
26187 +           DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
26188 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
26189 +
26190 +       while (txstatus.b.txfspcavail > dwords &&
26191 +              ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
26192 +               /* Write the FIFO */
26193 +               dwc_otg_ep_write_packet(core_if, ep, 0);
26194 +
26195 +               len = ep->xfer_len - ep->xfer_count;
26196 +               if (len > ep->maxpacket) {
26197 +                       len = ep->maxpacket;
26198 +               }
26199 +
26200 +               dwords = (len + 3) / 4;
26201 +               txstatus.d32 =
26202 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
26203 +                                  dtxfsts);
26204 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
26205 +                           txstatus.d32);
26206 +       }
26207 +}
26208 +
26209 +/**
26210 + * This function initializes a descriptor chain for Isochronous transfer
26211 + *
26212 + * @param core_if Programming view of DWC_otg controller.
26213 + * @param ep The EP to start the transfer on.
26214 + *
26215 + */
26216 +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
26217 +                                      dwc_ep_t * ep)
26218 +{
26219 +       deptsiz_data_t deptsiz = {.d32 = 0 };
26220 +       depctl_data_t depctl = {.d32 = 0 };
26221 +       dsts_data_t dsts = {.d32 = 0 };
26222 +       volatile uint32_t *addr;
26223 +
26224 +       if (ep->is_in) {
26225 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
26226 +       } else {
26227 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
26228 +       }
26229 +
26230 +       ep->xfer_len = ep->data_per_frame;
26231 +       ep->xfer_count = 0;
26232 +       ep->xfer_buff = ep->cur_pkt_addr;
26233 +       ep->dma_addr = ep->cur_pkt_dma_addr;
26234 +
26235 +       if (ep->is_in) {
26236 +               /* Program the transfer size and packet count
26237 +                *      as follows: xfersize = N * maxpacket +
26238 +                *      short_packet pktcnt = N + (short_packet
26239 +                *      exist ? 1 : 0)
26240 +                */
26241 +               deptsiz.b.xfersize = ep->xfer_len;
26242 +               deptsiz.b.pktcnt =
26243 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
26244 +               deptsiz.b.mc = deptsiz.b.pktcnt;
26245 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
26246 +                               deptsiz.d32);
26247 +
26248 +               /* Write the DMA register */
26249 +               if (core_if->dma_enable) {
26250 +                       DWC_WRITE_REG32(&
26251 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
26252 +                                        diepdma), (uint32_t) ep->dma_addr);
26253 +               }
26254 +       } else {
26255 +               deptsiz.b.pktcnt =
26256 +                   (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
26257 +               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
26258 +
26259 +               DWC_WRITE_REG32(&core_if->dev_if->
26260 +                               out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);
26261 +
26262 +               if (core_if->dma_enable) {
26263 +                       DWC_WRITE_REG32(&
26264 +                                       (core_if->dev_if->
26265 +                                        out_ep_regs[ep->num]->doepdma),
26266 +                                       (uint32_t) ep->dma_addr);
26267 +               }
26268 +       }
26269 +
26270 +       /** Enable endpoint, clear nak  */
26271 +
26272 +       depctl.d32 = 0;
26273 +       if (ep->bInterval == 1) {
26274 +               dsts.d32 =
26275 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
26276 +               ep->next_frame = dsts.b.soffn + ep->bInterval;
26277 +
26278 +               if (ep->next_frame & 0x1) {
26279 +                       depctl.b.setd1pid = 1;
26280 +               } else {
26281 +                       depctl.b.setd0pid = 1;
26282 +               }
26283 +       } else {
26284 +               ep->next_frame += ep->bInterval;
26285 +
26286 +               if (ep->next_frame & 0x1) {
26287 +                       depctl.b.setd1pid = 1;
26288 +               } else {
26289 +                       depctl.b.setd0pid = 1;
26290 +               }
26291 +       }
26292 +       depctl.b.epena = 1;
26293 +       depctl.b.cnak = 1;
26294 +
26295 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
26296 +       depctl.d32 = DWC_READ_REG32(addr);
26297 +
26298 +       if (ep->is_in && core_if->dma_enable == 0) {
26299 +               write_isoc_frame_data(core_if, ep);
26300 +       }
26301 +
26302 +}
26303 +#endif /* DWC_EN_ISOC */
26304 +
26305 +static void dwc_otg_set_uninitialized(int32_t * p, int size)
26306 +{
26307 +       int i;
26308 +       for (i = 0; i < size; i++) {
26309 +               p[i] = -1;
26310 +       }
26311 +}
26312 +
26313 +static int dwc_otg_param_initialized(int32_t val)
26314 +{
26315 +       return val != -1;
26316 +}
26317 +
26318 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
26319 +{
26320 +       int i;
26321 +       core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
26322 +       if (!core_if->core_params) {
26323 +               return -DWC_E_NO_MEMORY;
26324 +       }
26325 +       dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
26326 +                                 sizeof(*core_if->core_params) /
26327 +                                 sizeof(int32_t));
26328 +       DWC_PRINTF("Setting default values for core params\n");
26329 +       dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
26330 +       dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
26331 +       dwc_otg_set_param_dma_desc_enable(core_if,
26332 +                                         dwc_param_dma_desc_enable_default);
26333 +       dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
26334 +       dwc_otg_set_param_dma_burst_size(core_if,
26335 +                                        dwc_param_dma_burst_size_default);
26336 +       dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
26337 +                                                      dwc_param_host_support_fs_ls_low_power_default);
26338 +       dwc_otg_set_param_enable_dynamic_fifo(core_if,
26339 +                                             dwc_param_enable_dynamic_fifo_default);
26340 +       dwc_otg_set_param_data_fifo_size(core_if,
26341 +                                        dwc_param_data_fifo_size_default);
26342 +       dwc_otg_set_param_dev_rx_fifo_size(core_if,
26343 +                                          dwc_param_dev_rx_fifo_size_default);
26344 +       dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
26345 +                                                 dwc_param_dev_nperio_tx_fifo_size_default);
26346 +       dwc_otg_set_param_host_rx_fifo_size(core_if,
26347 +                                           dwc_param_host_rx_fifo_size_default);
26348 +       dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
26349 +                                                  dwc_param_host_nperio_tx_fifo_size_default);
26350 +       dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
26351 +                                                 dwc_param_host_perio_tx_fifo_size_default);
26352 +       dwc_otg_set_param_max_transfer_size(core_if,
26353 +                                           dwc_param_max_transfer_size_default);
26354 +       dwc_otg_set_param_max_packet_count(core_if,
26355 +                                          dwc_param_max_packet_count_default);
26356 +       dwc_otg_set_param_host_channels(core_if,
26357 +                                       dwc_param_host_channels_default);
26358 +       dwc_otg_set_param_dev_endpoints(core_if,
26359 +                                       dwc_param_dev_endpoints_default);
26360 +       dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
26361 +       dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
26362 +       dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
26363 +                                                   dwc_param_host_ls_low_power_phy_clk_default);
26364 +       dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
26365 +       dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
26366 +                                           dwc_param_phy_ulpi_ext_vbus_default);
26367 +       dwc_otg_set_param_phy_utmi_width(core_if,
26368 +                                        dwc_param_phy_utmi_width_default);
26369 +       dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
26370 +       dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
26371 +       dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
26372 +       dwc_otg_set_param_en_multiple_tx_fifo(core_if,
26373 +                                             dwc_param_en_multiple_tx_fifo_default);
26374 +       for (i = 0; i < 15; i++) {
26375 +               dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
26376 +                                                        dwc_param_dev_perio_tx_fifo_size_default,
26377 +                                                        i);
26378 +       }
26379 +
26380 +       for (i = 0; i < 15; i++) {
26381 +               dwc_otg_set_param_dev_tx_fifo_size(core_if,
26382 +                                                  dwc_param_dev_tx_fifo_size_default,
26383 +                                                  i);
26384 +       }
26385 +       dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
26386 +       dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
26387 +       dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
26388 +       dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
26389 +       dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
26390 +       dwc_otg_set_param_tx_thr_length(core_if,
26391 +                                       dwc_param_tx_thr_length_default);
26392 +       dwc_otg_set_param_rx_thr_length(core_if,
26393 +                                       dwc_param_rx_thr_length_default);
26394 +       dwc_otg_set_param_ahb_thr_ratio(core_if,
26395 +                                       dwc_param_ahb_thr_ratio_default);
26396 +       dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
26397 +       dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
26398 +       dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
26399 +       dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
26400 +       dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
26401 +       dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
26402 +       dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
26403 +       DWC_PRINTF("Finished setting default values for core params\n");
26404 +
26405 +       return 0;
26406 +}
26407 +
26408 +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
26409 +{
26410 +       return core_if->dma_enable;
26411 +}
26412 +
26413 +/* Checks if the parameter is outside of its valid range of values */
26414 +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
26415 +               (((_param_) < (_low_)) || \
26416 +               ((_param_) > (_high_)))
26417 +
26418 +/* Parameter access functions */
26419 +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
26420 +{
26421 +       int valid;
26422 +       int retval = 0;
26423 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26424 +               DWC_WARN("Wrong value for otg_cap parameter\n");
26425 +               DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
26426 +               retval = -DWC_E_INVALID;
26427 +               goto out;
26428 +       }
26429 +
26430 +       valid = 1;
26431 +       switch (val) {
26432 +       case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
26433 +               if (core_if->hwcfg2.b.op_mode !=
26434 +                   DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26435 +                       valid = 0;
26436 +               break;
26437 +       case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
26438 +               if ((core_if->hwcfg2.b.op_mode !=
26439 +                    DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26440 +                   && (core_if->hwcfg2.b.op_mode !=
26441 +                       DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26442 +                   && (core_if->hwcfg2.b.op_mode !=
26443 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26444 +                   && (core_if->hwcfg2.b.op_mode !=
26445 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
26446 +                       valid = 0;
26447 +               }
26448 +               break;
26449 +       case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
26450 +               /* always valid */
26451 +               break;
26452 +       }
26453 +       if (!valid) {
26454 +               if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
26455 +                       DWC_ERROR
26456 +                           ("%d invalid for otg_cap paremter. Check HW configuration.\n",
26457 +                            val);
26458 +               }
26459 +               val =
26460 +                   (((core_if->hwcfg2.b.op_mode ==
26461 +                      DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26462 +                     || (core_if->hwcfg2.b.op_mode ==
26463 +                         DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26464 +                     || (core_if->hwcfg2.b.op_mode ==
26465 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26466 +                     || (core_if->hwcfg2.b.op_mode ==
26467 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
26468 +                    DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
26469 +                    DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
26470 +               retval = -DWC_E_INVALID;
26471 +       }
26472 +
26473 +       core_if->core_params->otg_cap = val;
26474 +out:
26475 +       return retval;
26476 +}
26477 +
26478 +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
26479 +{
26480 +       return core_if->core_params->otg_cap;
26481 +}
26482 +
26483 +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
26484 +{
26485 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26486 +               DWC_WARN("Wrong value for opt parameter\n");
26487 +               return -DWC_E_INVALID;
26488 +       }
26489 +       core_if->core_params->opt = val;
26490 +       return 0;
26491 +}
26492 +
26493 +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
26494 +{
26495 +       return core_if->core_params->opt;
26496 +}
26497 +
26498 +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
26499 +{
26500 +       int retval = 0;
26501 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26502 +               DWC_WARN("Wrong value for dma enable\n");
26503 +               return -DWC_E_INVALID;
26504 +       }
26505 +
26506 +       if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
26507 +               if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
26508 +                       DWC_ERROR
26509 +                           ("%d invalid for dma_enable paremter. Check HW configuration.\n",
26510 +                            val);
26511 +               }
26512 +               val = 0;
26513 +               retval = -DWC_E_INVALID;
26514 +       }
26515 +
26516 +       core_if->core_params->dma_enable = val;
26517 +       if (val == 0) {
26518 +               dwc_otg_set_param_dma_desc_enable(core_if, 0);
26519 +       }
26520 +       return retval;
26521 +}
26522 +
26523 +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
26524 +{
26525 +       return core_if->core_params->dma_enable;
26526 +}
26527 +
26528 +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
26529 +{
26530 +       int retval = 0;
26531 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26532 +               DWC_WARN("Wrong value for dma_enable\n");
26533 +               DWC_WARN("dma_desc_enable must be 0 or 1\n");
26534 +               return -DWC_E_INVALID;
26535 +       }
26536 +
26537 +       if ((val == 1)
26538 +           && ((dwc_otg_get_param_dma_enable(core_if) == 0)
26539 +               || (core_if->hwcfg4.b.desc_dma == 0))) {
26540 +               if (dwc_otg_param_initialized
26541 +                   (core_if->core_params->dma_desc_enable)) {
26542 +                       DWC_ERROR
26543 +                           ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
26544 +                            val);
26545 +               }
26546 +               val = 0;
26547 +               retval = -DWC_E_INVALID;
26548 +       }
26549 +       core_if->core_params->dma_desc_enable = val;
26550 +       return retval;
26551 +}
26552 +
26553 +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
26554 +{
26555 +       return core_if->core_params->dma_desc_enable;
26556 +}
26557 +
26558 +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
26559 +                                                  int32_t val)
26560 +{
26561 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26562 +               DWC_WARN("Wrong value for host_support_fs_low_power\n");
26563 +               DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
26564 +               return -DWC_E_INVALID;
26565 +       }
26566 +       core_if->core_params->host_support_fs_ls_low_power = val;
26567 +       return 0;
26568 +}
26569 +
26570 +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
26571 +                                                      core_if)
26572 +{
26573 +       return core_if->core_params->host_support_fs_ls_low_power;
26574 +}
26575 +
26576 +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
26577 +                                         int32_t val)
26578 +{
26579 +       int retval = 0;
26580 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26581 +               DWC_WARN("Wrong value for enable_dynamic_fifo\n");
26582 +               DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
26583 +               return -DWC_E_INVALID;
26584 +       }
26585 +
26586 +       if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
26587 +               if (dwc_otg_param_initialized
26588 +                   (core_if->core_params->enable_dynamic_fifo)) {
26589 +                       DWC_ERROR
26590 +                           ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
26591 +                            val);
26592 +               }
26593 +               val = 0;
26594 +               retval = -DWC_E_INVALID;
26595 +       }
26596 +       core_if->core_params->enable_dynamic_fifo = val;
26597 +       return retval;
26598 +}
26599 +
26600 +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
26601 +{
26602 +       return core_if->core_params->enable_dynamic_fifo;
26603 +}
26604 +
26605 +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26606 +{
26607 +       int retval = 0;
26608 +       if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
26609 +               DWC_WARN("Wrong value for data_fifo_size\n");
26610 +               DWC_WARN("data_fifo_size must be 32-32768\n");
26611 +               return -DWC_E_INVALID;
26612 +       }
26613 +
26614 +       if (val > core_if->hwcfg3.b.dfifo_depth) {
26615 +               if (dwc_otg_param_initialized
26616 +                   (core_if->core_params->data_fifo_size)) {
26617 +                       DWC_ERROR
26618 +                           ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
26619 +                            val);
26620 +               }
26621 +               val = core_if->hwcfg3.b.dfifo_depth;
26622 +               retval = -DWC_E_INVALID;
26623 +       }
26624 +
26625 +       core_if->core_params->data_fifo_size = val;
26626 +       return retval;
26627 +}
26628 +
26629 +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
26630 +{
26631 +       return core_if->core_params->data_fifo_size;
26632 +}
26633 +
26634 +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26635 +{
26636 +       int retval = 0;
26637 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26638 +               DWC_WARN("Wrong value for dev_rx_fifo_size\n");
26639 +               DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
26640 +               return -DWC_E_INVALID;
26641 +       }
26642 +
26643 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26644 +               if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
26645 +               DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
26646 +               }
26647 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26648 +               retval = -DWC_E_INVALID;
26649 +       }
26650 +
26651 +       core_if->core_params->dev_rx_fifo_size = val;
26652 +       return retval;
26653 +}
26654 +
26655 +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
26656 +{
26657 +       return core_if->core_params->dev_rx_fifo_size;
26658 +}
26659 +
26660 +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26661 +                                             int32_t val)
26662 +{
26663 +       int retval = 0;
26664 +
26665 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26666 +               DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
26667 +               DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
26668 +               return -DWC_E_INVALID;
26669 +       }
26670 +
26671 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26672 +               if (dwc_otg_param_initialized
26673 +                   (core_if->core_params->dev_nperio_tx_fifo_size)) {
26674 +                       DWC_ERROR
26675 +                           ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
26676 +                            val);
26677 +               }
26678 +               val =
26679 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26680 +                    16);
26681 +               retval = -DWC_E_INVALID;
26682 +       }
26683 +
26684 +       core_if->core_params->dev_nperio_tx_fifo_size = val;
26685 +       return retval;
26686 +}
26687 +
26688 +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26689 +{
26690 +       return core_if->core_params->dev_nperio_tx_fifo_size;
26691 +}
26692 +
26693 +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
26694 +                                       int32_t val)
26695 +{
26696 +       int retval = 0;
26697 +
26698 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26699 +               DWC_WARN("Wrong value for host_rx_fifo_size\n");
26700 +               DWC_WARN("host_rx_fifo_size must be 16-32768\n");
26701 +               return -DWC_E_INVALID;
26702 +       }
26703 +
26704 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26705 +               if (dwc_otg_param_initialized
26706 +                   (core_if->core_params->host_rx_fifo_size)) {
26707 +                       DWC_ERROR
26708 +                           ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
26709 +                            val);
26710 +               }
26711 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26712 +               retval = -DWC_E_INVALID;
26713 +       }
26714 +
26715 +       core_if->core_params->host_rx_fifo_size = val;
26716 +       return retval;
26717 +
26718 +}
26719 +
26720 +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
26721 +{
26722 +       return core_if->core_params->host_rx_fifo_size;
26723 +}
26724 +
26725 +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26726 +                                              int32_t val)
26727 +{
26728 +       int retval = 0;
26729 +
26730 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26731 +               DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
26732 +               DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
26733 +               return -DWC_E_INVALID;
26734 +       }
26735 +
26736 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26737 +               if (dwc_otg_param_initialized
26738 +                   (core_if->core_params->host_nperio_tx_fifo_size)) {
26739 +                       DWC_ERROR
26740 +                           ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
26741 +                            val);
26742 +               }
26743 +               val =
26744 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26745 +                    16);
26746 +               retval = -DWC_E_INVALID;
26747 +       }
26748 +
26749 +       core_if->core_params->host_nperio_tx_fifo_size = val;
26750 +       return retval;
26751 +}
26752 +
26753 +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26754 +{
26755 +       return core_if->core_params->host_nperio_tx_fifo_size;
26756 +}
26757 +
26758 +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26759 +                                             int32_t val)
26760 +{
26761 +       int retval = 0;
26762 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26763 +               DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
26764 +               DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
26765 +               return -DWC_E_INVALID;
26766 +       }
26767 +
26768 +       if (val > ((core_if->hptxfsiz.d32) >> 16)) {
26769 +               if (dwc_otg_param_initialized
26770 +                   (core_if->core_params->host_perio_tx_fifo_size)) {
26771 +                       DWC_ERROR
26772 +                           ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
26773 +                            val);
26774 +               }
26775 +               val = (core_if->hptxfsiz.d32) >> 16;
26776 +               retval = -DWC_E_INVALID;
26777 +       }
26778 +
26779 +       core_if->core_params->host_perio_tx_fifo_size = val;
26780 +       return retval;
26781 +}
26782 +
26783 +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26784 +{
26785 +       return core_if->core_params->host_perio_tx_fifo_size;
26786 +}
26787 +
26788 +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
26789 +                                       int32_t val)
26790 +{
26791 +       int retval = 0;
26792 +
26793 +       if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
26794 +               DWC_WARN("Wrong value for max_transfer_size\n");
26795 +               DWC_WARN("max_transfer_size must be 2047-524288\n");
26796 +               return -DWC_E_INVALID;
26797 +       }
26798 +
26799 +       if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
26800 +               if (dwc_otg_param_initialized
26801 +                   (core_if->core_params->max_transfer_size)) {
26802 +                       DWC_ERROR
26803 +                           ("%d invalid for max_transfer_size. Check HW configuration.\n",
26804 +                            val);
26805 +               }
26806 +               val =
26807 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
26808 +                    1);
26809 +               retval = -DWC_E_INVALID;
26810 +       }
26811 +
26812 +       core_if->core_params->max_transfer_size = val;
26813 +       return retval;
26814 +}
26815 +
26816 +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
26817 +{
26818 +       return core_if->core_params->max_transfer_size;
26819 +}
26820 +
26821 +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
26822 +{
26823 +       int retval = 0;
26824 +
26825 +       if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
26826 +               DWC_WARN("Wrong value for max_packet_count\n");
26827 +               DWC_WARN("max_packet_count must be 15-511\n");
26828 +               return -DWC_E_INVALID;
26829 +       }
26830 +
26831 +       if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
26832 +               if (dwc_otg_param_initialized
26833 +                   (core_if->core_params->max_packet_count)) {
26834 +                       DWC_ERROR
26835 +                           ("%d invalid for max_packet_count. Check HW configuration.\n",
26836 +                            val);
26837 +               }
26838 +               val =
26839 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
26840 +               retval = -DWC_E_INVALID;
26841 +       }
26842 +
26843 +       core_if->core_params->max_packet_count = val;
26844 +       return retval;
26845 +}
26846 +
26847 +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
26848 +{
26849 +       return core_if->core_params->max_packet_count;
26850 +}
26851 +
26852 +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
26853 +{
26854 +       int retval = 0;
26855 +
26856 +       if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
26857 +               DWC_WARN("Wrong value for host_channels\n");
26858 +               DWC_WARN("host_channels must be 1-16\n");
26859 +               return -DWC_E_INVALID;
26860 +       }
26861 +
26862 +       if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
26863 +               if (dwc_otg_param_initialized
26864 +                   (core_if->core_params->host_channels)) {
26865 +                       DWC_ERROR
26866 +                           ("%d invalid for host_channels. Check HW configurations.\n",
26867 +                            val);
26868 +               }
26869 +               val = (core_if->hwcfg2.b.num_host_chan + 1);
26870 +               retval = -DWC_E_INVALID;
26871 +       }
26872 +
26873 +       core_if->core_params->host_channels = val;
26874 +       return retval;
26875 +}
26876 +
26877 +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
26878 +{
26879 +       return core_if->core_params->host_channels;
26880 +}
26881 +
26882 +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
26883 +{
26884 +       int retval = 0;
26885 +
26886 +       if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
26887 +               DWC_WARN("Wrong value for dev_endpoints\n");
26888 +               DWC_WARN("dev_endpoints must be 1-15\n");
26889 +               return -DWC_E_INVALID;
26890 +       }
26891 +
26892 +       if (val > (core_if->hwcfg2.b.num_dev_ep)) {
26893 +               if (dwc_otg_param_initialized
26894 +                   (core_if->core_params->dev_endpoints)) {
26895 +                       DWC_ERROR
26896 +                           ("%d invalid for dev_endpoints. Check HW configurations.\n",
26897 +                            val);
26898 +               }
26899 +               val = core_if->hwcfg2.b.num_dev_ep;
26900 +               retval = -DWC_E_INVALID;
26901 +       }
26902 +
26903 +       core_if->core_params->dev_endpoints = val;
26904 +       return retval;
26905 +}
26906 +
26907 +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
26908 +{
26909 +       return core_if->core_params->dev_endpoints;
26910 +}
26911 +
26912 +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
26913 +{
26914 +       int retval = 0;
26915 +       int valid = 0;
26916 +
26917 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26918 +               DWC_WARN("Wrong value for phy_type\n");
26919 +               DWC_WARN("phy_type must be 0,1 or 2\n");
26920 +               return -DWC_E_INVALID;
26921 +       }
26922 +#ifndef NO_FS_PHY_HW_CHECKS
26923 +       if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
26924 +           ((core_if->hwcfg2.b.hs_phy_type == 1) ||
26925 +            (core_if->hwcfg2.b.hs_phy_type == 3))) {
26926 +               valid = 1;
26927 +       } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
26928 +                  ((core_if->hwcfg2.b.hs_phy_type == 2) ||
26929 +                   (core_if->hwcfg2.b.hs_phy_type == 3))) {
26930 +               valid = 1;
26931 +       } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
26932 +                  (core_if->hwcfg2.b.fs_phy_type == 1)) {
26933 +               valid = 1;
26934 +       }
26935 +       if (!valid) {
26936 +               if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
26937 +                       DWC_ERROR
26938 +                           ("%d invalid for phy_type. Check HW configurations.\n",
26939 +                            val);
26940 +               }
26941 +               if (core_if->hwcfg2.b.hs_phy_type) {
26942 +                       if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
26943 +                           (core_if->hwcfg2.b.hs_phy_type == 1)) {
26944 +                               val = DWC_PHY_TYPE_PARAM_UTMI;
26945 +                       } else {
26946 +                               val = DWC_PHY_TYPE_PARAM_ULPI;
26947 +                       }
26948 +               }
26949 +               retval = -DWC_E_INVALID;
26950 +       }
26951 +#endif
26952 +       core_if->core_params->phy_type = val;
26953 +       return retval;
26954 +}
26955 +
26956 +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
26957 +{
26958 +       return core_if->core_params->phy_type;
26959 +}
26960 +
26961 +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
26962 +{
26963 +       int retval = 0;
26964 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26965 +               DWC_WARN("Wrong value for speed parameter\n");
26966 +               DWC_WARN("max_speed parameter must be 0 or 1\n");
26967 +               return -DWC_E_INVALID;
26968 +       }
26969 +       if ((val == 0)
26970 +           && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
26971 +               if (dwc_otg_param_initialized(core_if->core_params->speed)) {
26972 +                       DWC_ERROR
26973 +                           ("%d invalid for speed paremter. Check HW configuration.\n",
26974 +                            val);
26975 +               }
26976 +               val =
26977 +                   (dwc_otg_get_param_phy_type(core_if) ==
26978 +                    DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
26979 +               retval = -DWC_E_INVALID;
26980 +       }
26981 +       core_if->core_params->speed = val;
26982 +       return retval;
26983 +}
26984 +
26985 +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
26986 +{
26987 +       return core_if->core_params->speed;
26988 +}
26989 +
26990 +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
26991 +                                               int32_t val)
26992 +{
26993 +       int retval = 0;
26994 +
26995 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26996 +               DWC_WARN
26997 +                   ("Wrong value for host_ls_low_power_phy_clk parameter\n");
26998 +               DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
26999 +               return -DWC_E_INVALID;
27000 +       }
27001 +
27002 +       if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
27003 +           && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
27004 +               if (dwc_otg_param_initialized
27005 +                   (core_if->core_params->host_ls_low_power_phy_clk)) {
27006 +                       DWC_ERROR
27007 +                           ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
27008 +                            val);
27009 +               }
27010 +               val =
27011 +                   (dwc_otg_get_param_phy_type(core_if) ==
27012 +                    DWC_PHY_TYPE_PARAM_FS) ?
27013 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
27014 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
27015 +               retval = -DWC_E_INVALID;
27016 +       }
27017 +
27018 +       core_if->core_params->host_ls_low_power_phy_clk = val;
27019 +       return retval;
27020 +}
27021 +
27022 +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
27023 +{
27024 +       return core_if->core_params->host_ls_low_power_phy_clk;
27025 +}
27026 +
27027 +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
27028 +{
27029 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27030 +               DWC_WARN("Wrong value for phy_ulpi_ddr\n");
27031 +               DWC_WARN("phy_upli_ddr must be 0 or 1\n");
27032 +               return -DWC_E_INVALID;
27033 +       }
27034 +
27035 +       core_if->core_params->phy_ulpi_ddr = val;
27036 +       return 0;
27037 +}
27038 +
27039 +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
27040 +{
27041 +       return core_if->core_params->phy_ulpi_ddr;
27042 +}
27043 +
27044 +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
27045 +                                       int32_t val)
27046 +{
27047 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27048 +               DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
27049 +               DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
27050 +               return -DWC_E_INVALID;
27051 +       }
27052 +
27053 +       core_if->core_params->phy_ulpi_ext_vbus = val;
27054 +       return 0;
27055 +}
27056 +
27057 +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
27058 +{
27059 +       return core_if->core_params->phy_ulpi_ext_vbus;
27060 +}
27061 +
27062 +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
27063 +{
27064 +       if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
27065 +               DWC_WARN("Wrong valaue for phy_utmi_width\n");
27066 +               DWC_WARN("phy_utmi_width must be 8 or 16\n");
27067 +               return -DWC_E_INVALID;
27068 +       }
27069 +
27070 +       core_if->core_params->phy_utmi_width = val;
27071 +       return 0;
27072 +}
27073 +
27074 +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
27075 +{
27076 +       return core_if->core_params->phy_utmi_width;
27077 +}
27078 +
27079 +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
27080 +{
27081 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27082 +               DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
27083 +               DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
27084 +               return -DWC_E_INVALID;
27085 +       }
27086 +
27087 +       core_if->core_params->ulpi_fs_ls = val;
27088 +       return 0;
27089 +}
27090 +
27091 +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
27092 +{
27093 +       return core_if->core_params->ulpi_fs_ls;
27094 +}
27095 +
27096 +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
27097 +{
27098 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27099 +               DWC_WARN("Wrong valaue for ts_dline\n");
27100 +               DWC_WARN("ts_dline must be 0 or 1\n");
27101 +               return -DWC_E_INVALID;
27102 +       }
27103 +
27104 +       core_if->core_params->ts_dline = val;
27105 +       return 0;
27106 +}
27107 +
27108 +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
27109 +{
27110 +       return core_if->core_params->ts_dline;
27111 +}
27112 +
27113 +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
27114 +{
27115 +       int retval = 0;
27116 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27117 +               DWC_WARN("Wrong valaue for i2c_enable\n");
27118 +               DWC_WARN("i2c_enable must be 0 or 1\n");
27119 +               return -DWC_E_INVALID;
27120 +       }
27121 +#ifndef NO_FS_PHY_HW_CHECK
27122 +       if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
27123 +               if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
27124 +                       DWC_ERROR
27125 +                           ("%d invalid for i2c_enable. Check HW configuration.\n",
27126 +                            val);
27127 +               }
27128 +               val = 0;
27129 +               retval = -DWC_E_INVALID;
27130 +       }
27131 +#endif
27132 +
27133 +       core_if->core_params->i2c_enable = val;
27134 +       return retval;
27135 +}
27136 +
27137 +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
27138 +{
27139 +       return core_if->core_params->i2c_enable;
27140 +}
27141 +
27142 +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27143 +                                            int32_t val, int fifo_num)
27144 +{
27145 +       int retval = 0;
27146 +
27147 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27148 +               DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
27149 +               DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
27150 +               return -DWC_E_INVALID;
27151 +       }
27152 +
27153 +       if (val >
27154 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27155 +               if (dwc_otg_param_initialized
27156 +                   (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
27157 +                       DWC_ERROR
27158 +                           ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
27159 +                            val, fifo_num);
27160 +               }
27161 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27162 +               retval = -DWC_E_INVALID;
27163 +       }
27164 +
27165 +       core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
27166 +       return retval;
27167 +}
27168 +
27169 +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27170 +                                                int fifo_num)
27171 +{
27172 +       return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
27173 +}
27174 +
27175 +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
27176 +                                         int32_t val)
27177 +{
27178 +       int retval = 0;
27179 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27180 +               DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
27181 +               DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
27182 +               return -DWC_E_INVALID;
27183 +       }
27184 +
27185 +       if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
27186 +               if (dwc_otg_param_initialized
27187 +                   (core_if->core_params->en_multiple_tx_fifo)) {
27188 +                       DWC_ERROR
27189 +                           ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
27190 +                            val);
27191 +               }
27192 +               val = 0;
27193 +               retval = -DWC_E_INVALID;
27194 +       }
27195 +
27196 +       core_if->core_params->en_multiple_tx_fifo = val;
27197 +       return retval;
27198 +}
27199 +
27200 +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
27201 +{
27202 +       return core_if->core_params->en_multiple_tx_fifo;
27203 +}
27204 +
27205 +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
27206 +                                      int fifo_num)
27207 +{
27208 +       int retval = 0;
27209 +
27210 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27211 +               DWC_WARN("Wrong value for dev_tx_fifo_size\n");
27212 +               DWC_WARN("dev_tx_fifo_size must be 4-768\n");
27213 +               return -DWC_E_INVALID;
27214 +       }
27215 +
27216 +       if (val >
27217 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27218 +               if (dwc_otg_param_initialized
27219 +                   (core_if->core_params->dev_tx_fifo_size[fifo_num])) {
27220 +                       DWC_ERROR
27221 +                           ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
27222 +                            val, fifo_num);
27223 +               }
27224 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27225 +               retval = -DWC_E_INVALID;
27226 +       }
27227 +
27228 +       core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
27229 +       return retval;
27230 +}
27231 +
27232 +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
27233 +                                          int fifo_num)
27234 +{
27235 +       return core_if->core_params->dev_tx_fifo_size[fifo_num];
27236 +}
27237 +
27238 +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27239 +{
27240 +       int retval = 0;
27241 +
27242 +       if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
27243 +               DWC_WARN("Wrong value for thr_ctl\n");
27244 +               DWC_WARN("thr_ctl must be 0-7\n");
27245 +               return -DWC_E_INVALID;
27246 +       }
27247 +
27248 +       if ((val != 0) &&
27249 +           (!dwc_otg_get_param_dma_enable(core_if) ||
27250 +            !core_if->hwcfg4.b.ded_fifo_en)) {
27251 +               if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
27252 +                       DWC_ERROR
27253 +                           ("%d invalid for parameter thr_ctl. Check HW configuration.\n",
27254 +                            val);
27255 +               }
27256 +               val = 0;
27257 +               retval = -DWC_E_INVALID;
27258 +       }
27259 +
27260 +       core_if->core_params->thr_ctl = val;
27261 +       return retval;
27262 +}
27263 +
27264 +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
27265 +{
27266 +       return core_if->core_params->thr_ctl;
27267 +}
27268 +
27269 +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
27270 +{
27271 +       int retval = 0;
27272 +
27273 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27274 +               DWC_WARN("Wrong value for lpm_enable\n");
27275 +               DWC_WARN("lpm_enable must be 0 or 1\n");
27276 +               return -DWC_E_INVALID;
27277 +       }
27278 +
27279 +       if (val && !core_if->hwcfg3.b.otg_lpm_en) {
27280 +               if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
27281 +                       DWC_ERROR
27282 +                           ("%d invalid for parameter lpm_enable. Check HW configuration.\n",
27283 +                            val);
27284 +               }
27285 +               val = 0;
27286 +               retval = -DWC_E_INVALID;
27287 +       }
27288 +
27289 +       core_if->core_params->lpm_enable = val;
27290 +       return retval;
27291 +}
27292 +
27293 +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
27294 +{
27295 +       return core_if->core_params->lpm_enable;
27296 +}
27297 +
27298 +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27299 +{
27300 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27301 +               DWC_WARN("Wrong valaue for tx_thr_length\n");
27302 +               DWC_WARN("tx_thr_length must be 8 - 128\n");
27303 +               return -DWC_E_INVALID;
27304 +       }
27305 +
27306 +       core_if->core_params->tx_thr_length = val;
27307 +       return 0;
27308 +}
27309 +
27310 +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
27311 +{
27312 +       return core_if->core_params->tx_thr_length;
27313 +}
27314 +
27315 +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27316 +{
27317 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27318 +               DWC_WARN("Wrong valaue for rx_thr_length\n");
27319 +               DWC_WARN("rx_thr_length must be 8 - 128\n");
27320 +               return -DWC_E_INVALID;
27321 +       }
27322 +
27323 +       core_if->core_params->rx_thr_length = val;
27324 +       return 0;
27325 +}
27326 +
27327 +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
27328 +{
27329 +       return core_if->core_params->rx_thr_length;
27330 +}
27331 +
27332 +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
27333 +{
27334 +       if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
27335 +           DWC_OTG_PARAM_TEST(val, 4, 4) &&
27336 +           DWC_OTG_PARAM_TEST(val, 8, 8) &&
27337 +           DWC_OTG_PARAM_TEST(val, 16, 16) &&
27338 +           DWC_OTG_PARAM_TEST(val, 32, 32) &&
27339 +           DWC_OTG_PARAM_TEST(val, 64, 64) &&
27340 +           DWC_OTG_PARAM_TEST(val, 128, 128) &&
27341 +           DWC_OTG_PARAM_TEST(val, 256, 256)) {
27342 +               DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
27343 +               return -DWC_E_INVALID;
27344 +       }
27345 +       core_if->core_params->dma_burst_size = val;
27346 +       return 0;
27347 +}
27348 +
27349 +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
27350 +{
27351 +       return core_if->core_params->dma_burst_size;
27352 +}
27353 +
27354 +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
27355 +{
27356 +       int retval = 0;
27357 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27358 +               DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
27359 +               return -DWC_E_INVALID;
27360 +       }
27361 +       if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
27362 +               if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
27363 +                       DWC_ERROR
27364 +                           ("%d invalid for parameter pti_enable. Check HW configuration.\n",
27365 +                            val);
27366 +               }
27367 +               retval = -DWC_E_INVALID;
27368 +               val = 0;
27369 +       }
27370 +       core_if->core_params->pti_enable = val;
27371 +       return retval;
27372 +}
27373 +
27374 +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
27375 +{
27376 +       return core_if->core_params->pti_enable;
27377 +}
27378 +
27379 +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
27380 +{
27381 +       int retval = 0;
27382 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27383 +               DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
27384 +               return -DWC_E_INVALID;
27385 +       }
27386 +       if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
27387 +               if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
27388 +                       DWC_ERROR
27389 +                           ("%d invalid for parameter mpi_enable. Check HW configuration.\n",
27390 +                            val);
27391 +               }
27392 +               retval = -DWC_E_INVALID;
27393 +               val = 0;
27394 +       }
27395 +       core_if->core_params->mpi_enable = val;
27396 +       return retval;
27397 +}
27398 +
27399 +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
27400 +{
27401 +       return core_if->core_params->mpi_enable;
27402 +}
27403 +
27404 +int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)
27405 +{
27406 +       int retval = 0;
27407 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27408 +               DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);
27409 +               return -DWC_E_INVALID;
27410 +       }
27411 +       if (val && (core_if->hwcfg3.b.adp_supp == 0)) {
27412 +               if (dwc_otg_param_initialized
27413 +                   (core_if->core_params->adp_supp_enable)) {
27414 +                       DWC_ERROR
27415 +                           ("%d invalid for parameter adp_enable. Check HW configuration.\n",
27416 +                            val);
27417 +               }
27418 +               retval = -DWC_E_INVALID;
27419 +               val = 0;
27420 +       }
27421 +       core_if->core_params->adp_supp_enable = val;
27422 +       /*Set OTG version 2.0 in case of enabling ADP*/
27423 +       if (val)
27424 +               dwc_otg_set_param_otg_ver(core_if, 1);
27425 +
27426 +       return retval;
27427 +}
27428 +
27429 +int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)
27430 +{
27431 +       return core_if->core_params->adp_supp_enable;
27432 +}
27433 +
27434 +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)
27435 +{
27436 +       int retval = 0;
27437 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27438 +               DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
27439 +               DWC_WARN("ic_usb_cap must be 0 or 1\n");
27440 +               return -DWC_E_INVALID;
27441 +       }
27442 +
27443 +       if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {
27444 +               if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
27445 +                       DWC_ERROR
27446 +                           ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
27447 +                            val);
27448 +               }
27449 +               retval = -DWC_E_INVALID;
27450 +               val = 0;
27451 +       }
27452 +       core_if->core_params->ic_usb_cap = val;
27453 +       return retval;
27454 +}
27455 +
27456 +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
27457 +{
27458 +       return core_if->core_params->ic_usb_cap;
27459 +}
27460 +
27461 +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
27462 +{
27463 +       int retval = 0;
27464 +       int valid = 1;
27465 +
27466 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27467 +               DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
27468 +               DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
27469 +               return -DWC_E_INVALID;
27470 +       }
27471 +
27472 +       if (val
27473 +           && (core_if->snpsid < OTG_CORE_REV_2_81a
27474 +               || !dwc_otg_get_param_thr_ctl(core_if))) {
27475 +               valid = 0;
27476 +       } else if (val
27477 +                  && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <
27478 +                      4)) {
27479 +               valid = 0;
27480 +       }
27481 +       if (valid == 0) {
27482 +               if (dwc_otg_param_initialized
27483 +                   (core_if->core_params->ahb_thr_ratio)) {
27484 +                       DWC_ERROR
27485 +                           ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",
27486 +                            val);
27487 +               }
27488 +               retval = -DWC_E_INVALID;
27489 +               val = 0;
27490 +       }
27491 +
27492 +       core_if->core_params->ahb_thr_ratio = val;
27493 +       return retval;
27494 +}
27495 +
27496 +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
27497 +{
27498 +       return core_if->core_params->ahb_thr_ratio;
27499 +}
27500 +
27501 +int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)
27502 +{
27503 +       int retval = 0;
27504 +       int valid = 1;
27505 +       hwcfg4_data_t hwcfg4 = {.d32 = 0 };
27506 +       hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
27507 +
27508 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27509 +               DWC_WARN("`%d' invalid for parameter `power_down'\n", val);
27510 +               DWC_WARN("power_down must be 0 - 2\n");
27511 +               return -DWC_E_INVALID;
27512 +       }
27513 +
27514 +       if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {
27515 +               valid = 0;
27516 +       }
27517 +       if ((val == 3)
27518 +           && ((core_if->snpsid < OTG_CORE_REV_3_00a)
27519 +               || (hwcfg4.b.xhiber == 0))) {
27520 +               valid = 0;
27521 +       }
27522 +       if (valid == 0) {
27523 +               if (dwc_otg_param_initialized(core_if->core_params->power_down)) {
27524 +                       DWC_ERROR
27525 +                           ("%d invalid for parameter power_down. Check HW configuration.\n",
27526 +                            val);
27527 +               }
27528 +               retval = -DWC_E_INVALID;
27529 +               val = 0;
27530 +       }
27531 +       core_if->core_params->power_down = val;
27532 +       return retval;
27533 +}
27534 +
27535 +int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)
27536 +{
27537 +       return core_if->core_params->power_down;
27538 +}
27539 +
27540 +int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27541 +{
27542 +       int retval = 0;
27543 +       int valid = 1;
27544 +
27545 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27546 +               DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);
27547 +               DWC_WARN("reload_ctl must be 0 or 1\n");
27548 +               return -DWC_E_INVALID;
27549 +       }
27550 +
27551 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {
27552 +               valid = 0;
27553 +       }
27554 +       if (valid == 0) {
27555 +               if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {
27556 +                       DWC_ERROR("%d invalid for parameter reload_ctl."
27557 +                                 "Check HW configuration.\n", val);
27558 +               }
27559 +               retval = -DWC_E_INVALID;
27560 +               val = 0;
27561 +       }
27562 +       core_if->core_params->reload_ctl = val;
27563 +       return retval;
27564 +}
27565 +
27566 +int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)
27567 +{
27568 +       return core_if->core_params->reload_ctl;
27569 +}
27570 +
27571 +int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)
27572 +{
27573 +       int retval = 0;
27574 +       int valid = 1;
27575 +
27576 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27577 +               DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);
27578 +               DWC_WARN("dev_out_nak must be 0 or 1\n");
27579 +               return -DWC_E_INVALID;
27580 +       }
27581 +
27582 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||
27583 +               !(core_if->core_params->dma_desc_enable))) {
27584 +               valid = 0;
27585 +       }
27586 +       if (valid == 0) {
27587 +               if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {
27588 +                       DWC_ERROR("%d invalid for parameter dev_out_nak."
27589 +                               "Check HW configuration.\n", val);
27590 +               }
27591 +               retval = -DWC_E_INVALID;
27592 +               val = 0;
27593 +       }
27594 +       core_if->core_params->dev_out_nak = val;
27595 +       return retval;
27596 +}
27597 +
27598 +int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)
27599 +{
27600 +       return core_if->core_params->dev_out_nak;
27601 +}
27602 +
27603 +int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
27604 +{
27605 +       int retval = 0;
27606 +       int valid = 1;
27607 +
27608 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27609 +               DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
27610 +               DWC_WARN("cont_on_bna must be 0 or 1\n");
27611 +               return -DWC_E_INVALID;
27612 +       }
27613 +
27614 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
27615 +               !(core_if->core_params->dma_desc_enable))) {
27616 +                       valid = 0;
27617 +       }
27618 +       if (valid == 0) {
27619 +               if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
27620 +                       DWC_ERROR("%d invalid for parameter cont_on_bna."
27621 +                               "Check HW configuration.\n", val);
27622 +               }
27623 +               retval = -DWC_E_INVALID;
27624 +               val = 0;
27625 +       }
27626 +       core_if->core_params->cont_on_bna = val;
27627 +       return retval;
27628 +}
27629 +
27630 +int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
27631 +{
27632 +       return core_if->core_params->cont_on_bna;
27633 +}
27634 +
27635 +int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
27636 +{
27637 +       int retval = 0;
27638 +       int valid = 1;
27639 +
27640 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27641 +               DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
27642 +               DWC_WARN("ahb_single must be 0 or 1\n");
27643 +               return -DWC_E_INVALID;
27644 +       }
27645 +
27646 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
27647 +                       valid = 0;
27648 +       }
27649 +       if (valid == 0) {
27650 +               if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
27651 +                       DWC_ERROR("%d invalid for parameter ahb_single."
27652 +                               "Check HW configuration.\n", val);
27653 +               }
27654 +               retval = -DWC_E_INVALID;
27655 +               val = 0;
27656 +       }
27657 +       core_if->core_params->ahb_single = val;
27658 +       return retval;
27659 +}
27660 +
27661 +int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
27662 +{
27663 +       return core_if->core_params->ahb_single;
27664 +}
27665 +
27666 +int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
27667 +{
27668 +       int retval = 0;
27669 +
27670 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27671 +               DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);
27672 +               DWC_WARN
27673 +                   ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");
27674 +               return -DWC_E_INVALID;
27675 +       }
27676 +
27677 +       core_if->core_params->otg_ver = val;
27678 +       return retval;
27679 +}
27680 +
27681 +int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)
27682 +{
27683 +       return core_if->core_params->otg_ver;
27684 +}
27685 +
27686 +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
27687 +{
27688 +       gotgctl_data_t otgctl;
27689 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27690 +       return otgctl.b.hstnegscs;
27691 +}
27692 +
27693 +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
27694 +{
27695 +       gotgctl_data_t otgctl;
27696 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27697 +       return otgctl.b.sesreqscs;
27698 +}
27699 +
27700 +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
27701 +{
27702 +       if(core_if->otg_ver == 0) {
27703 +               gotgctl_data_t otgctl;
27704 +               otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27705 +               otgctl.b.hnpreq = val;
27706 +               DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);
27707 +       } else {
27708 +               core_if->otg_sts = val;
27709 +       }
27710 +}
27711 +
27712 +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
27713 +{
27714 +       return core_if->snpsid;
27715 +}
27716 +
27717 +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
27718 +{
27719 +       gintsts_data_t gintsts;
27720 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
27721 +       return gintsts.b.curmode;
27722 +}
27723 +
27724 +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
27725 +{
27726 +       gusbcfg_data_t usbcfg;
27727 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27728 +       return usbcfg.b.hnpcap;
27729 +}
27730 +
27731 +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27732 +{
27733 +       gusbcfg_data_t usbcfg;
27734 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27735 +       usbcfg.b.hnpcap = val;
27736 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27737 +}
27738 +
27739 +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
27740 +{
27741 +       gusbcfg_data_t usbcfg;
27742 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27743 +       return usbcfg.b.srpcap;
27744 +}
27745 +
27746 +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27747 +{
27748 +       gusbcfg_data_t usbcfg;
27749 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27750 +       usbcfg.b.srpcap = val;
27751 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27752 +}
27753 +
27754 +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
27755 +{
27756 +       dcfg_data_t dcfg;
27757 +       /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */
27758 +
27759 +        dcfg.d32 = -1; //GRAYG
27760 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
27761 +        if (NULL == core_if)
27762 +                DWC_ERROR("reg request with NULL core_if\n");
27763 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
27764 +                    core_if, core_if->dev_if);
27765 +        if (NULL == core_if->dev_if)
27766 +                DWC_ERROR("reg request with NULL dev_if\n");
27767 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
27768 +                    "dev_global_regs(%p)\n", __func__,
27769 +                    core_if, core_if->dev_if,
27770 +                    core_if->dev_if->dev_global_regs);
27771 +        if (NULL == core_if->dev_if->dev_global_regs)
27772 +                DWC_ERROR("reg request with NULL dev_global_regs\n");
27773 +        else {
27774 +                DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
27775 +                            "dev_global_regs(%p)->dcfg = %p\n", __func__,
27776 +                            core_if, core_if->dev_if,
27777 +                            core_if->dev_if->dev_global_regs,
27778 +                            &core_if->dev_if->dev_global_regs->dcfg);
27779 +               dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27780 +        }
27781 +       return dcfg.b.devspd;
27782 +}
27783 +
27784 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
27785 +{
27786 +       dcfg_data_t dcfg;
27787 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27788 +       dcfg.b.devspd = val;
27789 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
27790 +}
27791 +
27792 +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
27793 +{
27794 +       hprt0_data_t hprt0;
27795 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27796 +       return hprt0.b.prtconnsts;
27797 +}
27798 +
27799 +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
27800 +{
27801 +       dsts_data_t dsts;
27802 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
27803 +       return dsts.b.enumspd;
27804 +}
27805 +
27806 +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
27807 +{
27808 +       hprt0_data_t hprt0;
27809 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27810 +       return hprt0.b.prtpwr;
27811 +
27812 +}
27813 +
27814 +uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)
27815 +{
27816 +       return core_if->hibernation_suspend;
27817 +}
27818 +
27819 +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
27820 +{
27821 +       hprt0_data_t hprt0;
27822 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27823 +       hprt0.b.prtpwr = val;
27824 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27825 +}
27826 +
27827 +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
27828 +{
27829 +       hprt0_data_t hprt0;
27830 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27831 +       return hprt0.b.prtsusp;
27832 +
27833 +}
27834 +
27835 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
27836 +{
27837 +       hprt0_data_t hprt0;
27838 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27839 +       hprt0.b.prtsusp = val;
27840 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27841 +}
27842 +
27843 +uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)
27844 +{
27845 +       hfir_data_t hfir;
27846 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27847 +       return hfir.b.frint;
27848 +
27849 +}
27850 +
27851 +void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)
27852 +{
27853 +       hfir_data_t hfir;
27854 +       uint32_t fram_int;
27855 +       fram_int = calc_frame_interval(core_if);
27856 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27857 +       if (!core_if->core_params->reload_ctl) {
27858 +               DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"
27859 +                        "not set to 1.\nShould load driver with reload_ctl=1"
27860 +                        " module parameter\n");
27861 +               return;
27862 +       }
27863 +       switch (fram_int) {
27864 +       case 3750:
27865 +               if ((val < 3350) || (val > 4150)) {
27866 +                       DWC_WARN("HFIR interval for HS core and 30 MHz"
27867 +                                "clock freq should be from 3350 to 4150\n");
27868 +                       return;
27869 +               }
27870 +               break;
27871 +       case 30000:
27872 +               if ((val < 26820) || (val > 33180)) {
27873 +                       DWC_WARN("HFIR interval for FS/LS core and 30 MHz"
27874 +                                "clock freq should be from 26820 to 33180\n");
27875 +                       return;
27876 +               }
27877 +               break;
27878 +       case 6000:
27879 +               if ((val < 5360) || (val > 6640)) {
27880 +                       DWC_WARN("HFIR interval for HS core and 48 MHz"
27881 +                                "clock freq should be from 5360 to 6640\n");
27882 +                       return;
27883 +               }
27884 +               break;
27885 +       case 48000:
27886 +               if ((val < 42912) || (val > 53088)) {
27887 +                       DWC_WARN("HFIR interval for FS/LS core and 48 MHz"
27888 +                                "clock freq should be from 42912 to 53088\n");
27889 +                       return;
27890 +               }
27891 +               break;
27892 +       case 7500:
27893 +               if ((val < 6700) || (val > 8300)) {
27894 +                       DWC_WARN("HFIR interval for HS core and 60 MHz"
27895 +                                "clock freq should be from 6700 to 8300\n");
27896 +                       return;
27897 +               }
27898 +               break;
27899 +       case 60000:
27900 +               if ((val < 53640) || (val > 65536)) {
27901 +                       DWC_WARN("HFIR interval for FS/LS core and 60 MHz"
27902 +                                "clock freq should be from 53640 to 65536\n");
27903 +                       return;
27904 +               }
27905 +               break;
27906 +       default:
27907 +               DWC_WARN("Unknown frame interval\n");
27908 +               return;
27909 +               break;
27910 +
27911 +       }
27912 +       hfir.b.frint = val;
27913 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);
27914 +}
27915 +
27916 +uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)
27917 +{
27918 +       hcfg_data_t hcfg;
27919 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
27920 +       return hcfg.b.modechtimen;
27921 +
27922 +}
27923 +
27924 +void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)
27925 +{
27926 +       hcfg_data_t hcfg;
27927 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
27928 +       hcfg.b.modechtimen = val;
27929 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
27930 +}
27931 +
27932 +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
27933 +{
27934 +       hprt0_data_t hprt0;
27935 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27936 +       hprt0.b.prtres = val;
27937 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27938 +}
27939 +
27940 +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
27941 +{
27942 +       dctl_data_t dctl;
27943 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
27944 +       return dctl.b.rmtwkupsig;
27945 +}
27946 +
27947 +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
27948 +{
27949 +       glpmcfg_data_t lpmcfg;
27950 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27951 +
27952 +       DWC_ASSERT(!
27953 +                  ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
27954 +                  "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
27955 +                  core_if->lx_state, lpmcfg.b.prt_sleep_sts);
27956 +
27957 +       return lpmcfg.b.prt_sleep_sts;
27958 +}
27959 +
27960 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
27961 +{
27962 +       glpmcfg_data_t lpmcfg;
27963 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27964 +       return lpmcfg.b.rem_wkup_en;
27965 +}
27966 +
27967 +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
27968 +{
27969 +       glpmcfg_data_t lpmcfg;
27970 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27971 +       return lpmcfg.b.appl_resp;
27972 +}
27973 +
27974 +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
27975 +{
27976 +       glpmcfg_data_t lpmcfg;
27977 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27978 +       lpmcfg.b.appl_resp = val;
27979 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
27980 +}
27981 +
27982 +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
27983 +{
27984 +       glpmcfg_data_t lpmcfg;
27985 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27986 +       return lpmcfg.b.hsic_connect;
27987 +}
27988 +
27989 +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
27990 +{
27991 +       glpmcfg_data_t lpmcfg;
27992 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27993 +       lpmcfg.b.hsic_connect = val;
27994 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
27995 +}
27996 +
27997 +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
27998 +{
27999 +       glpmcfg_data_t lpmcfg;
28000 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28001 +       return lpmcfg.b.inv_sel_hsic;
28002 +
28003 +}
28004 +
28005 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
28006 +{
28007 +       glpmcfg_data_t lpmcfg;
28008 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28009 +       lpmcfg.b.inv_sel_hsic = val;
28010 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28011 +}
28012 +
28013 +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
28014 +{
28015 +       return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
28016 +}
28017 +
28018 +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
28019 +{
28020 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);
28021 +}
28022 +
28023 +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
28024 +{
28025 +       return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
28026 +}
28027 +
28028 +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
28029 +{
28030 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);
28031 +}
28032 +
28033 +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
28034 +{
28035 +       return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
28036 +}
28037 +
28038 +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28039 +{
28040 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);
28041 +}
28042 +
28043 +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
28044 +{
28045 +       return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
28046 +}
28047 +
28048 +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28049 +{
28050 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);
28051 +}
28052 +
28053 +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
28054 +{
28055 +       return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);
28056 +}
28057 +
28058 +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
28059 +{
28060 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);
28061 +}
28062 +
28063 +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
28064 +{
28065 +       return DWC_READ_REG32(&core_if->core_global_regs->ggpio);
28066 +}
28067 +
28068 +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
28069 +{
28070 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);
28071 +}
28072 +
28073 +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
28074 +{
28075 +       return DWC_READ_REG32(core_if->host_if->hprt0);
28076 +
28077 +}
28078 +
28079 +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
28080 +{
28081 +       DWC_WRITE_REG32(core_if->host_if->hprt0, val);
28082 +}
28083 +
28084 +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
28085 +{
28086 +       return DWC_READ_REG32(&core_if->core_global_regs->guid);
28087 +}
28088 +
28089 +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
28090 +{
28091 +       DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);
28092 +}
28093 +
28094 +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
28095 +{
28096 +       return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
28097 +}
28098 +
28099 +uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)
28100 +{
28101 +       return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);
28102 +}
28103 +
28104 +/**
28105 + * Start the SRP timer to detect when the SRP does not complete within
28106 + * 6 seconds.
28107 + *
28108 + * @param core_if the pointer to core_if strucure.
28109 + */
28110 +void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)
28111 +{
28112 +       core_if->srp_timer_started = 1;
28113 +       DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );
28114 +}
28115 +
28116 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)
28117 +{
28118 +       uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);
28119 +       gotgctl_data_t mem;
28120 +       gotgctl_data_t val;
28121 +
28122 +       val.d32 = DWC_READ_REG32(addr);
28123 +       if (val.b.sesreq) {
28124 +               DWC_ERROR("Session Request Already active!\n");
28125 +               return;
28126 +       }
28127 +
28128 +       DWC_INFO("Session Request Initated\n"); //NOTICE
28129 +       mem.d32 = DWC_READ_REG32(addr);
28130 +       mem.b.sesreq = 1;
28131 +       DWC_WRITE_REG32(addr, mem.d32);
28132 +
28133 +       /* Start the SRP timer */
28134 +       dwc_otg_pcd_start_srp_timer(core_if);
28135 +       return;
28136 +}
28137 --- /dev/null
28138 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
28139 @@ -0,0 +1,1464 @@
28140 +/* ==========================================================================
28141 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
28142 + * $Revision: #123 $
28143 + * $Date: 2012/08/10 $
28144 + * $Change: 2047372 $
28145 + *
28146 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
28147 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
28148 + * otherwise expressly agreed to in writing between Synopsys and you.
28149 + *
28150 + * The Software IS NOT an item of Licensed Software or Licensed Product under
28151 + * any End User Software License Agreement or Agreement for Licensed Product
28152 + * with Synopsys or any supplement thereto. You are permitted to use and
28153 + * redistribute this Software in source and binary forms, with or without
28154 + * modification, provided that redistributions of source code must retain this
28155 + * notice. You may not view, use, disclose, copy or distribute this file or
28156 + * any information contained herein except pursuant to this license grant from
28157 + * Synopsys. If you do not agree with this notice, including the disclaimer
28158 + * below, then you are not authorized to use the Software.
28159 + *
28160 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
28161 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28162 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28163 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
28164 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28165 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28166 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28167 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28168 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28169 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28170 + * DAMAGE.
28171 + * ========================================================================== */
28172 +
28173 +#if !defined(__DWC_CIL_H__)
28174 +#define __DWC_CIL_H__
28175 +
28176 +#include "dwc_list.h"
28177 +#include "dwc_otg_dbg.h"
28178 +#include "dwc_otg_regs.h"
28179 +
28180 +#include "dwc_otg_core_if.h"
28181 +#include "dwc_otg_adp.h"
28182 +
28183 +/**
28184 + * @file
28185 + * This file contains the interface to the Core Interface Layer.
28186 + */
28187 +
28188 +#ifdef DWC_UTE_CFI
28189 +
28190 +#define MAX_DMA_DESCS_PER_EP   256
28191 +
28192 +/**
28193 + * Enumeration for the data buffer mode
28194 + */
28195 +typedef enum _data_buffer_mode {
28196 +       BM_STANDARD = 0,        /* data buffer is in normal mode */
28197 +       BM_SG = 1,              /* data buffer uses the scatter/gather mode */
28198 +       BM_CONCAT = 2,          /* data buffer uses the concatenation mode */
28199 +       BM_CIRCULAR = 3,        /* data buffer uses the circular DMA mode */
28200 +       BM_ALIGN = 4            /* data buffer is in buffer alignment mode */
28201 +} data_buffer_mode_e;
28202 +#endif //DWC_UTE_CFI
28203 +
28204 +/** Macros defined for DWC OTG HW Release version */
28205 +
28206 +#define OTG_CORE_REV_2_60a     0x4F54260A
28207 +#define OTG_CORE_REV_2_71a     0x4F54271A
28208 +#define OTG_CORE_REV_2_72a     0x4F54272A
28209 +#define OTG_CORE_REV_2_80a     0x4F54280A
28210 +#define OTG_CORE_REV_2_81a     0x4F54281A
28211 +#define OTG_CORE_REV_2_90a     0x4F54290A
28212 +#define OTG_CORE_REV_2_91a     0x4F54291A
28213 +#define OTG_CORE_REV_2_92a     0x4F54292A
28214 +#define OTG_CORE_REV_2_93a     0x4F54293A
28215 +#define OTG_CORE_REV_2_94a     0x4F54294A
28216 +#define OTG_CORE_REV_3_00a     0x4F54300A
28217 +
28218 +/**
28219 + * Information for each ISOC packet.
28220 + */
28221 +typedef struct iso_pkt_info {
28222 +       uint32_t offset;
28223 +       uint32_t length;
28224 +       int32_t status;
28225 +} iso_pkt_info_t;
28226 +
28227 +/**
28228 + * The <code>dwc_ep</code> structure represents the state of a single
28229 + * endpoint when acting in device mode. It contains the data items
28230 + * needed for an endpoint to be activated and transfer packets.
28231 + */
28232 +typedef struct dwc_ep {
28233 +       /** EP number used for register address lookup */
28234 +       uint8_t num;
28235 +       /** EP direction 0 = OUT */
28236 +       unsigned is_in:1;
28237 +       /** EP active. */
28238 +       unsigned active:1;
28239 +
28240 +       /**
28241 +        * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
28242 +        * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
28243 +       unsigned tx_fifo_num:4;
28244 +       /** EP type: 0 - Control, 1 - ISOC,      2 - BULK,      3 - INTR */
28245 +       unsigned type:2;
28246 +#define DWC_OTG_EP_TYPE_CONTROL           0
28247 +#define DWC_OTG_EP_TYPE_ISOC      1
28248 +#define DWC_OTG_EP_TYPE_BULK      2
28249 +#define DWC_OTG_EP_TYPE_INTR      3
28250 +
28251 +       /** DATA start PID for INTR and BULK EP */
28252 +       unsigned data_pid_start:1;
28253 +       /** Frame (even/odd) for ISOC EP */
28254 +       unsigned even_odd_frame:1;
28255 +       /** Max Packet bytes */
28256 +       unsigned maxpacket:11;
28257 +
28258 +       /** Max Transfer size */
28259 +       uint32_t maxxfer;
28260 +
28261 +       /** @name Transfer state */
28262 +       /** @{ */
28263 +
28264 +       /**
28265 +        * Pointer to the beginning of the transfer buffer -- do not modify
28266 +        * during transfer.
28267 +        */
28268 +
28269 +       dwc_dma_t dma_addr;
28270 +
28271 +       dwc_dma_t dma_desc_addr;
28272 +       dwc_otg_dev_dma_desc_t *desc_addr;
28273 +
28274 +       uint8_t *start_xfer_buff;
28275 +       /** pointer to the transfer buffer */
28276 +       uint8_t *xfer_buff;
28277 +       /** Number of bytes to transfer */
28278 +       unsigned xfer_len:19;
28279 +       /** Number of bytes transferred. */
28280 +       unsigned xfer_count:19;
28281 +       /** Sent ZLP */
28282 +       unsigned sent_zlp:1;
28283 +       /** Total len for control transfer */
28284 +       unsigned total_len:19;
28285 +
28286 +       /** stall clear flag */
28287 +       unsigned stall_clear_flag:1;
28288 +
28289 +       /** SETUP pkt cnt rollover flag for EP0 out*/
28290 +       unsigned stp_rollover;
28291 +
28292 +#ifdef DWC_UTE_CFI
28293 +       /* The buffer mode */
28294 +       data_buffer_mode_e buff_mode;
28295 +
28296 +       /* The chain of DMA descriptors.
28297 +        * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
28298 +        */
28299 +       dwc_otg_dma_desc_t *descs;
28300 +
28301 +       /* The DMA address of the descriptors chain start */
28302 +       dma_addr_t descs_dma_addr;
28303 +       /** This variable stores the length of the last enqueued request */
28304 +       uint32_t cfi_req_len;
28305 +#endif                         //DWC_UTE_CFI
28306 +
28307 +/** Max DMA Descriptor count for any EP */
28308 +#define MAX_DMA_DESC_CNT 256
28309 +       /** Allocated DMA Desc count */
28310 +       uint32_t desc_cnt;
28311 +
28312 +       /** bInterval */
28313 +       uint32_t bInterval;
28314 +       /** Next frame num to setup next ISOC transfer */
28315 +       uint32_t frame_num;
28316 +       /** Indicates SOF number overrun in DSTS */
28317 +       uint8_t frm_overrun;
28318 +
28319 +#ifdef DWC_UTE_PER_IO
28320 +       /** Next frame num for which will be setup DMA Desc */
28321 +       uint32_t xiso_frame_num;
28322 +       /** bInterval */
28323 +       uint32_t xiso_bInterval;
28324 +       /** Count of currently active transfers - shall be either 0 or 1 */
28325 +       int xiso_active_xfers;
28326 +       int xiso_queued_xfers;
28327 +#endif
28328 +#ifdef DWC_EN_ISOC
28329 +       /**
28330 +        * Variables specific for ISOC EPs
28331 +        *
28332 +        */
28333 +       /** DMA addresses of ISOC buffers */
28334 +       dwc_dma_t dma_addr0;
28335 +       dwc_dma_t dma_addr1;
28336 +
28337 +       dwc_dma_t iso_dma_desc_addr;
28338 +       dwc_otg_dev_dma_desc_t *iso_desc_addr;
28339 +
28340 +       /** pointer to the transfer buffers */
28341 +       uint8_t *xfer_buff0;
28342 +       uint8_t *xfer_buff1;
28343 +
28344 +       /** number of ISOC Buffer is processing */
28345 +       uint32_t proc_buf_num;
28346 +       /** Interval of ISOC Buffer processing */
28347 +       uint32_t buf_proc_intrvl;
28348 +       /** Data size for regular frame */
28349 +       uint32_t data_per_frame;
28350 +
28351 +       /* todo - pattern data support is to be implemented in the future */
28352 +       /** Data size for pattern frame */
28353 +       uint32_t data_pattern_frame;
28354 +       /** Frame number of pattern data */
28355 +       uint32_t sync_frame;
28356 +
28357 +       /** bInterval */
28358 +       uint32_t bInterval;
28359 +       /** ISO Packet number per frame */
28360 +       uint32_t pkt_per_frm;
28361 +       /** Next frame num for which will be setup DMA Desc */
28362 +       uint32_t next_frame;
28363 +       /** Number of packets per buffer processing */
28364 +       uint32_t pkt_cnt;
28365 +       /** Info for all isoc packets */
28366 +       iso_pkt_info_t *pkt_info;
28367 +       /** current pkt number */
28368 +       uint32_t cur_pkt;
28369 +       /** current pkt number */
28370 +       uint8_t *cur_pkt_addr;
28371 +       /** current pkt number */
28372 +       uint32_t cur_pkt_dma_addr;
28373 +#endif                         /* DWC_EN_ISOC */
28374 +
28375 +/** @} */
28376 +} dwc_ep_t;
28377 +
28378 +/*
28379 + * Reasons for halting a host channel.
28380 + */
28381 +typedef enum dwc_otg_halt_status {
28382 +       DWC_OTG_HC_XFER_NO_HALT_STATUS,
28383 +       DWC_OTG_HC_XFER_COMPLETE,
28384 +       DWC_OTG_HC_XFER_URB_COMPLETE,
28385 +       DWC_OTG_HC_XFER_ACK,
28386 +       DWC_OTG_HC_XFER_NAK,
28387 +       DWC_OTG_HC_XFER_NYET,
28388 +       DWC_OTG_HC_XFER_STALL,
28389 +       DWC_OTG_HC_XFER_XACT_ERR,
28390 +       DWC_OTG_HC_XFER_FRAME_OVERRUN,
28391 +       DWC_OTG_HC_XFER_BABBLE_ERR,
28392 +       DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
28393 +       DWC_OTG_HC_XFER_AHB_ERR,
28394 +       DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
28395 +       DWC_OTG_HC_XFER_URB_DEQUEUE
28396 +} dwc_otg_halt_status_e;
28397 +
28398 +/**
28399 + * Host channel descriptor. This structure represents the state of a single
28400 + * host channel when acting in host mode. It contains the data items needed to
28401 + * transfer packets to an endpoint via a host channel.
28402 + */
28403 +typedef struct dwc_hc {
28404 +       /** Host channel number used for register address lookup */
28405 +       uint8_t hc_num;
28406 +
28407 +       /** Device to access */
28408 +       unsigned dev_addr:7;
28409 +
28410 +       /** EP to access */
28411 +       unsigned ep_num:4;
28412 +
28413 +       /** EP direction. 0: OUT, 1: IN */
28414 +       unsigned ep_is_in:1;
28415 +
28416 +       /**
28417 +        * EP speed.
28418 +        * One of the following values:
28419 +        *      - DWC_OTG_EP_SPEED_LOW
28420 +        *      - DWC_OTG_EP_SPEED_FULL
28421 +        *      - DWC_OTG_EP_SPEED_HIGH
28422 +        */
28423 +       unsigned speed:2;
28424 +#define DWC_OTG_EP_SPEED_LOW   0
28425 +#define DWC_OTG_EP_SPEED_FULL  1
28426 +#define DWC_OTG_EP_SPEED_HIGH  2
28427 +
28428 +       /**
28429 +        * Endpoint type.
28430 +        * One of the following values:
28431 +        *      - DWC_OTG_EP_TYPE_CONTROL: 0
28432 +        *      - DWC_OTG_EP_TYPE_ISOC: 1
28433 +        *      - DWC_OTG_EP_TYPE_BULK: 2
28434 +        *      - DWC_OTG_EP_TYPE_INTR: 3
28435 +        */
28436 +       unsigned ep_type:2;
28437 +
28438 +       /** Max packet size in bytes */
28439 +       unsigned max_packet:11;
28440 +
28441 +       /**
28442 +        * PID for initial transaction.
28443 +        * 0: DATA0,<br>
28444 +        * 1: DATA2,<br>
28445 +        * 2: DATA1,<br>
28446 +        * 3: MDATA (non-Control EP),
28447 +        *        SETUP (Control EP)
28448 +        */
28449 +       unsigned data_pid_start:2;
28450 +#define DWC_OTG_HC_PID_DATA0 0
28451 +#define DWC_OTG_HC_PID_DATA2 1
28452 +#define DWC_OTG_HC_PID_DATA1 2
28453 +#define DWC_OTG_HC_PID_MDATA 3
28454 +#define DWC_OTG_HC_PID_SETUP 3
28455 +
28456 +       /** Number of periodic transactions per (micro)frame */
28457 +       unsigned multi_count:2;
28458 +
28459 +       /** @name Transfer State */
28460 +       /** @{ */
28461 +
28462 +       /** Pointer to the current transfer buffer position. */
28463 +       uint8_t *xfer_buff;
28464 +       /**
28465 +        * In Buffer DMA mode this buffer will be used
28466 +        * if xfer_buff is not DWORD aligned.
28467 +        */
28468 +       dwc_dma_t align_buff;
28469 +       /** Total number of bytes to transfer. */
28470 +       uint32_t xfer_len;
28471 +       /** Number of bytes transferred so far. */
28472 +       uint32_t xfer_count;
28473 +       /** Packet count at start of transfer.*/
28474 +       uint16_t start_pkt_count;
28475 +
28476 +       /**
28477 +        * Flag to indicate whether the transfer has been started. Set to 1 if
28478 +        * it has been started, 0 otherwise.
28479 +        */
28480 +       uint8_t xfer_started;
28481 +
28482 +       /**
28483 +        * Set to 1 to indicate that a PING request should be issued on this
28484 +        * channel. If 0, process normally.
28485 +        */
28486 +       uint8_t do_ping;
28487 +
28488 +       /**
28489 +        * Set to 1 to indicate that the error count for this transaction is
28490 +        * non-zero. Set to 0 if the error count is 0.
28491 +        */
28492 +       uint8_t error_state;
28493 +
28494 +       /**
28495 +        * Set to 1 to indicate that this channel should be halted the next
28496 +        * time a request is queued for the channel. This is necessary in
28497 +        * slave mode if no request queue space is available when an attempt
28498 +        * is made to halt the channel.
28499 +        */
28500 +       uint8_t halt_on_queue;
28501 +
28502 +       /**
28503 +        * Set to 1 if the host channel has been halted, but the core is not
28504 +        * finished flushing queued requests. Otherwise 0.
28505 +        */
28506 +       uint8_t halt_pending;
28507 +
28508 +       /**
28509 +        * Reason for halting the host channel.
28510 +        */
28511 +       dwc_otg_halt_status_e halt_status;
28512 +
28513 +       /*
28514 +        * Split settings for the host channel
28515 +        */
28516 +       uint8_t do_split;                  /**< Enable split for the channel */
28517 +       uint8_t complete_split;    /**< Enable complete split */
28518 +       uint8_t hub_addr;                  /**< Address of high speed hub */
28519 +
28520 +       uint8_t port_addr;                 /**< Port of the low/full speed device */
28521 +       /** Split transaction position
28522 +        * One of the following values:
28523 +        *        - DWC_HCSPLIT_XACTPOS_MID
28524 +        *        - DWC_HCSPLIT_XACTPOS_BEGIN
28525 +        *        - DWC_HCSPLIT_XACTPOS_END
28526 +        *        - DWC_HCSPLIT_XACTPOS_ALL */
28527 +       uint8_t xact_pos;
28528 +
28529 +       /** Set when the host channel does a short read. */
28530 +       uint8_t short_read;
28531 +
28532 +       /**
28533 +        * Number of requests issued for this channel since it was assigned to
28534 +        * the current transfer (not counting PINGs).
28535 +        */
28536 +       uint8_t requests;
28537 +
28538 +       /**
28539 +        * Queue Head for the transfer being processed by this channel.
28540 +        */
28541 +       struct dwc_otg_qh *qh;
28542 +
28543 +       /** @} */
28544 +
28545 +       /** Entry in list of host channels. */
28546 +        DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
28547 +
28548 +       /** @name Descriptor DMA support */
28549 +       /** @{ */
28550 +
28551 +       /** Number of Transfer Descriptors */
28552 +       uint16_t ntd;
28553 +
28554 +       /** Descriptor List DMA address */
28555 +       dwc_dma_t desc_list_addr;
28556 +
28557 +       /** Scheduling micro-frame bitmap. */
28558 +       uint8_t schinfo;
28559 +
28560 +       /** @} */
28561 +} dwc_hc_t;
28562 +
28563 +/**
28564 + * The following parameters may be specified when starting the module. These
28565 + * parameters define how the DWC_otg controller should be configured.
28566 + */
28567 +typedef struct dwc_otg_core_params {
28568 +       int32_t opt;
28569 +
28570 +       /**
28571 +        * Specifies the OTG capabilities. The driver will automatically
28572 +        * detect the value for this parameter if none is specified.
28573 +        * 0 - HNP and SRP capable (default)
28574 +        * 1 - SRP Only capable
28575 +        * 2 - No HNP/SRP capable
28576 +        */
28577 +       int32_t otg_cap;
28578 +
28579 +       /**
28580 +        * Specifies whether to use slave or DMA mode for accessing the data
28581 +        * FIFOs. The driver will automatically detect the value for this
28582 +        * parameter if none is specified.
28583 +        * 0 - Slave
28584 +        * 1 - DMA (default, if available)
28585 +        */
28586 +       int32_t dma_enable;
28587 +
28588 +       /**
28589 +        * When DMA mode is enabled specifies whether to use address DMA or DMA
28590 +        * Descriptor mode for accessing the data FIFOs in device mode. The driver
28591 +        * will automatically detect the value for this if none is specified.
28592 +        * 0 - address DMA
28593 +        * 1 - DMA Descriptor(default, if available)
28594 +        */
28595 +       int32_t dma_desc_enable;
28596 +       /** The DMA Burst size (applicable only for External DMA
28597 +        * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
28598 +        */
28599 +       int32_t dma_burst_size; /* Translate this to GAHBCFG values */
28600 +
28601 +       /**
28602 +        * Specifies the maximum speed of operation in host and device mode.
28603 +        * The actual speed depends on the speed of the attached device and
28604 +        * the value of phy_type. The actual speed depends on the speed of the
28605 +        * attached device.
28606 +        * 0 - High Speed (default)
28607 +        * 1 - Full Speed
28608 +        */
28609 +       int32_t speed;
28610 +       /** Specifies whether low power mode is supported when attached
28611 +        *      to a Full Speed or Low Speed device in host mode.
28612 +        * 0 - Don't support low power mode (default)
28613 +        * 1 - Support low power mode
28614 +        */
28615 +       int32_t host_support_fs_ls_low_power;
28616 +
28617 +       /** Specifies the PHY clock rate in low power mode when connected to a
28618 +        * Low Speed device in host mode. This parameter is applicable only if
28619 +        * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
28620 +        * then defaults to 6 MHZ otherwise 48 MHZ.
28621 +        *
28622 +        * 0 - 48 MHz
28623 +        * 1 - 6 MHz
28624 +        */
28625 +       int32_t host_ls_low_power_phy_clk;
28626 +
28627 +       /**
28628 +        * 0 - Use cC FIFO size parameters
28629 +        * 1 - Allow dynamic FIFO sizing (default)
28630 +        */
28631 +       int32_t enable_dynamic_fifo;
28632 +
28633 +       /** Total number of 4-byte words in the data FIFO memory. This
28634 +        * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
28635 +        * Tx FIFOs.
28636 +        * 32 to 32768 (default 8192)
28637 +        * Note: The total FIFO memory depth in the FPGA configuration is 8192.
28638 +        */
28639 +       int32_t data_fifo_size;
28640 +
28641 +       /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
28642 +        * FIFO sizing is enabled.
28643 +        * 16 to 32768 (default 1064)
28644 +        */
28645 +       int32_t dev_rx_fifo_size;
28646 +
28647 +       /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
28648 +        * when dynamic FIFO sizing is enabled.
28649 +        * 16 to 32768 (default 1024)
28650 +        */
28651 +       int32_t dev_nperio_tx_fifo_size;
28652 +
28653 +       /** Number of 4-byte words in each of the periodic Tx FIFOs in device
28654 +        * mode when dynamic FIFO sizing is enabled.
28655 +        * 4 to 768 (default 256)
28656 +        */
28657 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
28658 +
28659 +       /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
28660 +        * FIFO sizing is enabled.
28661 +        * 16 to 32768 (default 1024)
28662 +        */
28663 +       int32_t host_rx_fifo_size;
28664 +
28665 +       /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
28666 +        * when Dynamic FIFO sizing is enabled in the core.
28667 +        * 16 to 32768 (default 1024)
28668 +        */
28669 +       int32_t host_nperio_tx_fifo_size;
28670 +
28671 +       /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
28672 +        * FIFO sizing is enabled.
28673 +        * 16 to 32768 (default 1024)
28674 +        */
28675 +       int32_t host_perio_tx_fifo_size;
28676 +
28677 +       /** The maximum transfer size supported in bytes.
28678 +        * 2047 to 65,535  (default 65,535)
28679 +        */
28680 +       int32_t max_transfer_size;
28681 +
28682 +       /** The maximum number of packets in a transfer.
28683 +        * 15 to 511  (default 511)
28684 +        */
28685 +       int32_t max_packet_count;
28686 +
28687 +       /** The number of host channel registers to use.
28688 +        * 1 to 16 (default 12)
28689 +        * Note: The FPGA configuration supports a maximum of 12 host channels.
28690 +        */
28691 +       int32_t host_channels;
28692 +
28693 +       /** The number of endpoints in addition to EP0 available for device
28694 +        * mode operations.
28695 +        * 1 to 15 (default 6 IN and OUT)
28696 +        * Note: The FPGA configuration supports a maximum of 6 IN and OUT
28697 +        * endpoints in addition to EP0.
28698 +        */
28699 +       int32_t dev_endpoints;
28700 +
28701 +               /**
28702 +                * Specifies the type of PHY interface to use. By default, the driver
28703 +                * will automatically detect the phy_type.
28704 +                *
28705 +                * 0 - Full Speed PHY
28706 +                * 1 - UTMI+ (default)
28707 +                * 2 - ULPI
28708 +                */
28709 +       int32_t phy_type;
28710 +
28711 +       /**
28712 +        * Specifies the UTMI+ Data Width. This parameter is
28713 +        * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
28714 +        * PHY_TYPE, this parameter indicates the data width between
28715 +        * the MAC and the ULPI Wrapper.) Also, this parameter is
28716 +        * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
28717 +        * to "8 and 16 bits", meaning that the core has been
28718 +        * configured to work at either data path width.
28719 +        *
28720 +        * 8 or 16 bits (default 16)
28721 +        */
28722 +       int32_t phy_utmi_width;
28723 +
28724 +       /**
28725 +        * Specifies whether the ULPI operates at double or single
28726 +        * data rate. This parameter is only applicable if PHY_TYPE is
28727 +        * ULPI.
28728 +        *
28729 +        * 0 - single data rate ULPI interface with 8 bit wide data
28730 +        * bus (default)
28731 +        * 1 - double data rate ULPI interface with 4 bit wide data
28732 +        * bus
28733 +        */
28734 +       int32_t phy_ulpi_ddr;
28735 +
28736 +       /**
28737 +        * Specifies whether to use the internal or external supply to
28738 +        * drive the vbus with a ULPI phy.
28739 +        */
28740 +       int32_t phy_ulpi_ext_vbus;
28741 +
28742 +       /**
28743 +        * Specifies whether to use the I2Cinterface for full speed PHY. This
28744 +        * parameter is only applicable if PHY_TYPE is FS.
28745 +        * 0 - No (default)
28746 +        * 1 - Yes
28747 +        */
28748 +       int32_t i2c_enable;
28749 +
28750 +       int32_t ulpi_fs_ls;
28751 +
28752 +       int32_t ts_dline;
28753 +
28754 +       /**
28755 +        * Specifies whether dedicated transmit FIFOs are
28756 +        * enabled for non periodic IN endpoints in device mode
28757 +        * 0 - No
28758 +        * 1 - Yes
28759 +        */
28760 +       int32_t en_multiple_tx_fifo;
28761 +
28762 +       /** Number of 4-byte words in each of the Tx FIFOs in device
28763 +        * mode when dynamic FIFO sizing is enabled.
28764 +        * 4 to 768 (default 256)
28765 +        */
28766 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
28767 +
28768 +       /** Thresholding enable flag-
28769 +        * bit 0 - enable non-ISO Tx thresholding
28770 +        * bit 1 - enable ISO Tx thresholding
28771 +        * bit 2 - enable Rx thresholding
28772 +        */
28773 +       uint32_t thr_ctl;
28774 +
28775 +       /** Thresholding length for Tx
28776 +        *      FIFOs in 32 bit DWORDs
28777 +        */
28778 +       uint32_t tx_thr_length;
28779 +
28780 +       /** Thresholding length for Rx
28781 +        *      FIFOs in 32 bit DWORDs
28782 +        */
28783 +       uint32_t rx_thr_length;
28784 +
28785 +       /**
28786 +        * Specifies whether LPM (Link Power Management) support is enabled
28787 +        */
28788 +       int32_t lpm_enable;
28789 +
28790 +       /** Per Transfer Interrupt
28791 +        *      mode enable flag
28792 +        * 1 - Enabled
28793 +        * 0 - Disabled
28794 +        */
28795 +       int32_t pti_enable;
28796 +
28797 +       /** Multi Processor Interrupt
28798 +        *      mode enable flag
28799 +        * 1 - Enabled
28800 +        * 0 - Disabled
28801 +        */
28802 +       int32_t mpi_enable;
28803 +
28804 +       /** IS_USB Capability
28805 +        * 1 - Enabled
28806 +        * 0 - Disabled
28807 +        */
28808 +       int32_t ic_usb_cap;
28809 +
28810 +       /** AHB Threshold Ratio
28811 +        * 2'b00 AHB Threshold =        MAC Threshold
28812 +        * 2'b01 AHB Threshold = 1/2    MAC Threshold
28813 +        * 2'b10 AHB Threshold = 1/4    MAC Threshold
28814 +        * 2'b11 AHB Threshold = 1/8    MAC Threshold
28815 +        */
28816 +       int32_t ahb_thr_ratio;
28817 +
28818 +       /** ADP Support
28819 +        * 1 - Enabled
28820 +        * 0 - Disabled
28821 +        */
28822 +       int32_t adp_supp_enable;
28823 +
28824 +       /** HFIR Reload Control
28825 +        * 0 - The HFIR cannot be reloaded dynamically.
28826 +        * 1 - Allow dynamic reloading of the HFIR register during runtime.
28827 +        */
28828 +       int32_t reload_ctl;
28829 +
28830 +       /** DCFG: Enable device Out NAK
28831 +        * 0 - The core does not set NAK after Bulk Out transfer complete.
28832 +        * 1 - The core sets NAK after Bulk OUT transfer complete.
28833 +        */
28834 +       int32_t dev_out_nak;
28835 +
28836 +       /** DCFG: Enable Continue on BNA
28837 +        * After receiving BNA interrupt the core disables the endpoint,when the
28838 +        * endpoint is re-enabled by the application the core starts processing
28839 +        * 0 - from the DOEPDMA descriptor
28840 +        * 1 - from the descriptor which received the BNA.
28841 +        */
28842 +       int32_t cont_on_bna;
28843 +
28844 +       /** GAHBCFG: AHB Single Support
28845 +        * This bit when programmed supports SINGLE transfers for remainder
28846 +        * data in a transfer for DMA mode of operation.
28847 +        * 0 - in this case the remainder data will be sent using INCR burst size.
28848 +        * 1 - in this case the remainder data will be sent using SINGLE burst size.
28849 +        */
28850 +       int32_t ahb_single;
28851 +
28852 +       /** Core Power down mode
28853 +        * 0 - No Power Down is enabled
28854 +        * 1 - Reserved
28855 +        * 2 - Complete Power Down (Hibernation)
28856 +        */
28857 +       int32_t power_down;
28858 +
28859 +       /** OTG revision supported
28860 +        * 0 - OTG 1.3 revision
28861 +        * 1 - OTG 2.0 revision
28862 +        */
28863 +       int32_t otg_ver;
28864 +
28865 +} dwc_otg_core_params_t;
28866 +
28867 +#ifdef DEBUG
28868 +struct dwc_otg_core_if;
28869 +typedef struct hc_xfer_info {
28870 +       struct dwc_otg_core_if *core_if;
28871 +       dwc_hc_t *hc;
28872 +} hc_xfer_info_t;
28873 +#endif
28874 +
28875 +typedef struct ep_xfer_info {
28876 +       struct dwc_otg_core_if *core_if;
28877 +       dwc_ep_t *ep;
28878 +       uint8_t state;
28879 +} ep_xfer_info_t;
28880 +/*
28881 + * Device States
28882 + */
28883 +typedef enum dwc_otg_lx_state {
28884 +       /** On state */
28885 +       DWC_OTG_L0,
28886 +       /** LPM sleep state*/
28887 +       DWC_OTG_L1,
28888 +       /** USB suspend state*/
28889 +       DWC_OTG_L2,
28890 +       /** Off state*/
28891 +       DWC_OTG_L3
28892 +} dwc_otg_lx_state_e;
28893 +
28894 +struct dwc_otg_global_regs_backup {
28895 +       uint32_t gotgctl_local;
28896 +       uint32_t gintmsk_local;
28897 +       uint32_t gahbcfg_local;
28898 +       uint32_t gusbcfg_local;
28899 +       uint32_t grxfsiz_local;
28900 +       uint32_t gnptxfsiz_local;
28901 +#ifdef CONFIG_USB_DWC_OTG_LPM
28902 +       uint32_t glpmcfg_local;
28903 +#endif
28904 +       uint32_t gi2cctl_local;
28905 +       uint32_t hptxfsiz_local;
28906 +       uint32_t pcgcctl_local;
28907 +       uint32_t gdfifocfg_local;
28908 +       uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];
28909 +       uint32_t gpwrdn_local;
28910 +       uint32_t xhib_pcgcctl;
28911 +       uint32_t xhib_gpwrdn;
28912 +};
28913 +
28914 +struct dwc_otg_host_regs_backup {
28915 +       uint32_t hcfg_local;
28916 +       uint32_t haintmsk_local;
28917 +       uint32_t hcintmsk_local[MAX_EPS_CHANNELS];
28918 +       uint32_t hprt0_local;
28919 +       uint32_t hfir_local;
28920 +};
28921 +
28922 +struct dwc_otg_dev_regs_backup {
28923 +       uint32_t dcfg;
28924 +       uint32_t dctl;
28925 +       uint32_t daintmsk;
28926 +       uint32_t diepmsk;
28927 +       uint32_t doepmsk;
28928 +       uint32_t diepctl[MAX_EPS_CHANNELS];
28929 +       uint32_t dieptsiz[MAX_EPS_CHANNELS];
28930 +       uint32_t diepdma[MAX_EPS_CHANNELS];
28931 +};
28932 +/**
28933 + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
28934 + * the DWC_otg controller acting in either host or device mode. It
28935 + * represents the programming view of the controller as a whole.
28936 + */
28937 +struct dwc_otg_core_if {
28938 +       /** Parameters that define how the core should be configured.*/
28939 +       dwc_otg_core_params_t *core_params;
28940 +
28941 +       /** Core Global registers starting at offset 000h. */
28942 +       dwc_otg_core_global_regs_t *core_global_regs;
28943 +
28944 +       /** Device-specific information */
28945 +       dwc_otg_dev_if_t *dev_if;
28946 +       /** Host-specific information */
28947 +       dwc_otg_host_if_t *host_if;
28948 +
28949 +       /** Value from SNPSID register */
28950 +       uint32_t snpsid;
28951 +
28952 +       /*
28953 +        * Set to 1 if the core PHY interface bits in USBCFG have been
28954 +        * initialized.
28955 +        */
28956 +       uint8_t phy_init_done;
28957 +
28958 +       /*
28959 +        * SRP Success flag, set by srp success interrupt in FS I2C mode
28960 +        */
28961 +       uint8_t srp_success;
28962 +       uint8_t srp_timer_started;
28963 +       /** Timer for SRP. If it expires before SRP is successful
28964 +        * clear the SRP. */
28965 +       dwc_timer_t *srp_timer;
28966 +
28967 +#ifdef DWC_DEV_SRPCAP
28968 +       /* This timer is needed to power on the hibernated host core if SRP is not
28969 +        * initiated on connected SRP capable device for limited period of time
28970 +        */
28971 +       uint8_t pwron_timer_started;
28972 +       dwc_timer_t *pwron_timer;
28973 +#endif
28974 +       /* Common configuration information */
28975 +       /** Power and Clock Gating Control Register */
28976 +       volatile uint32_t *pcgcctl;
28977 +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
28978 +
28979 +       /** Push/pop addresses for endpoints or host channels.*/
28980 +       uint32_t *data_fifo[MAX_EPS_CHANNELS];
28981 +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
28982 +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
28983 +
28984 +       /** Total RAM for FIFOs (Bytes) */
28985 +       uint16_t total_fifo_size;
28986 +       /** Size of Rx FIFO (Bytes) */
28987 +       uint16_t rx_fifo_size;
28988 +       /** Size of Non-periodic Tx FIFO (Bytes) */
28989 +       uint16_t nperio_tx_fifo_size;
28990 +
28991 +       /** 1 if DMA is enabled, 0 otherwise. */
28992 +       uint8_t dma_enable;
28993 +
28994 +       /** 1 if DMA descriptor is enabled, 0 otherwise. */
28995 +       uint8_t dma_desc_enable;
28996 +
28997 +       /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
28998 +       uint8_t pti_enh_enable;
28999 +
29000 +       /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
29001 +       uint8_t multiproc_int_enable;
29002 +
29003 +       /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
29004 +       uint8_t en_multiple_tx_fifo;
29005 +
29006 +       /** Set to 1 if multiple packets of a high-bandwidth transfer is in
29007 +        * process of being queued */
29008 +       uint8_t queuing_high_bandwidth;
29009 +
29010 +       /** Hardware Configuration -- stored here for convenience.*/
29011 +       hwcfg1_data_t hwcfg1;
29012 +       hwcfg2_data_t hwcfg2;
29013 +       hwcfg3_data_t hwcfg3;
29014 +       hwcfg4_data_t hwcfg4;
29015 +       fifosize_data_t hptxfsiz;
29016 +
29017 +       /** Host and Device Configuration -- stored here for convenience.*/
29018 +       hcfg_data_t hcfg;
29019 +       dcfg_data_t dcfg;
29020 +
29021 +       /** The operational State, during transations
29022 +        * (a_host>>a_peripherial and b_device=>b_host) this may not
29023 +        * match the core but allows the software to determine
29024 +        * transitions.
29025 +        */
29026 +       uint8_t op_state;
29027 +
29028 +       /**
29029 +        * Set to 1 if the HCD needs to be restarted on a session request
29030 +        * interrupt. This is required if no connector ID status change has
29031 +        * occurred since the HCD was last disconnected.
29032 +        */
29033 +       uint8_t restart_hcd_on_session_req;
29034 +
29035 +       /** HCD callbacks */
29036 +       /** A-Device is a_host */
29037 +#define A_HOST         (1)
29038 +       /** A-Device is a_suspend */
29039 +#define A_SUSPEND      (2)
29040 +       /** A-Device is a_peripherial */
29041 +#define A_PERIPHERAL   (3)
29042 +       /** B-Device is operating as a Peripheral. */
29043 +#define B_PERIPHERAL   (4)
29044 +       /** B-Device is operating as a Host. */
29045 +#define B_HOST         (5)
29046 +
29047 +       /** HCD callbacks */
29048 +       struct dwc_otg_cil_callbacks *hcd_cb;
29049 +       /** PCD callbacks */
29050 +       struct dwc_otg_cil_callbacks *pcd_cb;
29051 +
29052 +       /** Device mode Periodic Tx FIFO Mask */
29053 +       uint32_t p_tx_msk;
29054 +       /** Device mode Periodic Tx FIFO Mask */
29055 +       uint32_t tx_msk;
29056 +
29057 +       /** Workqueue object used for handling several interrupts */
29058 +       dwc_workq_t *wq_otg;
29059 +
29060 +       /** Timer object used for handling "Wakeup Detected" Interrupt */
29061 +       dwc_timer_t *wkp_timer;
29062 +       /** This arrays used for debug purposes for DEV OUT NAK enhancement */
29063 +       uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];
29064 +       ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];
29065 +       dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];
29066 +#ifdef DEBUG
29067 +       uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
29068 +
29069 +       hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
29070 +       dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
29071 +
29072 +       uint32_t hfnum_7_samples;
29073 +       uint64_t hfnum_7_frrem_accum;
29074 +       uint32_t hfnum_0_samples;
29075 +       uint64_t hfnum_0_frrem_accum;
29076 +       uint32_t hfnum_other_samples;
29077 +       uint64_t hfnum_other_frrem_accum;
29078 +#endif
29079 +
29080 +#ifdef DWC_UTE_CFI
29081 +       uint16_t pwron_rxfsiz;
29082 +       uint16_t pwron_gnptxfsiz;
29083 +       uint16_t pwron_txfsiz[15];
29084 +
29085 +       uint16_t init_rxfsiz;
29086 +       uint16_t init_gnptxfsiz;
29087 +       uint16_t init_txfsiz[15];
29088 +#endif
29089 +
29090 +       /** Lx state of device */
29091 +       dwc_otg_lx_state_e lx_state;
29092 +
29093 +       /** Saved Core Global registers */
29094 +       struct dwc_otg_global_regs_backup *gr_backup;
29095 +       /** Saved Host registers */
29096 +       struct dwc_otg_host_regs_backup *hr_backup;
29097 +       /** Saved Device registers */
29098 +       struct dwc_otg_dev_regs_backup *dr_backup;
29099 +
29100 +       /** Power Down Enable */
29101 +       uint32_t power_down;
29102 +
29103 +       /** ADP support Enable */
29104 +       uint32_t adp_enable;
29105 +
29106 +       /** ADP structure object */
29107 +       dwc_otg_adp_t adp;
29108 +
29109 +       /** hibernation/suspend flag */
29110 +       int hibernation_suspend;
29111 +
29112 +       /** Device mode extended hibernation flag */
29113 +       int xhib;
29114 +
29115 +       /** OTG revision supported */
29116 +       uint32_t otg_ver;
29117 +
29118 +       /** OTG status flag used for HNP polling */
29119 +       uint8_t otg_sts;
29120 +
29121 +       /** Pointer to either hcd->lock or pcd->lock */
29122 +       dwc_spinlock_t *lock;
29123 +
29124 +       /** Start predict NextEP based on Learning Queue if equal 1,
29125 +        * also used as counter of disabled NP IN EP's */
29126 +       uint8_t start_predict;
29127 +
29128 +       /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and
29129 +        * active, 0xff otherwise */
29130 +       uint8_t nextep_seq[MAX_EPS_CHANNELS];
29131 +
29132 +       /** Index of fisrt EP in nextep_seq array which should be re-enabled **/
29133 +       uint8_t first_in_nextep_seq;
29134 +
29135 +       /** Frame number while entering to ISR - needed for ISOCs **/
29136 +       uint32_t frame_num;
29137 +
29138 +};
29139 +
29140 +#ifdef DEBUG
29141 +/*
29142 + * This function is called when transfer is timed out.
29143 + */
29144 +extern void hc_xfer_timeout(void *ptr);
29145 +#endif
29146 +
29147 +/*
29148 + * This function is called when transfer is timed out on endpoint.
29149 + */
29150 +extern void ep_xfer_timeout(void *ptr);
29151 +
29152 +/*
29153 + * The following functions are functions for works
29154 + * using during handling some interrupts
29155 + */
29156 +extern void w_conn_id_status_change(void *p);
29157 +
29158 +extern void w_wakeup_detected(void *p);
29159 +
29160 +/** Saves global register values into system memory. */
29161 +extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);
29162 +/** Saves device register values into system memory. */
29163 +extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);
29164 +/** Saves host register values into system memory. */
29165 +extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);
29166 +/** Restore global register values. */
29167 +extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);
29168 +/** Restore host register values. */
29169 +extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);
29170 +/** Restore device register values. */
29171 +extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,
29172 +                                   int rem_wakeup);
29173 +extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);
29174 +extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,
29175 +                                 int is_host);
29176 +
29177 +extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
29178 +                                           int restore_mode, int reset);
29179 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
29180 +                                             int rem_wakeup, int reset);
29181 +
29182 +/*
29183 + * The following functions support initialization of the CIL driver component
29184 + * and the DWC_otg controller.
29185 + */
29186 +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
29187 +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
29188 +
29189 +/** @name Device CIL Functions
29190 + * The following functions support managing the DWC_otg controller in device
29191 + * mode.
29192 + */
29193 +/**@{*/
29194 +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
29195 +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
29196 +                                     uint32_t * _dest);
29197 +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
29198 +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29199 +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29200 +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29201 +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
29202 +                                     dwc_ep_t * _ep);
29203 +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
29204 +                                        dwc_ep_t * _ep);
29205 +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
29206 +                                      dwc_ep_t * _ep);
29207 +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
29208 +                                         dwc_ep_t * _ep);
29209 +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
29210 +                                   dwc_ep_t * _ep, int _dma);
29211 +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29212 +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
29213 +                                  dwc_ep_t * _ep);
29214 +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
29215 +
29216 +#ifdef DWC_EN_ISOC
29217 +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
29218 +                                             dwc_ep_t * ep);
29219 +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
29220 +                                             dwc_ep_t * ep);
29221 +#endif /* DWC_EN_ISOC */
29222 +/**@}*/
29223 +
29224 +/** @name Host CIL Functions
29225 + * The following functions support managing the DWC_otg controller in host
29226 + * mode.
29227 + */
29228 +/**@{*/
29229 +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29230 +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
29231 +                           dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
29232 +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29233 +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
29234 +                                     dwc_hc_t * _hc);
29235 +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
29236 +                                       dwc_hc_t * _hc);
29237 +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29238 +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
29239 +                                   dwc_hc_t * _hc);
29240 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
29241 +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
29242 +
29243 +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,
29244 +                                          dwc_hc_t * hc);
29245 +
29246 +extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);
29247 +
29248 +/* Macro used to clear one channel interrupt */
29249 +#define clear_hc_int(_hc_regs_, _intr_) \
29250 +do { \
29251 +       hcint_data_t hcint_clear = {.d32 = 0}; \
29252 +       hcint_clear.b._intr_ = 1; \
29253 +       DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \
29254 +} while (0)
29255 +
29256 +/*
29257 + * Macro used to disable one channel interrupt. Channel interrupts are
29258 + * disabled when the channel is halted or released by the interrupt handler.
29259 + * There is no need to handle further interrupts of that type until the
29260 + * channel is re-assigned. In fact, subsequent handling may cause crashes
29261 + * because the channel structures are cleaned up when the channel is released.
29262 + */
29263 +#define disable_hc_int(_hc_regs_, _intr_) \
29264 +do { \
29265 +       hcintmsk_data_t hcintmsk = {.d32 = 0}; \
29266 +       hcintmsk.b._intr_ = 1; \
29267 +       DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
29268 +} while (0)
29269 +
29270 +/**
29271 + * This function Reads HPRT0 in preparation to modify. It keeps the
29272 + * WC bits 0 so that if they are read as 1, they won't clear when you
29273 + * write it back
29274 + */
29275 +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
29276 +{
29277 +       hprt0_data_t hprt0;
29278 +       hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);
29279 +       hprt0.b.prtena = 0;
29280 +       hprt0.b.prtconndet = 0;
29281 +       hprt0.b.prtenchng = 0;
29282 +       hprt0.b.prtovrcurrchng = 0;
29283 +       return hprt0.d32;
29284 +}
29285 +
29286 +/**@}*/
29287 +
29288 +/** @name Common CIL Functions
29289 + * The following functions support managing the DWC_otg controller in either
29290 + * device or host mode.
29291 + */
29292 +/**@{*/
29293 +
29294 +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
29295 +                               uint8_t * dest, uint16_t bytes);
29296 +
29297 +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
29298 +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
29299 +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
29300 +
29301 +/**
29302 + * This function returns the Core Interrupt register.
29303 + */
29304 +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
29305 +{
29306 +       return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
29307 +               DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
29308 +}
29309 +
29310 +/**
29311 + * This function returns the OTG Interrupt register.
29312 + */
29313 +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
29314 +{
29315 +       return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));
29316 +}
29317 +
29318 +/**
29319 + * This function reads the Device All Endpoints Interrupt register and
29320 + * returns the IN endpoint interrupt bits.
29321 + */
29322 +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
29323 +                                                      core_if)
29324 +{
29325 +
29326 +       uint32_t v;
29327 +
29328 +       if (core_if->multiproc_int_enable) {
29329 +               v = DWC_READ_REG32(&core_if->dev_if->
29330 +                                  dev_global_regs->deachint) &
29331 +                   DWC_READ_REG32(&core_if->
29332 +                                  dev_if->dev_global_regs->deachintmsk);
29333 +       } else {
29334 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29335 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29336 +       }
29337 +       return (v & 0xffff);
29338 +}
29339 +
29340 +/**
29341 + * This function reads the Device All Endpoints Interrupt register and
29342 + * returns the OUT endpoint interrupt bits.
29343 + */
29344 +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
29345 +                                                       core_if)
29346 +{
29347 +       uint32_t v;
29348 +
29349 +       if (core_if->multiproc_int_enable) {
29350 +               v = DWC_READ_REG32(&core_if->dev_if->
29351 +                                  dev_global_regs->deachint) &
29352 +                   DWC_READ_REG32(&core_if->
29353 +                                  dev_if->dev_global_regs->deachintmsk);
29354 +       } else {
29355 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29356 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29357 +       }
29358 +
29359 +       return ((v & 0xffff0000) >> 16);
29360 +}
29361 +
29362 +/**
29363 + * This function returns the Device IN EP Interrupt register
29364 + */
29365 +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
29366 +                                                  dwc_ep_t * ep)
29367 +{
29368 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
29369 +       uint32_t v, msk, emp;
29370 +
29371 +       if (core_if->multiproc_int_enable) {
29372 +               msk =
29373 +                   DWC_READ_REG32(&dev_if->
29374 +                                  dev_global_regs->diepeachintmsk[ep->num]);
29375 +               emp =
29376 +                   DWC_READ_REG32(&dev_if->
29377 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29378 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29379 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29380 +       } else {
29381 +               msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
29382 +               emp =
29383 +                   DWC_READ_REG32(&dev_if->
29384 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29385 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29386 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29387 +       }
29388 +
29389 +       return v;
29390 +}
29391 +
29392 +/**
29393 + * This function returns the Device OUT EP Interrupt register
29394 + */
29395 +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
29396 +                                                   _core_if, dwc_ep_t * _ep)
29397 +{
29398 +       dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
29399 +       uint32_t v;
29400 +       doepmsk_data_t msk = {.d32 = 0 };
29401 +
29402 +       if (_core_if->multiproc_int_enable) {
29403 +               msk.d32 =
29404 +                   DWC_READ_REG32(&dev_if->
29405 +                                  dev_global_regs->doepeachintmsk[_ep->num]);
29406 +               if (_core_if->pti_enh_enable) {
29407 +                       msk.b.pktdrpsts = 1;
29408 +               }
29409 +               v = DWC_READ_REG32(&dev_if->
29410 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29411 +       } else {
29412 +               msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
29413 +               if (_core_if->pti_enh_enable) {
29414 +                       msk.b.pktdrpsts = 1;
29415 +               }
29416 +               v = DWC_READ_REG32(&dev_if->
29417 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29418 +       }
29419 +       return v;
29420 +}
29421 +
29422 +/**
29423 + * This function returns the Host All Channel Interrupt register
29424 + */
29425 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
29426 +                                                          _core_if)
29427 +{
29428 +       return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));
29429 +}
29430 +
29431 +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
29432 +                                                     _core_if, dwc_hc_t * _hc)
29433 +{
29434 +       return (DWC_READ_REG32
29435 +               (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
29436 +}
29437 +
29438 +/**
29439 + * This function returns the mode of the operation, host or device.
29440 + *
29441 + * @return 0 - Device Mode, 1 - Host Mode
29442 + */
29443 +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
29444 +{
29445 +       return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
29446 +}
29447 +
29448 +/**@}*/
29449 +
29450 +/**
29451 + * DWC_otg CIL callback structure. This structure allows the HCD and
29452 + * PCD to register functions used for starting and stopping the PCD
29453 + * and HCD for role change on for a DRD.
29454 + */
29455 +typedef struct dwc_otg_cil_callbacks {
29456 +       /** Start function for role change */
29457 +       int (*start) (void *_p);
29458 +       /** Stop Function for role change */
29459 +       int (*stop) (void *_p);
29460 +       /** Disconnect Function for role change */
29461 +       int (*disconnect) (void *_p);
29462 +       /** Resume/Remote wakeup Function */
29463 +       int (*resume_wakeup) (void *_p);
29464 +       /** Suspend function */
29465 +       int (*suspend) (void *_p);
29466 +       /** Session Start (SRP) */
29467 +       int (*session_start) (void *_p);
29468 +#ifdef CONFIG_USB_DWC_OTG_LPM
29469 +       /** Sleep (switch to L0 state) */
29470 +       int (*sleep) (void *_p);
29471 +#endif
29472 +       /** Pointer passed to start() and stop() */
29473 +       void *p;
29474 +} dwc_otg_cil_callbacks_t;
29475 +
29476 +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
29477 +                                              dwc_otg_cil_callbacks_t * _cb,
29478 +                                              void *_p);
29479 +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
29480 +                                              dwc_otg_cil_callbacks_t * _cb,
29481 +                                              void *_p);
29482 +
29483 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);
29484 +
29485 +//////////////////////////////////////////////////////////////////////
29486 +/** Start the HCD.  Helper function for using the HCD callbacks.
29487 + *
29488 + * @param core_if Programming view of DWC_otg controller.
29489 + */
29490 +static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)
29491 +{
29492 +       if (core_if->hcd_cb && core_if->hcd_cb->start) {
29493 +               core_if->hcd_cb->start(core_if->hcd_cb->p);
29494 +       }
29495 +}
29496 +
29497 +/** Stop the HCD.  Helper function for using the HCD callbacks.
29498 + *
29499 + * @param core_if Programming view of DWC_otg controller.
29500 + */
29501 +static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)
29502 +{
29503 +       if (core_if->hcd_cb && core_if->hcd_cb->stop) {
29504 +               core_if->hcd_cb->stop(core_if->hcd_cb->p);
29505 +       }
29506 +}
29507 +
29508 +/** Disconnect the HCD.  Helper function for using the HCD callbacks.
29509 + *
29510 + * @param core_if Programming view of DWC_otg controller.
29511 + */
29512 +static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)
29513 +{
29514 +       if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
29515 +               core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
29516 +       }
29517 +}
29518 +
29519 +/** Inform the HCD the a New Session has begun.  Helper function for
29520 + * using the HCD callbacks.
29521 + *
29522 + * @param core_if Programming view of DWC_otg controller.
29523 + */
29524 +static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)
29525 +{
29526 +       if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
29527 +               core_if->hcd_cb->session_start(core_if->hcd_cb->p);
29528 +       }
29529 +}
29530 +
29531 +#ifdef CONFIG_USB_DWC_OTG_LPM
29532 +/**
29533 + * Inform the HCD about LPM sleep.
29534 + * Helper function for using the HCD callbacks.
29535 + *
29536 + * @param core_if Programming view of DWC_otg controller.
29537 + */
29538 +static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)
29539 +{
29540 +       if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
29541 +               core_if->hcd_cb->sleep(core_if->hcd_cb->p);
29542 +       }
29543 +}
29544 +#endif
29545 +
29546 +/** Resume the HCD.  Helper function for using the HCD callbacks.
29547 + *
29548 + * @param core_if Programming view of DWC_otg controller.
29549 + */
29550 +static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)
29551 +{
29552 +       if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
29553 +               core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
29554 +       }
29555 +}
29556 +
29557 +/** Start the PCD.  Helper function for using the PCD callbacks.
29558 + *
29559 + * @param core_if Programming view of DWC_otg controller.
29560 + */
29561 +static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)
29562 +{
29563 +       if (core_if->pcd_cb && core_if->pcd_cb->start) {
29564 +               core_if->pcd_cb->start(core_if->pcd_cb->p);
29565 +       }
29566 +}
29567 +
29568 +/** Stop the PCD.  Helper function for using the PCD callbacks.
29569 + *
29570 + * @param core_if Programming view of DWC_otg controller.
29571 + */
29572 +static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)
29573 +{
29574 +       if (core_if->pcd_cb && core_if->pcd_cb->stop) {
29575 +               core_if->pcd_cb->stop(core_if->pcd_cb->p);
29576 +       }
29577 +}
29578 +
29579 +/** Suspend the PCD.  Helper function for using the PCD callbacks.
29580 + *
29581 + * @param core_if Programming view of DWC_otg controller.
29582 + */
29583 +static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)
29584 +{
29585 +       if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
29586 +               core_if->pcd_cb->suspend(core_if->pcd_cb->p);
29587 +       }
29588 +}
29589 +
29590 +/** Resume the PCD.  Helper function for using the PCD callbacks.
29591 + *
29592 + * @param core_if Programming view of DWC_otg controller.
29593 + */
29594 +static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)
29595 +{
29596 +       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
29597 +               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
29598 +       }
29599 +}
29600 +
29601 +//////////////////////////////////////////////////////////////////////
29602 +
29603 +#endif
29604 --- /dev/null
29605 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29606 @@ -0,0 +1,1563 @@
29607 +/* ==========================================================================
29608 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
29609 + * $Revision: #32 $
29610 + * $Date: 2012/08/10 $
29611 + * $Change: 2047372 $
29612 + *
29613 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
29614 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
29615 + * otherwise expressly agreed to in writing between Synopsys and you.
29616 + *
29617 + * The Software IS NOT an item of Licensed Software or Licensed Product under
29618 + * any End User Software License Agreement or Agreement for Licensed Product
29619 + * with Synopsys or any supplement thereto. You are permitted to use and
29620 + * redistribute this Software in source and binary forms, with or without
29621 + * modification, provided that redistributions of source code must retain this
29622 + * notice. You may not view, use, disclose, copy or distribute this file or
29623 + * any information contained herein except pursuant to this license grant from
29624 + * Synopsys. If you do not agree with this notice, including the disclaimer
29625 + * below, then you are not authorized to use the Software.
29626 + *
29627 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
29628 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29629 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29630 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
29631 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29632 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29633 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29634 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29635 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29636 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29637 + * DAMAGE.
29638 + * ========================================================================== */
29639 +
29640 +/** @file
29641 + *
29642 + * The Core Interface Layer provides basic services for accessing and
29643 + * managing the DWC_otg hardware. These services are used by both the
29644 + * Host Controller Driver and the Peripheral Controller Driver.
29645 + *
29646 + * This file contains the Common Interrupt handlers.
29647 + */
29648 +#include "dwc_os.h"
29649 +#include "dwc_otg_regs.h"
29650 +#include "dwc_otg_cil.h"
29651 +#include "dwc_otg_driver.h"
29652 +#include "dwc_otg_pcd.h"
29653 +#include "dwc_otg_hcd.h"
29654 +
29655 +#ifdef DEBUG
29656 +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
29657 +{
29658 +       return (core_if->op_state == A_HOST ? "a_host" :
29659 +               (core_if->op_state == A_SUSPEND ? "a_suspend" :
29660 +                (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
29661 +                 (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
29662 +                  (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
29663 +}
29664 +#endif
29665 +
29666 +/** This function will log a debug message
29667 + *
29668 + * @param core_if Programming view of DWC_otg controller.
29669 + */
29670 +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
29671 +{
29672 +       gintsts_data_t gintsts;
29673 +       DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
29674 +                dwc_otg_mode(core_if) ? "Host" : "Device");
29675 +
29676 +       /* Clear interrupt */
29677 +       gintsts.d32 = 0;
29678 +       gintsts.b.modemismatch = 1;
29679 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29680 +       return 1;
29681 +}
29682 +
29683 +/**
29684 + * This function handles the OTG Interrupts. It reads the OTG
29685 + * Interrupt Register (GOTGINT) to determine what interrupt has
29686 + * occurred.
29687 + *
29688 + * @param core_if Programming view of DWC_otg controller.
29689 + */
29690 +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
29691 +{
29692 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
29693 +       gotgint_data_t gotgint;
29694 +       gotgctl_data_t gotgctl;
29695 +       gintmsk_data_t gintmsk;
29696 +       gpwrdn_data_t gpwrdn;
29697 +
29698 +       gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
29699 +       gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29700 +       DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
29701 +                   op_state_str(core_if));
29702 +
29703 +       if (gotgint.b.sesenddet) {
29704 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29705 +                           "Session End Detected++ (%s)\n",
29706 +                           op_state_str(core_if));
29707 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29708 +
29709 +               if (core_if->op_state == B_HOST) {
29710 +                       cil_pcd_start(core_if);
29711 +                       core_if->op_state = B_PERIPHERAL;
29712 +               } else {
29713 +                       /* If not B_HOST and Device HNP still set. HNP
29714 +                        * Did not succeed!*/
29715 +                       if (gotgctl.b.devhnpen) {
29716 +                               DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
29717 +                               __DWC_ERROR("Device Not Connected/Responding!\n");
29718 +                       }
29719 +
29720 +                       /* If Session End Detected the B-Cable has
29721 +                        * been disconnected. */
29722 +                       /* Reset PCD and Gadget driver to a
29723 +                        * clean state. */
29724 +                       core_if->lx_state = DWC_OTG_L0;
29725 +                       DWC_SPINUNLOCK(core_if->lock);
29726 +                       cil_pcd_stop(core_if);
29727 +                       DWC_SPINLOCK(core_if->lock);
29728 +
29729 +                       if (core_if->adp_enable) {
29730 +                               if (core_if->power_down == 2) {
29731 +                                       gpwrdn.d32 = 0;
29732 +                                       gpwrdn.b.pwrdnswtch = 1;
29733 +                                       DWC_MODIFY_REG32(&core_if->
29734 +                                                        core_global_regs->
29735 +                                                        gpwrdn, gpwrdn.d32, 0);
29736 +                               }
29737 +
29738 +                               gpwrdn.d32 = 0;
29739 +                               gpwrdn.b.pmuintsel = 1;
29740 +                               gpwrdn.b.pmuactv = 1;
29741 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
29742 +                                                gpwrdn, 0, gpwrdn.d32);
29743 +
29744 +                               dwc_otg_adp_sense_start(core_if);
29745 +                       }
29746 +               }
29747 +
29748 +               gotgctl.d32 = 0;
29749 +               gotgctl.b.devhnpen = 1;
29750 +               DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29751 +       }
29752 +       if (gotgint.b.sesreqsucstschng) {
29753 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29754 +                           "Session Reqeust Success Status Change++\n");
29755 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29756 +               if (gotgctl.b.sesreqscs) {
29757 +
29758 +                       if ((core_if->core_params->phy_type ==
29759 +                            DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
29760 +                               core_if->srp_success = 1;
29761 +                       } else {
29762 +                               DWC_SPINUNLOCK(core_if->lock);
29763 +                               cil_pcd_resume(core_if);
29764 +                               DWC_SPINLOCK(core_if->lock);
29765 +                               /* Clear Session Request */
29766 +                               gotgctl.d32 = 0;
29767 +                               gotgctl.b.sesreq = 1;
29768 +                               DWC_MODIFY_REG32(&global_regs->gotgctl,
29769 +                                                gotgctl.d32, 0);
29770 +                       }
29771 +               }
29772 +       }
29773 +       if (gotgint.b.hstnegsucstschng) {
29774 +               /* Print statements during the HNP interrupt handling
29775 +                * can cause it to fail.*/
29776 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29777 +               /* WA for 3.00a- HW is not setting cur_mode, even sometimes
29778 +                * this does not help*/
29779 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
29780 +                       dwc_udelay(100);
29781 +               if (gotgctl.b.hstnegscs) {
29782 +                       if (dwc_otg_is_host_mode(core_if)) {
29783 +                               core_if->op_state = B_HOST;
29784 +                               /*
29785 +                                * Need to disable SOF interrupt immediately.
29786 +                                * When switching from device to host, the PCD
29787 +                                * interrupt handler won't handle the
29788 +                                * interrupt if host mode is already set. The
29789 +                                * HCD interrupt handler won't get called if
29790 +                                * the HCD state is HALT. This means that the
29791 +                                * interrupt does not get handled and Linux
29792 +                                * complains loudly.
29793 +                                */
29794 +                               gintmsk.d32 = 0;
29795 +                               gintmsk.b.sofintr = 1;
29796 +                               DWC_MODIFY_REG32(&global_regs->gintmsk,
29797 +                                                gintmsk.d32, 0);
29798 +                               /* Call callback function with spin lock released */
29799 +                               DWC_SPINUNLOCK(core_if->lock);
29800 +                               cil_pcd_stop(core_if);
29801 +                               /*
29802 +                                * Initialize the Core for Host mode.
29803 +                                */
29804 +                               cil_hcd_start(core_if);
29805 +                               DWC_SPINLOCK(core_if->lock);
29806 +                               core_if->op_state = B_HOST;
29807 +                       }
29808 +               } else {
29809 +                       gotgctl.d32 = 0;
29810 +                       gotgctl.b.hnpreq = 1;
29811 +                       gotgctl.b.devhnpen = 1;
29812 +                       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29813 +                       DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
29814 +                       __DWC_ERROR("Device Not Connected/Responding\n");
29815 +               }
29816 +       }
29817 +       if (gotgint.b.hstnegdet) {
29818 +               /* The disconnect interrupt is set at the same time as
29819 +                * Host Negotiation Detected.  During the mode
29820 +                * switch all interrupts are cleared so the disconnect
29821 +                * interrupt handler will not get executed.
29822 +                */
29823 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29824 +                           "Host Negotiation Detected++ (%s)\n",
29825 +                           (dwc_otg_is_host_mode(core_if) ? "Host" :
29826 +                            "Device"));
29827 +               if (dwc_otg_is_device_mode(core_if)) {
29828 +                       DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
29829 +                                   core_if->op_state);
29830 +                       DWC_SPINUNLOCK(core_if->lock);
29831 +                       cil_hcd_disconnect(core_if);
29832 +                       cil_pcd_start(core_if);
29833 +                       DWC_SPINLOCK(core_if->lock);
29834 +                       core_if->op_state = A_PERIPHERAL;
29835 +               } else {
29836 +                       /*
29837 +                        * Need to disable SOF interrupt immediately. When
29838 +                        * switching from device to host, the PCD interrupt
29839 +                        * handler won't handle the interrupt if host mode is
29840 +                        * already set. The HCD interrupt handler won't get
29841 +                        * called if the HCD state is HALT. This means that
29842 +                        * the interrupt does not get handled and Linux
29843 +                        * complains loudly.
29844 +                        */
29845 +                       gintmsk.d32 = 0;
29846 +                       gintmsk.b.sofintr = 1;
29847 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
29848 +                       DWC_SPINUNLOCK(core_if->lock);
29849 +                       cil_pcd_stop(core_if);
29850 +                       cil_hcd_start(core_if);
29851 +                       DWC_SPINLOCK(core_if->lock);
29852 +                       core_if->op_state = A_HOST;
29853 +               }
29854 +       }
29855 +       if (gotgint.b.adevtoutchng) {
29856 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29857 +                           "A-Device Timeout Change++\n");
29858 +       }
29859 +       if (gotgint.b.debdone) {
29860 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
29861 +       }
29862 +
29863 +       /* Clear GOTGINT */
29864 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
29865 +
29866 +       return 1;
29867 +}
29868 +
29869 +void w_conn_id_status_change(void *p)
29870 +{
29871 +       dwc_otg_core_if_t *core_if = p;
29872 +       uint32_t count = 0;
29873 +       gotgctl_data_t gotgctl = {.d32 = 0 };
29874 +
29875 +       gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
29876 +       DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
29877 +       DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
29878 +
29879 +       /* B-Device connector (Device Mode) */
29880 +       if (gotgctl.b.conidsts) {
29881 +               /* Wait for switch to device mode. */
29882 +               while (!dwc_otg_is_device_mode(core_if)) {
29883 +                       DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
29884 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
29885 +                                   "Peripheral"));
29886 +                       dwc_mdelay(100);
29887 +                       if (++count > 10000)
29888 +                               break;
29889 +               }
29890 +               DWC_ASSERT(++count < 10000,
29891 +                          "Connection id status change timed out");
29892 +               core_if->op_state = B_PERIPHERAL;
29893 +               dwc_otg_core_init(core_if);
29894 +               dwc_otg_enable_global_interrupts(core_if);
29895 +               cil_pcd_start(core_if);
29896 +       } else {
29897 +               /* A-Device connector (Host Mode) */
29898 +               while (!dwc_otg_is_host_mode(core_if)) {
29899 +                       DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
29900 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
29901 +                                   "Peripheral"));
29902 +                       dwc_mdelay(100);
29903 +                       if (++count > 10000)
29904 +                               break;
29905 +               }
29906 +               DWC_ASSERT(++count < 10000,
29907 +                          "Connection id status change timed out");
29908 +               core_if->op_state = A_HOST;
29909 +               /*
29910 +                * Initialize the Core for Host mode.
29911 +                */
29912 +               dwc_otg_core_init(core_if);
29913 +               dwc_otg_enable_global_interrupts(core_if);
29914 +               cil_hcd_start(core_if);
29915 +       }
29916 +}
29917 +
29918 +/**
29919 + * This function handles the Connector ID Status Change Interrupt.  It
29920 + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
29921 + * is a Device to Host Mode transition or a Host Mode to Device
29922 + * Transition.
29923 + *
29924 + * This only occurs when the cable is connected/removed from the PHY
29925 + * connector.
29926 + *
29927 + * @param core_if Programming view of DWC_otg controller.
29928 + */
29929 +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
29930 +{
29931 +
29932 +       /*
29933 +        * Need to disable SOF interrupt immediately. If switching from device
29934 +        * to host, the PCD interrupt handler won't handle the interrupt if
29935 +        * host mode is already set. The HCD interrupt handler won't get
29936 +        * called if the HCD state is HALT. This means that the interrupt does
29937 +        * not get handled and Linux complains loudly.
29938 +        */
29939 +       gintmsk_data_t gintmsk = {.d32 = 0 };
29940 +       gintsts_data_t gintsts = {.d32 = 0 };
29941 +
29942 +       gintmsk.b.sofintr = 1;
29943 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
29944 +
29945 +       DWC_DEBUGPL(DBG_CIL,
29946 +                   " ++Connector ID Status Change Interrupt++  (%s)\n",
29947 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
29948 +
29949 +       DWC_SPINUNLOCK(core_if->lock);
29950 +
29951 +       /*
29952 +        * Need to schedule a work, as there are possible DELAY function calls
29953 +        * Release lock before scheduling workq as it holds spinlock during scheduling
29954 +        */
29955 +
29956 +       DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
29957 +                          core_if, "connection id status change");
29958 +       DWC_SPINLOCK(core_if->lock);
29959 +
29960 +       /* Set flag and clear interrupt */
29961 +       gintsts.b.conidstschng = 1;
29962 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29963 +
29964 +       return 1;
29965 +}
29966 +
29967 +/**
29968 + * This interrupt indicates that a device is initiating the Session
29969 + * Request Protocol to request the host to turn on bus power so a new
29970 + * session can begin. The handler responds by turning on bus power. If
29971 + * the DWC_otg controller is in low power mode, the handler brings the
29972 + * controller out of low power mode before turning on bus power.
29973 + *
29974 + * @param core_if Programming view of DWC_otg controller.
29975 + */
29976 +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
29977 +{
29978 +       gintsts_data_t gintsts;
29979 +
29980 +#ifndef DWC_HOST_ONLY
29981 +       DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
29982 +
29983 +       if (dwc_otg_is_device_mode(core_if)) {
29984 +               DWC_PRINTF("SRP: Device mode\n");
29985 +       } else {
29986 +               hprt0_data_t hprt0;
29987 +               DWC_PRINTF("SRP: Host mode\n");
29988 +
29989 +               /* Turn on the port power bit. */
29990 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
29991 +               hprt0.b.prtpwr = 1;
29992 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
29993 +
29994 +               /* Start the Connection timer. So a message can be displayed
29995 +                * if connect does not occur within 10 seconds. */
29996 +               cil_hcd_session_start(core_if);
29997 +       }
29998 +#endif
29999 +
30000 +       /* Clear interrupt */
30001 +       gintsts.d32 = 0;
30002 +       gintsts.b.sessreqintr = 1;
30003 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30004 +
30005 +       return 1;
30006 +}
30007 +
30008 +void w_wakeup_detected(void *p)
30009 +{
30010 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
30011 +       /*
30012 +        * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
30013 +        * so that OPT tests pass with all PHYs).
30014 +        */
30015 +       hprt0_data_t hprt0 = {.d32 = 0 };
30016 +#if 0
30017 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30018 +       /* Restart the Phy Clock */
30019 +       pcgcctl.b.stoppclk = 1;
30020 +       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30021 +       dwc_udelay(10);
30022 +#endif //0
30023 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
30024 +       DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
30025 +//      dwc_mdelay(70);
30026 +       hprt0.b.prtres = 0;     /* Resume */
30027 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30028 +       DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
30029 +                   DWC_READ_REG32(core_if->host_if->hprt0));
30030 +
30031 +       cil_hcd_resume(core_if);
30032 +
30033 +       /** Change to L0 state*/
30034 +       core_if->lx_state = DWC_OTG_L0;
30035 +}
30036 +
30037 +/**
30038 + * This interrupt indicates that the DWC_otg controller has detected a
30039 + * resume or remote wakeup sequence. If the DWC_otg controller is in
30040 + * low power mode, the handler must brings the controller out of low
30041 + * power mode. The controller automatically begins resume
30042 + * signaling. The handler schedules a time to stop resume signaling.
30043 + */
30044 +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30045 +{
30046 +       gintsts_data_t gintsts;
30047 +
30048 +       DWC_DEBUGPL(DBG_ANY,
30049 +                   "++Resume and Remote Wakeup Detected Interrupt++\n");
30050 +
30051 +       DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
30052 +
30053 +       if (dwc_otg_is_device_mode(core_if)) {
30054 +               dctl_data_t dctl = {.d32 = 0 };
30055 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
30056 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
30057 +                                          dsts));
30058 +               if (core_if->lx_state == DWC_OTG_L2) {
30059 +#ifdef PARTIAL_POWER_DOWN
30060 +                       if (core_if->hwcfg4.b.power_optimiz) {
30061 +                               pcgcctl_data_t power = {.d32 = 0 };
30062 +
30063 +                               power.d32 = DWC_READ_REG32(core_if->pcgcctl);
30064 +                               DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
30065 +                                           power.d32);
30066 +
30067 +                               power.b.stoppclk = 0;
30068 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30069 +
30070 +                               power.b.pwrclmp = 0;
30071 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30072 +
30073 +                               power.b.rstpdwnmodule = 0;
30074 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30075 +                       }
30076 +#endif
30077 +                       /* Clear the Remote Wakeup Signaling */
30078 +                       dctl.b.rmtwkupsig = 1;
30079 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
30080 +                                        dctl, dctl.d32, 0);
30081 +
30082 +                       DWC_SPINUNLOCK(core_if->lock);
30083 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
30084 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
30085 +                       }
30086 +                       DWC_SPINLOCK(core_if->lock);
30087 +               } else {
30088 +                       glpmcfg_data_t lpmcfg;
30089 +                       lpmcfg.d32 =
30090 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30091 +                       lpmcfg.b.hird_thres &= (~(1 << 4));
30092 +                       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30093 +                                       lpmcfg.d32);
30094 +               }
30095 +               /** Change to L0 state*/
30096 +               core_if->lx_state = DWC_OTG_L0;
30097 +       } else {
30098 +               if (core_if->lx_state != DWC_OTG_L1) {
30099 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30100 +
30101 +                       /* Restart the Phy Clock */
30102 +                       pcgcctl.b.stoppclk = 1;
30103 +                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30104 +                       DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
30105 +               } else {
30106 +                       /** Change to L0 state*/
30107 +                       core_if->lx_state = DWC_OTG_L0;
30108 +               }
30109 +       }
30110 +
30111 +       /* Clear interrupt */
30112 +       gintsts.d32 = 0;
30113 +       gintsts.b.wkupintr = 1;
30114 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30115 +
30116 +       return 1;
30117 +}
30118 +
30119 +/**
30120 + * This interrupt indicates that the Wakeup Logic has detected a
30121 + * Device disconnect.
30122 + */
30123 +static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
30124 +{
30125 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
30126 +       gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
30127 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30128 +
30129 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30130 +
30131 +       if (!core_if->hibernation_suspend) {
30132 +               DWC_PRINTF("Already exited from Hibernation\n");
30133 +               return 1;
30134 +       }
30135 +
30136 +       /* Switch on the voltage to the core */
30137 +       gpwrdn.b.pwrdnswtch = 1;
30138 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30139 +       dwc_udelay(10);
30140 +
30141 +       /* Reset the core */
30142 +       gpwrdn.d32 = 0;
30143 +       gpwrdn.b.pwrdnrstn = 1;
30144 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30145 +       dwc_udelay(10);
30146 +
30147 +       /* Disable power clamps*/
30148 +       gpwrdn.d32 = 0;
30149 +       gpwrdn.b.pwrdnclmp = 1;
30150 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30151 +
30152 +       /* Remove reset the core signal */
30153 +       gpwrdn.d32 = 0;
30154 +       gpwrdn.b.pwrdnrstn = 1;
30155 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30156 +       dwc_udelay(10);
30157 +
30158 +       /* Disable PMU interrupt */
30159 +       gpwrdn.d32 = 0;
30160 +       gpwrdn.b.pmuintsel = 1;
30161 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30162 +
30163 +       core_if->hibernation_suspend = 0;
30164 +
30165 +       /* Disable PMU */
30166 +       gpwrdn.d32 = 0;
30167 +       gpwrdn.b.pmuactv = 1;
30168 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30169 +       dwc_udelay(10);
30170 +
30171 +       if (gpwrdn_temp.b.idsts) {
30172 +               core_if->op_state = B_PERIPHERAL;
30173 +               dwc_otg_core_init(core_if);
30174 +               dwc_otg_enable_global_interrupts(core_if);
30175 +               cil_pcd_start(core_if);
30176 +       } else {
30177 +               core_if->op_state = A_HOST;
30178 +               dwc_otg_core_init(core_if);
30179 +               dwc_otg_enable_global_interrupts(core_if);
30180 +               cil_hcd_start(core_if);
30181 +       }
30182 +
30183 +       return 1;
30184 +}
30185 +
30186 +/**
30187 + * This interrupt indicates that the Wakeup Logic has detected a
30188 + * remote wakeup sequence.
30189 + */
30190 +static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30191 +{
30192 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30193 +       DWC_DEBUGPL(DBG_ANY,
30194 +                   "++Powerdown Remote Wakeup Detected Interrupt++\n");
30195 +
30196 +       if (!core_if->hibernation_suspend) {
30197 +               DWC_PRINTF("Already exited from Hibernation\n");
30198 +               return 1;
30199 +       }
30200 +
30201 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30202 +       if (gpwrdn.b.idsts) {   // Device Mode
30203 +               if ((core_if->power_down == 2)
30204 +                   && (core_if->hibernation_suspend == 1)) {
30205 +                       dwc_otg_device_hibernation_restore(core_if, 0, 0);
30206 +               }
30207 +       } else {
30208 +               if ((core_if->power_down == 2)
30209 +                   && (core_if->hibernation_suspend == 1)) {
30210 +                       dwc_otg_host_hibernation_restore(core_if, 1, 0);
30211 +               }
30212 +       }
30213 +       return 1;
30214 +}
30215 +
30216 +static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
30217 +{
30218 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30219 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30220 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30221 +
30222 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30223 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30224 +       if (core_if->power_down == 2) {
30225 +               if (!core_if->hibernation_suspend) {
30226 +                       DWC_PRINTF("Already exited from Hibernation\n");
30227 +                       return 1;
30228 +               }
30229 +               DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
30230 +               /* Switch on the voltage to the core */
30231 +               gpwrdn.b.pwrdnswtch = 1;
30232 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30233 +               dwc_udelay(10);
30234 +
30235 +               /* Reset the core */
30236 +               gpwrdn.d32 = 0;
30237 +               gpwrdn.b.pwrdnrstn = 1;
30238 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30239 +               dwc_udelay(10);
30240 +
30241 +               /* Disable power clamps */
30242 +               gpwrdn.d32 = 0;
30243 +               gpwrdn.b.pwrdnclmp = 1;
30244 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30245 +
30246 +               /* Remove reset the core signal */
30247 +               gpwrdn.d32 = 0;
30248 +               gpwrdn.b.pwrdnrstn = 1;
30249 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30250 +               dwc_udelay(10);
30251 +
30252 +               /* Disable PMU interrupt */
30253 +               gpwrdn.d32 = 0;
30254 +               gpwrdn.b.pmuintsel = 1;
30255 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30256 +
30257 +               /*Indicates that we are exiting from hibernation */
30258 +               core_if->hibernation_suspend = 0;
30259 +
30260 +               /* Disable PMU */
30261 +               gpwrdn.d32 = 0;
30262 +               gpwrdn.b.pmuactv = 1;
30263 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30264 +               dwc_udelay(10);
30265 +
30266 +               gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
30267 +               if (gpwrdn.b.dis_vbus == 1) {
30268 +                       gpwrdn.d32 = 0;
30269 +                       gpwrdn.b.dis_vbus = 1;
30270 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30271 +               }
30272 +
30273 +               if (gpwrdn_temp.b.idsts) {
30274 +                       core_if->op_state = B_PERIPHERAL;
30275 +                       dwc_otg_core_init(core_if);
30276 +                       dwc_otg_enable_global_interrupts(core_if);
30277 +                       cil_pcd_start(core_if);
30278 +               } else {
30279 +                       core_if->op_state = A_HOST;
30280 +                       dwc_otg_core_init(core_if);
30281 +                       dwc_otg_enable_global_interrupts(core_if);
30282 +                       cil_hcd_start(core_if);
30283 +               }
30284 +       }
30285 +
30286 +       if (core_if->adp_enable) {
30287 +               uint8_t is_host = 0;
30288 +               DWC_SPINUNLOCK(core_if->lock);
30289 +               /* Change the core_if's lock to hcd/pcd lock depend on mode? */
30290 +#ifndef DWC_HOST_ONLY
30291 +               if (gpwrdn_temp.b.idsts)
30292 +                       core_if->lock = otg_dev->pcd->lock;
30293 +#endif
30294 +#ifndef DWC_DEVICE_ONLY
30295 +               if (!gpwrdn_temp.b.idsts) {
30296 +                               core_if->lock = otg_dev->hcd->lock;
30297 +                               is_host = 1;
30298 +               }
30299 +#endif
30300 +               DWC_PRINTF("RESTART ADP\n");
30301 +               if (core_if->adp.probe_enabled)
30302 +                       dwc_otg_adp_probe_stop(core_if);
30303 +               if (core_if->adp.sense_enabled)
30304 +                       dwc_otg_adp_sense_stop(core_if);
30305 +               if (core_if->adp.sense_timer_started)
30306 +                       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
30307 +               if (core_if->adp.vbuson_timer_started)
30308 +                       DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
30309 +               core_if->adp.probe_timer_values[0] = -1;
30310 +               core_if->adp.probe_timer_values[1] = -1;
30311 +               core_if->adp.sense_timer_started = 0;
30312 +               core_if->adp.vbuson_timer_started = 0;
30313 +               core_if->adp.probe_counter = 0;
30314 +               core_if->adp.gpwrdn = 0;
30315 +
30316 +               /* Disable PMU and restart ADP */
30317 +               gpwrdn_temp.d32 = 0;
30318 +               gpwrdn_temp.b.pmuactv = 1;
30319 +               gpwrdn_temp.b.pmuintsel = 1;
30320 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30321 +               DWC_PRINTF("Check point 1\n");
30322 +               dwc_mdelay(110);
30323 +               dwc_otg_adp_start(core_if, is_host);
30324 +               DWC_SPINLOCK(core_if->lock);
30325 +       }
30326 +
30327 +
30328 +       return 1;
30329 +}
30330 +
30331 +static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
30332 +{
30333 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30334 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
30335 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30336 +
30337 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30338 +       if (core_if->power_down == 2) {
30339 +               if (!core_if->hibernation_suspend) {
30340 +                       DWC_PRINTF("Already exited from Hibernation\n");
30341 +                       return 1;
30342 +               }
30343 +
30344 +               if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30345 +                        otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
30346 +                       gpwrdn.b.bsessvld == 0) {
30347 +                       /* Save gpwrdn register for further usage if stschng interrupt */
30348 +                       core_if->gr_backup->gpwrdn_local =
30349 +                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30350 +                       /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
30351 +                       return 1;
30352 +               }
30353 +
30354 +               /* Switch on the voltage to the core */
30355 +               gpwrdn.d32 = 0;
30356 +               gpwrdn.b.pwrdnswtch = 1;
30357 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30358 +               dwc_udelay(10);
30359 +
30360 +               /* Reset the core */
30361 +               gpwrdn.d32 = 0;
30362 +               gpwrdn.b.pwrdnrstn = 1;
30363 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30364 +               dwc_udelay(10);
30365 +
30366 +               /* Disable power clamps */
30367 +               gpwrdn.d32 = 0;
30368 +               gpwrdn.b.pwrdnclmp = 1;
30369 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30370 +
30371 +               /* Remove reset the core signal */
30372 +               gpwrdn.d32 = 0;
30373 +               gpwrdn.b.pwrdnrstn = 1;
30374 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30375 +               dwc_udelay(10);
30376 +
30377 +               /* Disable PMU interrupt */
30378 +               gpwrdn.d32 = 0;
30379 +               gpwrdn.b.pmuintsel = 1;
30380 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30381 +               dwc_udelay(10);
30382 +
30383 +               /*Indicates that we are exiting from hibernation */
30384 +               core_if->hibernation_suspend = 0;
30385 +
30386 +               /* Disable PMU */
30387 +               gpwrdn.d32 = 0;
30388 +               gpwrdn.b.pmuactv = 1;
30389 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30390 +               dwc_udelay(10);
30391 +
30392 +               core_if->op_state = B_PERIPHERAL;
30393 +               dwc_otg_core_init(core_if);
30394 +               dwc_otg_enable_global_interrupts(core_if);
30395 +               cil_pcd_start(core_if);
30396 +
30397 +               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30398 +                       otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
30399 +                       /*
30400 +                        * Initiate SRP after initial ADP probe.
30401 +                        */
30402 +                       dwc_otg_initiate_srp(core_if);
30403 +               }
30404 +       }
30405 +
30406 +       return 1;
30407 +}
30408 +/**
30409 + * This interrupt indicates that the Wakeup Logic has detected a
30410 + * status change either on IDDIG or BSessVld.
30411 + */
30412 +static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
30413 +{
30414 +       int retval;
30415 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30416 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30417 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30418 +
30419 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30420 +
30421 +       if (core_if->power_down == 2) {
30422 +               if (core_if->hibernation_suspend <= 0) {
30423 +                       DWC_PRINTF("Already exited from Hibernation\n");
30424 +                       return 1;
30425 +               } else
30426 +                       gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
30427 +
30428 +       } else {
30429 +               gpwrdn_temp.d32 = core_if->adp.gpwrdn;
30430 +       }
30431 +
30432 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30433 +
30434 +       if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
30435 +               retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
30436 +       } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
30437 +               retval = dwc_otg_handle_pwrdn_session_change(core_if);
30438 +       }
30439 +
30440 +       return retval;
30441 +}
30442 +
30443 +/**
30444 + * This interrupt indicates that the Wakeup Logic has detected a
30445 + * SRP.
30446 + */
30447 +static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
30448 +{
30449 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30450 +
30451 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30452 +
30453 +       if (!core_if->hibernation_suspend) {
30454 +               DWC_PRINTF("Already exited from Hibernation\n");
30455 +               return 1;
30456 +       }
30457 +#ifdef DWC_DEV_SRPCAP
30458 +       if (core_if->pwron_timer_started) {
30459 +               core_if->pwron_timer_started = 0;
30460 +               DWC_TIMER_CANCEL(core_if->pwron_timer);
30461 +       }
30462 +#endif
30463 +
30464 +       /* Switch on the voltage to the core */
30465 +       gpwrdn.b.pwrdnswtch = 1;
30466 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30467 +       dwc_udelay(10);
30468 +
30469 +       /* Reset the core */
30470 +       gpwrdn.d32 = 0;
30471 +       gpwrdn.b.pwrdnrstn = 1;
30472 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30473 +       dwc_udelay(10);
30474 +
30475 +       /* Disable power clamps */
30476 +       gpwrdn.d32 = 0;
30477 +       gpwrdn.b.pwrdnclmp = 1;
30478 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30479 +
30480 +       /* Remove reset the core signal */
30481 +       gpwrdn.d32 = 0;
30482 +       gpwrdn.b.pwrdnrstn = 1;
30483 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30484 +       dwc_udelay(10);
30485 +
30486 +       /* Disable PMU interrupt */
30487 +       gpwrdn.d32 = 0;
30488 +       gpwrdn.b.pmuintsel = 1;
30489 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30490 +
30491 +       /* Indicates that we are exiting from hibernation */
30492 +       core_if->hibernation_suspend = 0;
30493 +
30494 +       /* Disable PMU */
30495 +       gpwrdn.d32 = 0;
30496 +       gpwrdn.b.pmuactv = 1;
30497 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30498 +       dwc_udelay(10);
30499 +
30500 +       /* Programm Disable VBUS to 0 */
30501 +       gpwrdn.d32 = 0;
30502 +       gpwrdn.b.dis_vbus = 1;
30503 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30504 +
30505 +       /*Initialize the core as Host */
30506 +       core_if->op_state = A_HOST;
30507 +       dwc_otg_core_init(core_if);
30508 +       dwc_otg_enable_global_interrupts(core_if);
30509 +       cil_hcd_start(core_if);
30510 +
30511 +       return 1;
30512 +}
30513 +
30514 +/** This interrupt indicates that restore command after Hibernation
30515 + * was completed by the core. */
30516 +int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
30517 +{
30518 +       pcgcctl_data_t pcgcctl;
30519 +       DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
30520 +
30521 +       //TODO De-assert restore signal. 8.a
30522 +       pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
30523 +       if (pcgcctl.b.restoremode == 1) {
30524 +               gintmsk_data_t gintmsk = {.d32 = 0 };
30525 +               /*
30526 +                * If restore mode is Remote Wakeup,
30527 +                * unmask Remote Wakeup interrupt.
30528 +                */
30529 +               gintmsk.b.wkupintr = 1;
30530 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
30531 +                                0, gintmsk.d32);
30532 +       }
30533 +
30534 +       return 1;
30535 +}
30536 +
30537 +/**
30538 + * This interrupt indicates that a device has been disconnected from
30539 + * the root port.
30540 + */
30541 +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
30542 +{
30543 +       gintsts_data_t gintsts;
30544 +
30545 +       DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
30546 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
30547 +                   op_state_str(core_if));
30548 +
30549 +/** @todo Consolidate this if statement. */
30550 +#ifndef DWC_HOST_ONLY
30551 +       if (core_if->op_state == B_HOST) {
30552 +               /* If in device mode Disconnect and stop the HCD, then
30553 +                * start the PCD. */
30554 +               DWC_SPINUNLOCK(core_if->lock);
30555 +               cil_hcd_disconnect(core_if);
30556 +               cil_pcd_start(core_if);
30557 +               DWC_SPINLOCK(core_if->lock);
30558 +               core_if->op_state = B_PERIPHERAL;
30559 +       } else if (dwc_otg_is_device_mode(core_if)) {
30560 +               gotgctl_data_t gotgctl = {.d32 = 0 };
30561 +               gotgctl.d32 =
30562 +                   DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
30563 +               if (gotgctl.b.hstsethnpen == 1) {
30564 +                       /* Do nothing, if HNP in process the OTG
30565 +                        * interrupt "Host Negotiation Detected"
30566 +                        * interrupt will do the mode switch.
30567 +                        */
30568 +               } else if (gotgctl.b.devhnpen == 0) {
30569 +                       /* If in device mode Disconnect and stop the HCD, then
30570 +                        * start the PCD. */
30571 +                       DWC_SPINUNLOCK(core_if->lock);
30572 +                       cil_hcd_disconnect(core_if);
30573 +                       cil_pcd_start(core_if);
30574 +                       DWC_SPINLOCK(core_if->lock);
30575 +                       core_if->op_state = B_PERIPHERAL;
30576 +               } else {
30577 +                       DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
30578 +               }
30579 +       } else {
30580 +               if (core_if->op_state == A_HOST) {
30581 +                       /* A-Cable still connected but device disconnected. */
30582 +                       cil_hcd_disconnect(core_if);
30583 +                       if (core_if->adp_enable) {
30584 +                               gpwrdn_data_t gpwrdn = { .d32 = 0 };
30585 +                               cil_hcd_stop(core_if);
30586 +                               /* Enable Power Down Logic */
30587 +                               gpwrdn.b.pmuintsel = 1;
30588 +                               gpwrdn.b.pmuactv = 1;
30589 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30590 +                                                gpwrdn, 0, gpwrdn.d32);
30591 +                               dwc_otg_adp_probe_start(core_if);
30592 +
30593 +                               /* Power off the core */
30594 +                               if (core_if->power_down == 2) {
30595 +                                       gpwrdn.d32 = 0;
30596 +                                       gpwrdn.b.pwrdnswtch = 1;
30597 +                                       DWC_MODIFY_REG32
30598 +                                           (&core_if->core_global_regs->gpwrdn,
30599 +                                            gpwrdn.d32, 0);
30600 +                               }
30601 +                       }
30602 +               }
30603 +       }
30604 +#endif
30605 +       /* Change to L3(OFF) state */
30606 +       core_if->lx_state = DWC_OTG_L3;
30607 +
30608 +       gintsts.d32 = 0;
30609 +       gintsts.b.disconnect = 1;
30610 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30611 +       return 1;
30612 +}
30613 +
30614 +/**
30615 + * This interrupt indicates that SUSPEND state has been detected on
30616 + * the USB.
30617 + *
30618 + * For HNP the USB Suspend interrupt signals the change from
30619 + * "a_peripheral" to "a_host".
30620 + *
30621 + * When power management is enabled the core will be put in low power
30622 + * mode.
30623 + */
30624 +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
30625 +{
30626 +       dsts_data_t dsts;
30627 +       gintsts_data_t gintsts;
30628 +       dcfg_data_t dcfg;
30629 +
30630 +       DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
30631 +
30632 +       if (dwc_otg_is_device_mode(core_if)) {
30633 +               /* Check the Device status register to determine if the Suspend
30634 +                * state is active. */
30635 +               dsts.d32 =
30636 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
30637 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
30638 +               DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
30639 +                           "HWCFG4.power Optimize=%d\n",
30640 +                           dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
30641 +
30642 +#ifdef PARTIAL_POWER_DOWN
30643 +/** @todo Add a module parameter for power management. */
30644 +
30645 +               if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
30646 +                       pcgcctl_data_t power = {.d32 = 0 };
30647 +                       DWC_DEBUGPL(DBG_CIL, "suspend\n");
30648 +
30649 +                       power.b.pwrclmp = 1;
30650 +                       DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30651 +
30652 +                       power.b.rstpdwnmodule = 1;
30653 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30654 +
30655 +                       power.b.stoppclk = 1;
30656 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30657 +
30658 +               } else {
30659 +                       DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
30660 +               }
30661 +#endif
30662 +               /* PCD callback for suspend. Release the lock inside of callback function */
30663 +               cil_pcd_suspend(core_if);
30664 +               if (core_if->power_down == 2)
30665 +               {
30666 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30667 +                       DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
30668 +                       DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
30669 +
30670 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30671 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
30672 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
30673 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
30674 +
30675 +                               /* Change to L2(suspend) state */
30676 +                               core_if->lx_state = DWC_OTG_L2;
30677 +
30678 +                               /* Clear interrupt in gintsts */
30679 +                               gintsts.d32 = 0;
30680 +                               gintsts.b.usbsuspend = 1;
30681 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30682 +                                               gintsts, gintsts.d32);
30683 +                               DWC_PRINTF("Start of hibernation completed\n");
30684 +                               dwc_otg_save_global_regs(core_if);
30685 +                               dwc_otg_save_dev_regs(core_if);
30686 +
30687 +                               gusbcfg.d32 =
30688 +                                   DWC_READ_REG32(&core_if->core_global_regs->
30689 +                                                  gusbcfg);
30690 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
30691 +                                       /* ULPI interface */
30692 +                                       /* Suspend the Phy Clock */
30693 +                                       pcgcctl.d32 = 0;
30694 +                                       pcgcctl.b.stoppclk = 1;
30695 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30696 +                                                        pcgcctl.d32);
30697 +                                       dwc_udelay(10);
30698 +                                       gpwrdn.b.pmuactv = 1;
30699 +                                       DWC_MODIFY_REG32(&core_if->
30700 +                                                        core_global_regs->
30701 +                                                        gpwrdn, 0, gpwrdn.d32);
30702 +                               } else {
30703 +                                       /* UTMI+ Interface */
30704 +                                       gpwrdn.b.pmuactv = 1;
30705 +                                       DWC_MODIFY_REG32(&core_if->
30706 +                                                        core_global_regs->
30707 +                                                        gpwrdn, 0, gpwrdn.d32);
30708 +                                       dwc_udelay(10);
30709 +                                       pcgcctl.b.stoppclk = 1;
30710 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30711 +                                                        pcgcctl.d32);
30712 +                                       dwc_udelay(10);
30713 +                               }
30714 +
30715 +                               /* Set flag to indicate that we are in hibernation */
30716 +                               core_if->hibernation_suspend = 1;
30717 +                               /* Enable interrupts from wake up logic */
30718 +                               gpwrdn.d32 = 0;
30719 +                               gpwrdn.b.pmuintsel = 1;
30720 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30721 +                                                gpwrdn, 0, gpwrdn.d32);
30722 +                               dwc_udelay(10);
30723 +
30724 +                               /* Unmask device mode interrupts in GPWRDN */
30725 +                               gpwrdn.d32 = 0;
30726 +                               gpwrdn.b.rst_det_msk = 1;
30727 +                               gpwrdn.b.lnstchng_msk = 1;
30728 +                               gpwrdn.b.sts_chngint_msk = 1;
30729 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30730 +                                                gpwrdn, 0, gpwrdn.d32);
30731 +                               dwc_udelay(10);
30732 +
30733 +                               /* Enable Power Down Clamp */
30734 +                               gpwrdn.d32 = 0;
30735 +                               gpwrdn.b.pwrdnclmp = 1;
30736 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30737 +                                                gpwrdn, 0, gpwrdn.d32);
30738 +                               dwc_udelay(10);
30739 +
30740 +                               /* Switch off VDD */
30741 +                               gpwrdn.d32 = 0;
30742 +                               gpwrdn.b.pwrdnswtch = 1;
30743 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30744 +                                                gpwrdn, 0, gpwrdn.d32);
30745 +
30746 +                               /* Save gpwrdn register for further usage if stschng interrupt */
30747 +                               core_if->gr_backup->gpwrdn_local =
30748 +                                                       DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30749 +                               DWC_PRINTF("Hibernation completed\n");
30750 +
30751 +                               return 1;
30752 +                       }
30753 +               } else if (core_if->power_down == 3) {
30754 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30755 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30756 +                       DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);
30757 +                       DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);
30758 +
30759 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30760 +                               DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");
30761 +                               core_if->xhib = 1;
30762 +
30763 +                               /* Clear interrupt in gintsts */
30764 +                               gintsts.d32 = 0;
30765 +                               gintsts.b.usbsuspend = 1;
30766 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30767 +                                       gintsts, gintsts.d32);
30768 +
30769 +                               dwc_otg_save_global_regs(core_if);
30770 +                               dwc_otg_save_dev_regs(core_if);
30771 +
30772 +                               /* Wait for 10 PHY clocks */
30773 +                               dwc_udelay(10);
30774 +
30775 +                               /* Program GPIO register while entering to xHib */
30776 +                               DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);
30777 +
30778 +                               pcgcctl.b.enbl_extnd_hiber = 1;
30779 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30780 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30781 +
30782 +                               pcgcctl.d32 = 0;
30783 +                               pcgcctl.b.extnd_hiber_pwrclmp = 1;
30784 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30785 +
30786 +                               pcgcctl.d32 = 0;
30787 +                               pcgcctl.b.extnd_hiber_switch = 1;
30788 +                               core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30789 +                               core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;
30790 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30791 +
30792 +                               DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");
30793 +
30794 +                               return 1;
30795 +                       }
30796 +               }
30797 +       } else {
30798 +               if (core_if->op_state == A_PERIPHERAL) {
30799 +                       DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
30800 +                       /* Clear the a_peripheral flag, back to a_host. */
30801 +                       DWC_SPINUNLOCK(core_if->lock);
30802 +                       cil_pcd_stop(core_if);
30803 +                       cil_hcd_start(core_if);
30804 +                       DWC_SPINLOCK(core_if->lock);
30805 +                       core_if->op_state = A_HOST;
30806 +               }
30807 +       }
30808 +
30809 +       /* Change to L2(suspend) state */
30810 +       core_if->lx_state = DWC_OTG_L2;
30811 +
30812 +       /* Clear interrupt */
30813 +       gintsts.d32 = 0;
30814 +       gintsts.b.usbsuspend = 1;
30815 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30816 +
30817 +       return 1;
30818 +}
30819 +
30820 +static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)
30821 +{
30822 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30823 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30824 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
30825 +
30826 +       dwc_udelay(10);
30827 +
30828 +       /* Program GPIO register while entering to xHib */
30829 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
30830 +
30831 +       pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
30832 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30833 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30834 +       dwc_udelay(10);
30835 +
30836 +       gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
30837 +       gpwrdn.b.restore = 1;
30838 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
30839 +       dwc_udelay(10);
30840 +
30841 +       restore_lpm_i2c_regs(core_if);
30842 +
30843 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30844 +       pcgcctl.b.max_xcvrselect = 1;
30845 +       pcgcctl.b.ess_reg_restored = 0;
30846 +       pcgcctl.b.extnd_hiber_switch = 0;
30847 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30848 +       pcgcctl.b.enbl_extnd_hiber = 1;
30849 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30850 +
30851 +       gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
30852 +       gahbcfg.b.glblintrmsk = 1;
30853 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
30854 +
30855 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
30856 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
30857 +
30858 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
30859 +                       core_if->gr_backup->gusbcfg_local);
30860 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
30861 +                       core_if->dr_backup->dcfg);
30862 +
30863 +       pcgcctl.d32 = 0;
30864 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30865 +       pcgcctl.b.max_xcvrselect = 1;
30866 +       pcgcctl.d32 |= 0x608;
30867 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30868 +       dwc_udelay(10);
30869 +
30870 +       pcgcctl.d32 = 0;
30871 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30872 +       pcgcctl.b.max_xcvrselect = 1;
30873 +       pcgcctl.b.ess_reg_restored = 1;
30874 +       pcgcctl.b.enbl_extnd_hiber = 1;
30875 +       pcgcctl.b.rstpdwnmodule = 1;
30876 +       pcgcctl.b.restoremode = 1;
30877 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30878 +
30879 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30880 +
30881 +       return 1;
30882 +}
30883 +
30884 +#ifdef CONFIG_USB_DWC_OTG_LPM
30885 +/**
30886 + * This function hadles LPM transaction received interrupt.
30887 + */
30888 +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
30889 +{
30890 +       glpmcfg_data_t lpmcfg;
30891 +       gintsts_data_t gintsts;
30892 +
30893 +       if (!core_if->core_params->lpm_enable) {
30894 +               DWC_PRINTF("Unexpected LPM interrupt\n");
30895 +       }
30896 +
30897 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30898 +       DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
30899 +
30900 +       if (dwc_otg_is_host_mode(core_if)) {
30901 +               cil_hcd_sleep(core_if);
30902 +       } else {
30903 +               lpmcfg.b.hird_thres |= (1 << 4);
30904 +               DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30905 +                               lpmcfg.d32);
30906 +       }
30907 +
30908 +       /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
30909 +       dwc_udelay(10);
30910 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30911 +       if (lpmcfg.b.prt_sleep_sts) {
30912 +               /* Save the current state */
30913 +               core_if->lx_state = DWC_OTG_L1;
30914 +       }
30915 +
30916 +       /* Clear interrupt  */
30917 +       gintsts.d32 = 0;
30918 +       gintsts.b.lpmtranrcvd = 1;
30919 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30920 +       return 1;
30921 +}
30922 +#endif /* CONFIG_USB_DWC_OTG_LPM */
30923 +
30924 +/**
30925 + * This function returns the Core Interrupt register.
30926 + */
30927 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
30928 +{
30929 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
30930 +       gintsts_data_t gintsts;
30931 +       gintmsk_data_t gintmsk;
30932 +       gintmsk_data_t gintmsk_common = {.d32 = 0 };
30933 +       gintmsk_common.b.wkupintr = 1;
30934 +       gintmsk_common.b.sessreqintr = 1;
30935 +       gintmsk_common.b.conidstschng = 1;
30936 +       gintmsk_common.b.otgintr = 1;
30937 +       gintmsk_common.b.modemismatch = 1;
30938 +       gintmsk_common.b.disconnect = 1;
30939 +       gintmsk_common.b.usbsuspend = 1;
30940 +#ifdef CONFIG_USB_DWC_OTG_LPM
30941 +       gintmsk_common.b.lpmtranrcvd = 1;
30942 +#endif
30943 +       gintmsk_common.b.restoredone = 1;
30944 +       /** @todo: The port interrupt occurs while in device
30945 +         * mode. Added code to CIL to clear the interrupt for now!
30946 +         */
30947 +       gintmsk_common.b.portintr = 1;
30948 +
30949 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
30950 +       gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
30951 +       gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
30952 +
30953 +#ifdef DEBUG
30954 +       /* if any common interrupts set */
30955 +       if (gintsts.d32 & gintmsk_common.d32) {
30956 +               DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
30957 +                           gintsts.d32, gintmsk.d32);
30958 +       }
30959 +#endif
30960 +       if (gahbcfg.b.glblintrmsk)
30961 +               return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
30962 +       else
30963 +               return 0;
30964 +
30965 +}
30966 +
30967 +/* MACRO for clearing interupt bits in GPWRDN register */
30968 +#define CLEAR_GPWRDN_INTR(__core_if,__intr) \
30969 +do { \
30970 +               gpwrdn_data_t gpwrdn = {.d32=0}; \
30971 +               gpwrdn.b.__intr = 1; \
30972 +               DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
30973 +               0, gpwrdn.d32); \
30974 +} while (0)
30975 +
30976 +/**
30977 + * Common interrupt handler.
30978 + *
30979 + * The common interrupts are those that occur in both Host and Device mode.
30980 + * This handler handles the following interrupts:
30981 + * - Mode Mismatch Interrupt
30982 + * - Disconnect Interrupt
30983 + * - OTG Interrupt
30984 + * - Connector ID Status Change Interrupt
30985 + * - Session Request Interrupt.
30986 + * - Resume / Remote Wakeup Detected Interrupt.
30987 + * - LPM Transaction Received Interrupt
30988 + * - ADP Transaction Received Interrupt
30989 + *
30990 + */
30991 +int32_t dwc_otg_handle_common_intr(void *dev)
30992 +{
30993 +       int retval = 0;
30994 +       gintsts_data_t gintsts;
30995 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30996 +       dwc_otg_device_t *otg_dev = dev;
30997 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30998 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30999 +       if (dwc_otg_is_device_mode(core_if))
31000 +               core_if->frame_num = dwc_otg_get_frame_number(core_if);
31001 +
31002 +       if (core_if->lock)
31003 +               DWC_SPINLOCK(core_if->lock);
31004 +
31005 +       if (core_if->power_down == 3 && core_if->xhib == 1) {
31006 +               DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
31007 +               retval |= dwc_otg_handle_xhib_exit_intr(core_if);
31008 +               core_if->xhib = 2;
31009 +               if (core_if->lock)
31010 +                       DWC_SPINUNLOCK(core_if->lock);
31011 +
31012 +               return retval;
31013 +       }
31014 +
31015 +       if (core_if->hibernation_suspend <= 0) {
31016 +               gintsts.d32 = dwc_otg_read_common_intr(core_if);
31017 +
31018 +               if (gintsts.b.modemismatch) {
31019 +                       retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
31020 +               }
31021 +               if (gintsts.b.otgintr) {
31022 +                       retval |= dwc_otg_handle_otg_intr(core_if);
31023 +               }
31024 +               if (gintsts.b.conidstschng) {
31025 +                       retval |=
31026 +                           dwc_otg_handle_conn_id_status_change_intr(core_if);
31027 +               }
31028 +               if (gintsts.b.disconnect) {
31029 +                       retval |= dwc_otg_handle_disconnect_intr(core_if);
31030 +               }
31031 +               if (gintsts.b.sessreqintr) {
31032 +                       retval |= dwc_otg_handle_session_req_intr(core_if);
31033 +               }
31034 +               if (gintsts.b.wkupintr) {
31035 +                       retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
31036 +               }
31037 +               if (gintsts.b.usbsuspend) {
31038 +                       retval |= dwc_otg_handle_usb_suspend_intr(core_if);
31039 +               }
31040 +#ifdef CONFIG_USB_DWC_OTG_LPM
31041 +               if (gintsts.b.lpmtranrcvd) {
31042 +                       retval |= dwc_otg_handle_lpm_intr(core_if);
31043 +               }
31044 +#endif
31045 +               if (gintsts.b.restoredone) {
31046 +                       gintsts.d32 = 0;
31047 +                       if (core_if->power_down == 2)
31048 +                               core_if->hibernation_suspend = -1;
31049 +                       else if (core_if->power_down == 3 && core_if->xhib == 2) {
31050 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
31051 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
31052 +                               dctl_data_t dctl = {.d32 = 0 };
31053 +
31054 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
31055 +                                               gintsts, 0xFFFFFFFF);
31056 +
31057 +                               DWC_DEBUGPL(DBG_ANY,
31058 +                                           "RESTORE DONE generated\n");
31059 +
31060 +                               gpwrdn.b.restore = 1;
31061 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
31062 +                               dwc_udelay(10);
31063 +
31064 +                               pcgcctl.b.rstpdwnmodule = 1;
31065 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31066 +
31067 +                               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);
31068 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);
31069 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);
31070 +                               dwc_udelay(50);
31071 +
31072 +                               dctl.b.pwronprgdone = 1;
31073 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
31074 +                               dwc_udelay(10);
31075 +
31076 +                               dwc_otg_restore_global_regs(core_if);
31077 +                               dwc_otg_restore_dev_regs(core_if, 0);
31078 +
31079 +                               dctl.d32 = 0;
31080 +                               dctl.b.pwronprgdone = 1;
31081 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
31082 +                               dwc_udelay(10);
31083 +
31084 +                               pcgcctl.d32 = 0;
31085 +                               pcgcctl.b.enbl_extnd_hiber = 1;
31086 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31087 +
31088 +                               /* The core will be in ON STATE */
31089 +                               core_if->lx_state = DWC_OTG_L0;
31090 +                               core_if->xhib = 0;
31091 +
31092 +                               DWC_SPINUNLOCK(core_if->lock);
31093 +                               if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
31094 +                                       core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
31095 +                               }
31096 +                               DWC_SPINLOCK(core_if->lock);
31097 +
31098 +                       }
31099 +
31100 +                       gintsts.b.restoredone = 1;
31101 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31102 +                       DWC_PRINTF(" --Restore done interrupt received-- \n");
31103 +                       retval |= 1;
31104 +               }
31105 +               if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
31106 +                       /* The port interrupt occurs while in device mode with HPRT0
31107 +                        * Port Enable/Disable.
31108 +                        */
31109 +                       gintsts.d32 = 0;
31110 +                       gintsts.b.portintr = 1;
31111 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31112 +                       retval |= 1;
31113 +
31114 +               }
31115 +       } else {
31116 +               DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
31117 +
31118 +               if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
31119 +                       CLEAR_GPWRDN_INTR(core_if, disconn_det);
31120 +                       if (gpwrdn.b.linestate == 0) {
31121 +                               dwc_otg_handle_pwrdn_disconnect_intr(core_if);
31122 +                       } else {
31123 +                               DWC_PRINTF("Disconnect detected while linestate is not 0\n");
31124 +                       }
31125 +
31126 +                       retval |= 1;
31127 +               }
31128 +               if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
31129 +                       CLEAR_GPWRDN_INTR(core_if, lnstschng);
31130 +                       /* remote wakeup from hibernation */
31131 +                       if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
31132 +                               dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
31133 +                       } else {
31134 +                               DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
31135 +                       }
31136 +                       retval |= 1;
31137 +               }
31138 +               if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
31139 +                       CLEAR_GPWRDN_INTR(core_if, rst_det);
31140 +                       if (gpwrdn.b.linestate == 0) {
31141 +                               DWC_PRINTF("Reset detected\n");
31142 +                               retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
31143 +                       }
31144 +               }
31145 +               if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
31146 +                       CLEAR_GPWRDN_INTR(core_if, srp_det);
31147 +                       dwc_otg_handle_pwrdn_srp_intr(core_if);
31148 +                       retval |= 1;
31149 +               }
31150 +       }
31151 +       /* Handle ADP interrupt here */
31152 +       if (gpwrdn.b.adp_int) {
31153 +               DWC_PRINTF("ADP interrupt\n");
31154 +               CLEAR_GPWRDN_INTR(core_if, adp_int);
31155 +               dwc_otg_adp_handle_intr(core_if);
31156 +               retval |= 1;
31157 +       }
31158 +       if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
31159 +               DWC_PRINTF("STS CHNG interrupt asserted\n");
31160 +               CLEAR_GPWRDN_INTR(core_if, sts_chngint);
31161 +               dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
31162 +
31163 +               retval |= 1;
31164 +       }
31165 +       if (core_if->lock)
31166 +               DWC_SPINUNLOCK(core_if->lock);
31167 +
31168 +       return retval;
31169 +}
31170 --- /dev/null
31171 +++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31172 @@ -0,0 +1,705 @@
31173 +/* ==========================================================================
31174 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
31175 + * $Revision: #13 $
31176 + * $Date: 2012/08/10 $
31177 + * $Change: 2047372 $
31178 + *
31179 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31180 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31181 + * otherwise expressly agreed to in writing between Synopsys and you.
31182 + *
31183 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31184 + * any End User Software License Agreement or Agreement for Licensed Product
31185 + * with Synopsys or any supplement thereto. You are permitted to use and
31186 + * redistribute this Software in source and binary forms, with or without
31187 + * modification, provided that redistributions of source code must retain this
31188 + * notice. You may not view, use, disclose, copy or distribute this file or
31189 + * any information contained herein except pursuant to this license grant from
31190 + * Synopsys. If you do not agree with this notice, including the disclaimer
31191 + * below, then you are not authorized to use the Software.
31192 + *
31193 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31194 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31195 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31196 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31197 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31198 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31199 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31200 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31201 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31202 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31203 + * DAMAGE.
31204 + * ========================================================================== */
31205 +#if !defined(__DWC_CORE_IF_H__)
31206 +#define __DWC_CORE_IF_H__
31207 +
31208 +#include "dwc_os.h"
31209 +
31210 +/** @file
31211 + * This file defines DWC_OTG Core API
31212 + */
31213 +
31214 +struct dwc_otg_core_if;
31215 +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
31216 +
31217 +/** Maximum number of Periodic FIFOs */
31218 +#define MAX_PERIO_FIFOS 15
31219 +/** Maximum number of Periodic FIFOs */
31220 +#define MAX_TX_FIFOS 15
31221 +
31222 +/** Maximum number of Endpoints/HostChannels */
31223 +#define MAX_EPS_CHANNELS 16
31224 +
31225 +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
31226 +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
31227 +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
31228 +
31229 +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
31230 +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
31231 +
31232 +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
31233 +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
31234 +
31235 +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
31236 +
31237 +/** This function should be called on every hardware interrupt. */
31238 +extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
31239 +
31240 +/** @name OTG Core Parameters */
31241 +/** @{ */
31242 +
31243 +/**
31244 + * Specifies the OTG capabilities. The driver will automatically
31245 + * detect the value for this parameter if none is specified.
31246 + * 0 - HNP and SRP capable (default)
31247 + * 1 - SRP Only capable
31248 + * 2 - No HNP/SRP capable
31249 + */
31250 +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
31251 +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
31252 +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
31253 +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
31254 +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
31255 +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
31256 +
31257 +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
31258 +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
31259 +#define dwc_param_opt_default 1
31260 +
31261 +/**
31262 + * Specifies whether to use slave or DMA mode for accessing the data
31263 + * FIFOs. The driver will automatically detect the value for this
31264 + * parameter if none is specified.
31265 + * 0 - Slave
31266 + * 1 - DMA (default, if available)
31267 + */
31268 +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
31269 +                                       int32_t val);
31270 +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
31271 +#define dwc_param_dma_enable_default 1
31272 +
31273 +/**
31274 + * When DMA mode is enabled specifies whether to use
31275 + * address DMA or DMA Descritor mode for accessing the data
31276 + * FIFOs in device mode. The driver will automatically detect
31277 + * the value for this parameter if none is specified.
31278 + * 0 - address DMA
31279 + * 1 - DMA Descriptor(default, if available)
31280 + */
31281 +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
31282 +                                            int32_t val);
31283 +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
31284 +//#define dwc_param_dma_desc_enable_default 1
31285 +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
31286 +
31287 +/** The DMA Burst size (applicable only for External DMA
31288 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
31289 + */
31290 +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
31291 +                                           int32_t val);
31292 +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
31293 +#define dwc_param_dma_burst_size_default 32
31294 +
31295 +/**
31296 + * Specifies the maximum speed of operation in host and device mode.
31297 + * The actual speed depends on the speed of the attached device and
31298 + * the value of phy_type. The actual speed depends on the speed of the
31299 + * attached device.
31300 + * 0 - High Speed (default)
31301 + * 1 - Full Speed
31302 + */
31303 +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
31304 +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
31305 +#define dwc_param_speed_default 0
31306 +#define DWC_SPEED_PARAM_HIGH 0
31307 +#define DWC_SPEED_PARAM_FULL 1
31308 +
31309 +/** Specifies whether low power mode is supported when attached
31310 + *     to a Full Speed or Low Speed device in host mode.
31311 + * 0 - Don't support low power mode (default)
31312 + * 1 - Support low power mode
31313 + */
31314 +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
31315 +                                                         core_if, int32_t val);
31316 +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
31317 +                                                             * core_if);
31318 +#define dwc_param_host_support_fs_ls_low_power_default 0
31319 +
31320 +/** Specifies the PHY clock rate in low power mode when connected to a
31321 + * Low Speed device in host mode. This parameter is applicable only if
31322 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
31323 + * then defaults to 6 MHZ otherwise 48 MHZ.
31324 + *
31325 + * 0 - 48 MHz
31326 + * 1 - 6 MHz
31327 + */
31328 +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31329 +                                                      core_if, int32_t val);
31330 +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31331 +                                                          core_if);
31332 +#define dwc_param_host_ls_low_power_phy_clk_default 0
31333 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
31334 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
31335 +
31336 +/**
31337 + * 0 - Use cC FIFO size parameters
31338 + * 1 - Allow dynamic FIFO sizing (default)
31339 + */
31340 +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
31341 +                                                int32_t val);
31342 +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
31343 +                                                    core_if);
31344 +#define dwc_param_enable_dynamic_fifo_default 1
31345 +
31346 +/** Total number of 4-byte words in the data FIFO memory. This
31347 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
31348 + * Tx FIFOs.
31349 + * 32 to 32768 (default 8192)
31350 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
31351 + */
31352 +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
31353 +                                           int32_t val);
31354 +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
31355 +//#define dwc_param_data_fifo_size_default 8192
31356 +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
31357 +
31358 +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
31359 + * FIFO sizing is enabled.
31360 + * 16 to 32768 (default 1064)
31361 + */
31362 +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
31363 +                                             int32_t val);
31364 +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
31365 +#define dwc_param_dev_rx_fifo_size_default 1064
31366 +
31367 +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
31368 + * when dynamic FIFO sizing is enabled.
31369 + * 16 to 32768 (default 1024)
31370 + */
31371 +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31372 +                                                    core_if, int32_t val);
31373 +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31374 +                                                        core_if);
31375 +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
31376 +
31377 +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
31378 + * mode when dynamic FIFO sizing is enabled.
31379 + * 4 to 768 (default 256)
31380 + */
31381 +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
31382 +                                                   int32_t val, int fifo_num);
31383 +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
31384 +                                                       core_if, int fifo_num);
31385 +#define dwc_param_dev_perio_tx_fifo_size_default 256
31386 +
31387 +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
31388 + * FIFO sizing is enabled.
31389 + * 16 to 32768 (default 1024)
31390 + */
31391 +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
31392 +                                              int32_t val);
31393 +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
31394 +//#define dwc_param_host_rx_fifo_size_default 1024
31395 +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
31396 +
31397 +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
31398 + * when Dynamic FIFO sizing is enabled in the core.
31399 + * 16 to 32768 (default 1024)
31400 + */
31401 +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31402 +                                                     core_if, int32_t val);
31403 +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31404 +                                                         core_if);
31405 +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
31406 +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
31407 +
31408 +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
31409 + * FIFO sizing is enabled.
31410 + * 16 to 32768 (default 1024)
31411 + */
31412 +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31413 +                                                    core_if, int32_t val);
31414 +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31415 +                                                        core_if);
31416 +//#define dwc_param_host_perio_tx_fifo_size_default 1024
31417 +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
31418 +
31419 +/** The maximum transfer size supported in bytes.
31420 + * 2047 to 65,535  (default 65,535)
31421 + */
31422 +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
31423 +                                              int32_t val);
31424 +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
31425 +#define dwc_param_max_transfer_size_default 65535
31426 +
31427 +/** The maximum number of packets in a transfer.
31428 + * 15 to 511  (default 511)
31429 + */
31430 +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
31431 +                                             int32_t val);
31432 +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
31433 +#define dwc_param_max_packet_count_default 511
31434 +
31435 +/** The number of host channel registers to use.
31436 + * 1 to 16 (default 12)
31437 + * Note: The FPGA configuration supports a maximum of 12 host channels.
31438 + */
31439 +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
31440 +                                          int32_t val);
31441 +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
31442 +//#define dwc_param_host_channels_default 12
31443 +#define dwc_param_host_channels_default 8 // Broadcom BCM2708
31444 +
31445 +/** The number of endpoints in addition to EP0 available for device
31446 + * mode operations.
31447 + * 1 to 15 (default 6 IN and OUT)
31448 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
31449 + * endpoints in addition to EP0.
31450 + */
31451 +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
31452 +                                          int32_t val);
31453 +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
31454 +#define dwc_param_dev_endpoints_default 6
31455 +
31456 +/**
31457 + * Specifies the type of PHY interface to use. By default, the driver
31458 + * will automatically detect the phy_type.
31459 + *
31460 + * 0 - Full Speed PHY
31461 + * 1 - UTMI+ (default)
31462 + * 2 - ULPI
31463 + */
31464 +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
31465 +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
31466 +#define DWC_PHY_TYPE_PARAM_FS 0
31467 +#define DWC_PHY_TYPE_PARAM_UTMI 1
31468 +#define DWC_PHY_TYPE_PARAM_ULPI 2
31469 +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
31470 +
31471 +/**
31472 + * Specifies the UTMI+ Data Width. This parameter is
31473 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
31474 + * PHY_TYPE, this parameter indicates the data width between
31475 + * the MAC and the ULPI Wrapper.) Also, this parameter is
31476 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
31477 + * to "8 and 16 bits", meaning that the core has been
31478 + * configured to work at either data path width.
31479 + *
31480 + * 8 or 16 bits (default 16)
31481 + */
31482 +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
31483 +                                           int32_t val);
31484 +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
31485 +//#define dwc_param_phy_utmi_width_default 16
31486 +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708
31487 +
31488 +/**
31489 + * Specifies whether the ULPI operates at double or single
31490 + * data rate. This parameter is only applicable if PHY_TYPE is
31491 + * ULPI.
31492 + *
31493 + * 0 - single data rate ULPI interface with 8 bit wide data
31494 + * bus (default)
31495 + * 1 - double data rate ULPI interface with 4 bit wide data
31496 + * bus
31497 + */
31498 +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
31499 +                                         int32_t val);
31500 +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
31501 +#define dwc_param_phy_ulpi_ddr_default 0
31502 +
31503 +/**
31504 + * Specifies whether to use the internal or external supply to
31505 + * drive the vbus with a ULPI phy.
31506 + */
31507 +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
31508 +                                              int32_t val);
31509 +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
31510 +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
31511 +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
31512 +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
31513 +
31514 +/**
31515 + * Specifies whether to use the I2Cinterface for full speed PHY. This
31516 + * parameter is only applicable if PHY_TYPE is FS.
31517 + * 0 - No (default)
31518 + * 1 - Yes
31519 + */
31520 +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
31521 +                                       int32_t val);
31522 +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
31523 +#define dwc_param_i2c_enable_default 0
31524 +
31525 +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
31526 +                                       int32_t val);
31527 +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
31528 +#define dwc_param_ulpi_fs_ls_default 0
31529 +
31530 +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
31531 +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
31532 +#define dwc_param_ts_dline_default 0
31533 +
31534 +/**
31535 + * Specifies whether dedicated transmit FIFOs are
31536 + * enabled for non periodic IN endpoints in device mode
31537 + * 0 - No
31538 + * 1 - Yes
31539 + */
31540 +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
31541 +                                                int32_t val);
31542 +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
31543 +                                                    core_if);
31544 +#define dwc_param_en_multiple_tx_fifo_default 1
31545 +
31546 +/** Number of 4-byte words in each of the Tx FIFOs in device
31547 + * mode when dynamic FIFO sizing is enabled.
31548 + * 4 to 768 (default 256)
31549 + */
31550 +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31551 +                                             int fifo_num, int32_t val);
31552 +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31553 +                                                 int fifo_num);
31554 +#define dwc_param_dev_tx_fifo_size_default 768
31555 +
31556 +/** Thresholding enable flag-
31557 + * bit 0 - enable non-ISO Tx thresholding
31558 + * bit 1 - enable ISO Tx thresholding
31559 + * bit 2 - enable Rx thresholding
31560 + */
31561 +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
31562 +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
31563 +#define dwc_param_thr_ctl_default 0
31564 +
31565 +/** Thresholding length for Tx
31566 + * FIFOs in 32 bit DWORDs
31567 + */
31568 +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
31569 +                                          int32_t val);
31570 +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
31571 +#define dwc_param_tx_thr_length_default 64
31572 +
31573 +/** Thresholding length for Rx
31574 + *     FIFOs in 32 bit DWORDs
31575 + */
31576 +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
31577 +                                          int32_t val);
31578 +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
31579 +#define dwc_param_rx_thr_length_default 64
31580 +
31581 +/**
31582 + * Specifies whether LPM (Link Power Management) support is enabled
31583 + */
31584 +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
31585 +                                       int32_t val);
31586 +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
31587 +#define dwc_param_lpm_enable_default 1
31588 +
31589 +/**
31590 + * Specifies whether PTI enhancement is enabled
31591 + */
31592 +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
31593 +                                       int32_t val);
31594 +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
31595 +#define dwc_param_pti_enable_default 0
31596 +
31597 +/**
31598 + * Specifies whether MPI enhancement is enabled
31599 + */
31600 +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
31601 +                                       int32_t val);
31602 +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
31603 +#define dwc_param_mpi_enable_default 0
31604 +
31605 +/**
31606 + * Specifies whether ADP capability is enabled
31607 + */
31608 +extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,
31609 +                                       int32_t val);
31610 +extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);
31611 +#define dwc_param_adp_enable_default 0
31612 +
31613 +/**
31614 + * Specifies whether IC_USB capability is enabled
31615 + */
31616 +
31617 +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
31618 +                                       int32_t val);
31619 +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
31620 +#define dwc_param_ic_usb_cap_default 0
31621 +
31622 +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,
31623 +                                          int32_t val);
31624 +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
31625 +#define dwc_param_ahb_thr_ratio_default 0
31626 +
31627 +extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,
31628 +                                       int32_t val);
31629 +extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);
31630 +#define dwc_param_power_down_default 0
31631 +
31632 +extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,
31633 +                                       int32_t val);
31634 +extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);
31635 +#define dwc_param_reload_ctl_default 0
31636 +
31637 +extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,
31638 +                                                                               int32_t val);
31639 +extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
31640 +#define dwc_param_dev_out_nak_default 0
31641 +
31642 +extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
31643 +                                                                                int32_t val);
31644 +extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
31645 +#define dwc_param_cont_on_bna_default 0
31646 +
31647 +extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
31648 +                                                                                int32_t val);
31649 +extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
31650 +#define dwc_param_ahb_single_default 0
31651 +
31652 +extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
31653 +extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
31654 +#define dwc_param_otg_ver_default 0
31655 +
31656 +/** @} */
31657 +
31658 +/** @name Access to registers and bit-fields */
31659 +
31660 +/**
31661 + * Dump core registers and SPRAM
31662 + */
31663 +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
31664 +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
31665 +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
31666 +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
31667 +
31668 +/**
31669 + * Get host negotiation status.
31670 + */
31671 +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
31672 +
31673 +/**
31674 + * Get srp status
31675 + */
31676 +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
31677 +
31678 +/**
31679 + * Set hnpreq bit in the GOTGCTL register.
31680 + */
31681 +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
31682 +
31683 +/**
31684 + * Get Content of SNPSID register.
31685 + */
31686 +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
31687 +
31688 +/**
31689 + * Get current mode.
31690 + * Returns 0 if in device mode, and 1 if in host mode.
31691 + */
31692 +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
31693 +
31694 +/**
31695 + * Get value of hnpcapable field in the GUSBCFG register
31696 + */
31697 +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
31698 +/**
31699 + * Set value of hnpcapable field in the GUSBCFG register
31700 + */
31701 +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31702 +
31703 +/**
31704 + * Get value of srpcapable field in the GUSBCFG register
31705 + */
31706 +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
31707 +/**
31708 + * Set value of srpcapable field in the GUSBCFG register
31709 + */
31710 +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31711 +
31712 +/**
31713 + * Get value of devspeed field in the DCFG register
31714 + */
31715 +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
31716 +/**
31717 + * Set value of devspeed field in the DCFG register
31718 + */
31719 +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
31720 +
31721 +/**
31722 + * Get the value of busconnected field from the HPRT0 register
31723 + */
31724 +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
31725 +
31726 +/**
31727 + * Gets the device enumeration Speed.
31728 + */
31729 +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
31730 +
31731 +/**
31732 + * Get value of prtpwr field from the HPRT0 register
31733 + */
31734 +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
31735 +
31736 +/**
31737 + * Get value of flag indicating core state - hibernated or not
31738 + */
31739 +extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);
31740 +
31741 +/**
31742 + * Set value of prtpwr field from the HPRT0 register
31743 + */
31744 +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
31745 +
31746 +/**
31747 + * Get value of prtsusp field from the HPRT0 regsiter
31748 + */
31749 +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
31750 +/**
31751 + * Set value of prtpwr field from the HPRT0 register
31752 + */
31753 +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
31754 +
31755 +/**
31756 + * Get value of ModeChTimEn field from the HCFG regsiter
31757 + */
31758 +extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);
31759 +/**
31760 + * Set value of ModeChTimEn field from the HCFG regsiter
31761 + */
31762 +extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);
31763 +
31764 +/**
31765 + * Get value of Fram Interval field from the HFIR regsiter
31766 + */
31767 +extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);
31768 +/**
31769 + * Set value of Frame Interval field from the HFIR regsiter
31770 + */
31771 +extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);
31772 +
31773 +/**
31774 + * Set value of prtres field from the HPRT0 register
31775 + *FIXME Remove?
31776 + */
31777 +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
31778 +
31779 +/**
31780 + * Get value of rmtwkupsig bit in DCTL register
31781 + */
31782 +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
31783 +
31784 +/**
31785 + * Get value of prt_sleep_sts field from the GLPMCFG register
31786 + */
31787 +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
31788 +
31789 +/**
31790 + * Get value of rem_wkup_en field from the GLPMCFG register
31791 + */
31792 +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
31793 +
31794 +/**
31795 + * Get value of appl_resp field from the GLPMCFG register
31796 + */
31797 +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
31798 +/**
31799 + * Set value of appl_resp field from the GLPMCFG register
31800 + */
31801 +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
31802 +
31803 +/**
31804 + * Get value of hsic_connect field from the GLPMCFG register
31805 + */
31806 +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
31807 +/**
31808 + * Set value of hsic_connect field from the GLPMCFG register
31809 + */
31810 +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
31811 +
31812 +/**
31813 + * Get value of inv_sel_hsic field from the GLPMCFG register.
31814 + */
31815 +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
31816 +/**
31817 + * Set value of inv_sel_hsic field from the GLPMFG register.
31818 + */
31819 +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
31820 +
31821 +/*
31822 + * Some functions for accessing registers
31823 + */
31824 +
31825 +/**
31826 + *  GOTGCTL register
31827 + */
31828 +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
31829 +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
31830 +
31831 +/**
31832 + * GUSBCFG register
31833 + */
31834 +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
31835 +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
31836 +
31837 +/**
31838 + * GRXFSIZ register
31839 + */
31840 +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
31841 +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31842 +
31843 +/**
31844 + * GNPTXFSIZ register
31845 + */
31846 +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
31847 +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31848 +
31849 +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
31850 +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
31851 +
31852 +/**
31853 + * GGPIO register
31854 + */
31855 +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
31856 +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
31857 +
31858 +/**
31859 + * GUID register
31860 + */
31861 +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
31862 +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
31863 +
31864 +/**
31865 + * HPRT0 register
31866 + */
31867 +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
31868 +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
31869 +
31870 +/**
31871 + * GHPTXFSIZE
31872 + */
31873 +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
31874 +
31875 +/** @} */
31876 +
31877 +#endif                         /* __DWC_CORE_IF_H__ */
31878 --- /dev/null
31879 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
31880 @@ -0,0 +1,116 @@
31881 +/* ==========================================================================
31882 + *
31883 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31884 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31885 + * otherwise expressly agreed to in writing between Synopsys and you.
31886 + *
31887 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31888 + * any End User Software License Agreement or Agreement for Licensed Product
31889 + * with Synopsys or any supplement thereto. You are permitted to use and
31890 + * redistribute this Software in source and binary forms, with or without
31891 + * modification, provided that redistributions of source code must retain this
31892 + * notice. You may not view, use, disclose, copy or distribute this file or
31893 + * any information contained herein except pursuant to this license grant from
31894 + * Synopsys. If you do not agree with this notice, including the disclaimer
31895 + * below, then you are not authorized to use the Software.
31896 + *
31897 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31898 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31899 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31900 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31901 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31902 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31903 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31904 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31905 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31906 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31907 + * DAMAGE.
31908 + * ========================================================================== */
31909 +
31910 +#ifndef __DWC_OTG_DBG_H__
31911 +#define __DWC_OTG_DBG_H__
31912 +
31913 +/** @file
31914 + * This file defines debug levels.
31915 + * Debugging support vanishes in non-debug builds.
31916 + */
31917 +
31918 +/**
31919 + * The Debug Level bit-mask variable.
31920 + */
31921 +extern uint32_t g_dbg_lvl;
31922 +/**
31923 + * Set the Debug Level variable.
31924 + */
31925 +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
31926 +{
31927 +       uint32_t old = g_dbg_lvl;
31928 +       g_dbg_lvl = new;
31929 +       return old;
31930 +}
31931 +
31932 +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
31933 +#define DBG_CIL                (0x2)
31934 +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
31935 + * messages */
31936 +#define DBG_CILV       (0x20)
31937 +/**  When debug level has the DBG_PCD bit set, display PCD (Device) debug
31938 + *  messages */
31939 +#define DBG_PCD                (0x4)
31940 +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
31941 + * messages */
31942 +#define DBG_PCDV       (0x40)
31943 +/** When debug level has the DBG_HCD bit set, display Host debug messages */
31944 +#define DBG_HCD                (0x8)
31945 +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
31946 + * messages */
31947 +#define DBG_HCDV       (0x80)
31948 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
31949 + *  mode. */
31950 +#define DBG_HCD_URB    (0x800)
31951 +/** When debug level has the DBG_HCDI bit set, display host interrupt
31952 + *  messages. */
31953 +#define DBG_HCDI       (0x1000)
31954 +
31955 +/** When debug level has any bit set, display debug messages */
31956 +#define DBG_ANY                (0xFF)
31957 +
31958 +/** All debug messages off */
31959 +#define DBG_OFF                0
31960 +
31961 +/** Prefix string for DWC_DEBUG print macros. */
31962 +#define USB_DWC "DWC_otg: "
31963 +
31964 +/**
31965 + * Print a debug message when the Global debug level variable contains
31966 + * the bit defined in <code>lvl</code>.
31967 + *
31968 + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
31969 + * @param[in] x - like printf
31970 + *
31971 + *    Example:<p>
31972 + * <code>
31973 + *      DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
31974 + * </code>
31975 + * <br>
31976 + * results in:<br>
31977 + * <code>
31978 + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
31979 + * </code>
31980 + */
31981 +#ifdef DEBUG
31982 +
31983 +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
31984 +# define DWC_DEBUGP(x...)      DWC_DEBUGPL(DBG_ANY, x )
31985 +
31986 +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
31987 +
31988 +#else
31989 +
31990 +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
31991 +# define DWC_DEBUGP(x...)
31992 +
31993 +# define CHK_DEBUG_LEVEL(level) (0)
31994 +
31995 +#endif /*DEBUG*/
31996 +#endif
31997 --- /dev/null
31998 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
31999 @@ -0,0 +1,1700 @@
32000 +/* ==========================================================================
32001 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
32002 + * $Revision: #92 $
32003 + * $Date: 2012/08/10 $
32004 + * $Change: 2047372 $
32005 + *
32006 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32007 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32008 + * otherwise expressly agreed to in writing between Synopsys and you.
32009 + *
32010 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32011 + * any End User Software License Agreement or Agreement for Licensed Product
32012 + * with Synopsys or any supplement thereto. You are permitted to use and
32013 + * redistribute this Software in source and binary forms, with or without
32014 + * modification, provided that redistributions of source code must retain this
32015 + * notice. You may not view, use, disclose, copy or distribute this file or
32016 + * any information contained herein except pursuant to this license grant from
32017 + * Synopsys. If you do not agree with this notice, including the disclaimer
32018 + * below, then you are not authorized to use the Software.
32019 + *
32020 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32021 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32022 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32023 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32024 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32025 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32026 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32027 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32028 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32029 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32030 + * DAMAGE.
32031 + * ========================================================================== */
32032 +
32033 +/** @file
32034 + * The dwc_otg_driver module provides the initialization and cleanup entry
32035 + * points for the DWC_otg driver. This module will be dynamically installed
32036 + * after Linux is booted using the insmod command. When the module is
32037 + * installed, the dwc_otg_driver_init function is called. When the module is
32038 + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
32039 + *
32040 + * This module also defines a data structure for the dwc_otg_driver, which is
32041 + * used in conjunction with the standard ARM lm_device structure. These
32042 + * structures allow the OTG driver to comply with the standard Linux driver
32043 + * model in which devices and drivers are registered with a bus driver. This
32044 + * has the benefit that Linux can expose attributes of the driver and device
32045 + * in its special sysfs file system. Users can then read or write files in
32046 + * this file system to perform diagnostics on the driver components or the
32047 + * device.
32048 + */
32049 +
32050 +#include "dwc_otg_os_dep.h"
32051 +#include "dwc_os.h"
32052 +#include "dwc_otg_dbg.h"
32053 +#include "dwc_otg_driver.h"
32054 +#include "dwc_otg_attr.h"
32055 +#include "dwc_otg_core_if.h"
32056 +#include "dwc_otg_pcd_if.h"
32057 +#include "dwc_otg_hcd_if.h"
32058 +
32059 +#define DWC_DRIVER_VERSION     "3.00a 10-AUG-2012"
32060 +#define DWC_DRIVER_DESC                "HS OTG USB Controller driver"
32061 +
32062 +bool microframe_schedule=true;
32063 +
32064 +static const char dwc_driver_name[] = "dwc_otg";
32065 +
32066 +extern int pcd_init(
32067 +#ifdef LM_INTERFACE
32068 +                          struct lm_device *_dev
32069 +#elif  defined(PCI_INTERFACE)
32070 +                          struct pci_dev *_dev
32071 +#elif  defined(PLATFORM_INTERFACE)
32072 +       struct platform_device *dev
32073 +#endif
32074 +    );
32075 +extern int hcd_init(
32076 +#ifdef LM_INTERFACE
32077 +                          struct lm_device *_dev
32078 +#elif  defined(PCI_INTERFACE)
32079 +                          struct pci_dev *_dev
32080 +#elif  defined(PLATFORM_INTERFACE)
32081 +       struct platform_device *dev
32082 +#endif
32083 +    );
32084 +
32085 +extern int pcd_remove(
32086 +#ifdef LM_INTERFACE
32087 +                            struct lm_device *_dev
32088 +#elif  defined(PCI_INTERFACE)
32089 +                            struct pci_dev *_dev
32090 +#elif  defined(PLATFORM_INTERFACE)
32091 +       struct platform_device *_dev
32092 +#endif
32093 +    );
32094 +
32095 +extern void hcd_remove(
32096 +#ifdef LM_INTERFACE
32097 +                             struct lm_device *_dev
32098 +#elif  defined(PCI_INTERFACE)
32099 +                             struct pci_dev *_dev
32100 +#elif  defined(PLATFORM_INTERFACE)
32101 +       struct platform_device *_dev
32102 +#endif
32103 +    );
32104 +
32105 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
32106 +
32107 +/*-------------------------------------------------------------------------*/
32108 +/* Encapsulate the module parameter settings */
32109 +
32110 +struct dwc_otg_driver_module_params {
32111 +       int32_t opt;
32112 +       int32_t otg_cap;
32113 +       int32_t dma_enable;
32114 +       int32_t dma_desc_enable;
32115 +       int32_t dma_burst_size;
32116 +       int32_t speed;
32117 +       int32_t host_support_fs_ls_low_power;
32118 +       int32_t host_ls_low_power_phy_clk;
32119 +       int32_t enable_dynamic_fifo;
32120 +       int32_t data_fifo_size;
32121 +       int32_t dev_rx_fifo_size;
32122 +       int32_t dev_nperio_tx_fifo_size;
32123 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
32124 +       int32_t host_rx_fifo_size;
32125 +       int32_t host_nperio_tx_fifo_size;
32126 +       int32_t host_perio_tx_fifo_size;
32127 +       int32_t max_transfer_size;
32128 +       int32_t max_packet_count;
32129 +       int32_t host_channels;
32130 +       int32_t dev_endpoints;
32131 +       int32_t phy_type;
32132 +       int32_t phy_utmi_width;
32133 +       int32_t phy_ulpi_ddr;
32134 +       int32_t phy_ulpi_ext_vbus;
32135 +       int32_t i2c_enable;
32136 +       int32_t ulpi_fs_ls;
32137 +       int32_t ts_dline;
32138 +       int32_t en_multiple_tx_fifo;
32139 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
32140 +       uint32_t thr_ctl;
32141 +       uint32_t tx_thr_length;
32142 +       uint32_t rx_thr_length;
32143 +       int32_t pti_enable;
32144 +       int32_t mpi_enable;
32145 +       int32_t lpm_enable;
32146 +       int32_t ic_usb_cap;
32147 +       int32_t ahb_thr_ratio;
32148 +       int32_t power_down;
32149 +       int32_t reload_ctl;
32150 +       int32_t dev_out_nak;
32151 +       int32_t cont_on_bna;
32152 +       int32_t ahb_single;
32153 +       int32_t otg_ver;
32154 +       int32_t adp_enable;
32155 +};
32156 +
32157 +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
32158 +       .opt = -1,
32159 +       .otg_cap = -1,
32160 +       .dma_enable = -1,
32161 +       .dma_desc_enable = -1,
32162 +       .dma_burst_size = -1,
32163 +       .speed = -1,
32164 +       .host_support_fs_ls_low_power = -1,
32165 +       .host_ls_low_power_phy_clk = -1,
32166 +       .enable_dynamic_fifo = -1,
32167 +       .data_fifo_size = -1,
32168 +       .dev_rx_fifo_size = -1,
32169 +       .dev_nperio_tx_fifo_size = -1,
32170 +       .dev_perio_tx_fifo_size = {
32171 +                                  /* dev_perio_tx_fifo_size_1 */
32172 +                                  -1,
32173 +                                  -1,
32174 +                                  -1,
32175 +                                  -1,
32176 +                                  -1,
32177 +                                  -1,
32178 +                                  -1,
32179 +                                  -1,
32180 +                                  -1,
32181 +                                  -1,
32182 +                                  -1,
32183 +                                  -1,
32184 +                                  -1,
32185 +                                  -1,
32186 +                                  -1
32187 +                                  /* 15 */
32188 +                                  },
32189 +       .host_rx_fifo_size = -1,
32190 +       .host_nperio_tx_fifo_size = -1,
32191 +       .host_perio_tx_fifo_size = -1,
32192 +       .max_transfer_size = -1,
32193 +       .max_packet_count = -1,
32194 +       .host_channels = -1,
32195 +       .dev_endpoints = -1,
32196 +       .phy_type = -1,
32197 +       .phy_utmi_width = -1,
32198 +       .phy_ulpi_ddr = -1,
32199 +       .phy_ulpi_ext_vbus = -1,
32200 +       .i2c_enable = -1,
32201 +       .ulpi_fs_ls = -1,
32202 +       .ts_dline = -1,
32203 +       .en_multiple_tx_fifo = -1,
32204 +       .dev_tx_fifo_size = {
32205 +                            /* dev_tx_fifo_size */
32206 +                            -1,
32207 +                            -1,
32208 +                            -1,
32209 +                            -1,
32210 +                            -1,
32211 +                            -1,
32212 +                            -1,
32213 +                            -1,
32214 +                            -1,
32215 +                            -1,
32216 +                            -1,
32217 +                            -1,
32218 +                            -1,
32219 +                            -1,
32220 +                            -1
32221 +                            /* 15 */
32222 +                            },
32223 +       .thr_ctl = -1,
32224 +       .tx_thr_length = -1,
32225 +       .rx_thr_length = -1,
32226 +       .pti_enable = -1,
32227 +       .mpi_enable = -1,
32228 +       .lpm_enable = 0,
32229 +       .ic_usb_cap = -1,
32230 +       .ahb_thr_ratio = -1,
32231 +       .power_down = -1,
32232 +       .reload_ctl = -1,
32233 +       .dev_out_nak = -1,
32234 +       .cont_on_bna = -1,
32235 +       .ahb_single = -1,
32236 +       .otg_ver = -1,
32237 +       .adp_enable = -1,
32238 +};
32239 +
32240 +/**
32241 + * This function shows the Driver Version.
32242 + */
32243 +static ssize_t version_show(struct device_driver *dev, char *buf)
32244 +{
32245 +       return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
32246 +                       DWC_DRIVER_VERSION);
32247 +}
32248 +
32249 +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
32250 +
32251 +/**
32252 + * Global Debug Level Mask.
32253 + */
32254 +uint32_t g_dbg_lvl = 0;                /* OFF */
32255 +
32256 +/**
32257 + * This function shows the driver Debug Level.
32258 + */
32259 +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
32260 +{
32261 +       return sprintf(buf, "0x%0x\n", g_dbg_lvl);
32262 +}
32263 +
32264 +/**
32265 + * This function stores the driver Debug Level.
32266 + */
32267 +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
32268 +                              size_t count)
32269 +{
32270 +       g_dbg_lvl = simple_strtoul(buf, NULL, 16);
32271 +       return count;
32272 +}
32273 +
32274 +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
32275 +                  dbg_level_store);
32276 +
32277 +/**
32278 + * This function is called during module intialization
32279 + * to pass module parameters to the DWC_OTG CORE.
32280 + */
32281 +static int set_parameters(dwc_otg_core_if_t * core_if)
32282 +{
32283 +       int retval = 0;
32284 +       int i;
32285 +
32286 +       if (dwc_otg_module_params.otg_cap != -1) {
32287 +               retval +=
32288 +                   dwc_otg_set_param_otg_cap(core_if,
32289 +                                             dwc_otg_module_params.otg_cap);
32290 +       }
32291 +       if (dwc_otg_module_params.dma_enable != -1) {
32292 +               retval +=
32293 +                   dwc_otg_set_param_dma_enable(core_if,
32294 +                                                dwc_otg_module_params.
32295 +                                                dma_enable);
32296 +       }
32297 +       if (dwc_otg_module_params.dma_desc_enable != -1) {
32298 +               retval +=
32299 +                   dwc_otg_set_param_dma_desc_enable(core_if,
32300 +                                                     dwc_otg_module_params.
32301 +                                                     dma_desc_enable);
32302 +       }
32303 +       if (dwc_otg_module_params.opt != -1) {
32304 +               retval +=
32305 +                   dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
32306 +       }
32307 +       if (dwc_otg_module_params.dma_burst_size != -1) {
32308 +               retval +=
32309 +                   dwc_otg_set_param_dma_burst_size(core_if,
32310 +                                                    dwc_otg_module_params.
32311 +                                                    dma_burst_size);
32312 +       }
32313 +       if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
32314 +               retval +=
32315 +                   dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
32316 +                                                                  dwc_otg_module_params.
32317 +                                                                  host_support_fs_ls_low_power);
32318 +       }
32319 +       if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
32320 +               retval +=
32321 +                   dwc_otg_set_param_enable_dynamic_fifo(core_if,
32322 +                                                         dwc_otg_module_params.
32323 +                                                         enable_dynamic_fifo);
32324 +       }
32325 +       if (dwc_otg_module_params.data_fifo_size != -1) {
32326 +               retval +=
32327 +                   dwc_otg_set_param_data_fifo_size(core_if,
32328 +                                                    dwc_otg_module_params.
32329 +                                                    data_fifo_size);
32330 +       }
32331 +       if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
32332 +               retval +=
32333 +                   dwc_otg_set_param_dev_rx_fifo_size(core_if,
32334 +                                                      dwc_otg_module_params.
32335 +                                                      dev_rx_fifo_size);
32336 +       }
32337 +       if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
32338 +               retval +=
32339 +                   dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
32340 +                                                             dwc_otg_module_params.
32341 +                                                             dev_nperio_tx_fifo_size);
32342 +       }
32343 +       if (dwc_otg_module_params.host_rx_fifo_size != -1) {
32344 +               retval +=
32345 +                   dwc_otg_set_param_host_rx_fifo_size(core_if,
32346 +                                                       dwc_otg_module_params.host_rx_fifo_size);
32347 +       }
32348 +       if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
32349 +               retval +=
32350 +                   dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
32351 +                                                              dwc_otg_module_params.
32352 +                                                              host_nperio_tx_fifo_size);
32353 +       }
32354 +       if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
32355 +               retval +=
32356 +                   dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
32357 +                                                             dwc_otg_module_params.
32358 +                                                             host_perio_tx_fifo_size);
32359 +       }
32360 +       if (dwc_otg_module_params.max_transfer_size != -1) {
32361 +               retval +=
32362 +                   dwc_otg_set_param_max_transfer_size(core_if,
32363 +                                                       dwc_otg_module_params.
32364 +                                                       max_transfer_size);
32365 +       }
32366 +       if (dwc_otg_module_params.max_packet_count != -1) {
32367 +               retval +=
32368 +                   dwc_otg_set_param_max_packet_count(core_if,
32369 +                                                      dwc_otg_module_params.
32370 +                                                      max_packet_count);
32371 +       }
32372 +       if (dwc_otg_module_params.host_channels != -1) {
32373 +               retval +=
32374 +                   dwc_otg_set_param_host_channels(core_if,
32375 +                                                   dwc_otg_module_params.
32376 +                                                   host_channels);
32377 +       }
32378 +       if (dwc_otg_module_params.dev_endpoints != -1) {
32379 +               retval +=
32380 +                   dwc_otg_set_param_dev_endpoints(core_if,
32381 +                                                   dwc_otg_module_params.
32382 +                                                   dev_endpoints);
32383 +       }
32384 +       if (dwc_otg_module_params.phy_type != -1) {
32385 +               retval +=
32386 +                   dwc_otg_set_param_phy_type(core_if,
32387 +                                              dwc_otg_module_params.phy_type);
32388 +       }
32389 +       if (dwc_otg_module_params.speed != -1) {
32390 +               retval +=
32391 +                   dwc_otg_set_param_speed(core_if,
32392 +                                           dwc_otg_module_params.speed);
32393 +       }
32394 +       if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
32395 +               retval +=
32396 +                   dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
32397 +                                                               dwc_otg_module_params.
32398 +                                                               host_ls_low_power_phy_clk);
32399 +       }
32400 +       if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
32401 +               retval +=
32402 +                   dwc_otg_set_param_phy_ulpi_ddr(core_if,
32403 +                                                  dwc_otg_module_params.
32404 +                                                  phy_ulpi_ddr);
32405 +       }
32406 +       if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
32407 +               retval +=
32408 +                   dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
32409 +                                                       dwc_otg_module_params.
32410 +                                                       phy_ulpi_ext_vbus);
32411 +       }
32412 +       if (dwc_otg_module_params.phy_utmi_width != -1) {
32413 +               retval +=
32414 +                   dwc_otg_set_param_phy_utmi_width(core_if,
32415 +                                                    dwc_otg_module_params.
32416 +                                                    phy_utmi_width);
32417 +       }
32418 +       if (dwc_otg_module_params.ulpi_fs_ls != -1) {
32419 +               retval +=
32420 +                   dwc_otg_set_param_ulpi_fs_ls(core_if,
32421 +                                                dwc_otg_module_params.ulpi_fs_ls);
32422 +       }
32423 +       if (dwc_otg_module_params.ts_dline != -1) {
32424 +               retval +=
32425 +                   dwc_otg_set_param_ts_dline(core_if,
32426 +                                              dwc_otg_module_params.ts_dline);
32427 +       }
32428 +       if (dwc_otg_module_params.i2c_enable != -1) {
32429 +               retval +=
32430 +                   dwc_otg_set_param_i2c_enable(core_if,
32431 +                                                dwc_otg_module_params.
32432 +                                                i2c_enable);
32433 +       }
32434 +       if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
32435 +               retval +=
32436 +                   dwc_otg_set_param_en_multiple_tx_fifo(core_if,
32437 +                                                         dwc_otg_module_params.
32438 +                                                         en_multiple_tx_fifo);
32439 +       }
32440 +       for (i = 0; i < 15; i++) {
32441 +               if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
32442 +                       retval +=
32443 +                           dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
32444 +                                                                    dwc_otg_module_params.
32445 +                                                                    dev_perio_tx_fifo_size
32446 +                                                                    [i], i);
32447 +               }
32448 +       }
32449 +
32450 +       for (i = 0; i < 15; i++) {
32451 +               if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
32452 +                       retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
32453 +                                                                    dwc_otg_module_params.
32454 +                                                                    dev_tx_fifo_size
32455 +                                                                    [i], i);
32456 +               }
32457 +       }
32458 +       if (dwc_otg_module_params.thr_ctl != -1) {
32459 +               retval +=
32460 +                   dwc_otg_set_param_thr_ctl(core_if,
32461 +                                             dwc_otg_module_params.thr_ctl);
32462 +       }
32463 +       if (dwc_otg_module_params.mpi_enable != -1) {
32464 +               retval +=
32465 +                   dwc_otg_set_param_mpi_enable(core_if,
32466 +                                                dwc_otg_module_params.
32467 +                                                mpi_enable);
32468 +       }
32469 +       if (dwc_otg_module_params.pti_enable != -1) {
32470 +               retval +=
32471 +                   dwc_otg_set_param_pti_enable(core_if,
32472 +                                                dwc_otg_module_params.
32473 +                                                pti_enable);
32474 +       }
32475 +       if (dwc_otg_module_params.lpm_enable != -1) {
32476 +               retval +=
32477 +                   dwc_otg_set_param_lpm_enable(core_if,
32478 +                                                dwc_otg_module_params.
32479 +                                                lpm_enable);
32480 +       }
32481 +       if (dwc_otg_module_params.ic_usb_cap != -1) {
32482 +               retval +=
32483 +                   dwc_otg_set_param_ic_usb_cap(core_if,
32484 +                                                dwc_otg_module_params.
32485 +                                                ic_usb_cap);
32486 +       }
32487 +       if (dwc_otg_module_params.tx_thr_length != -1) {
32488 +               retval +=
32489 +                   dwc_otg_set_param_tx_thr_length(core_if,
32490 +                                                   dwc_otg_module_params.tx_thr_length);
32491 +       }
32492 +       if (dwc_otg_module_params.rx_thr_length != -1) {
32493 +               retval +=
32494 +                   dwc_otg_set_param_rx_thr_length(core_if,
32495 +                                                   dwc_otg_module_params.
32496 +                                                   rx_thr_length);
32497 +       }
32498 +       if (dwc_otg_module_params.ahb_thr_ratio != -1) {
32499 +               retval +=
32500 +                   dwc_otg_set_param_ahb_thr_ratio(core_if,
32501 +                                                   dwc_otg_module_params.ahb_thr_ratio);
32502 +       }
32503 +       if (dwc_otg_module_params.power_down != -1) {
32504 +               retval +=
32505 +                   dwc_otg_set_param_power_down(core_if,
32506 +                                                dwc_otg_module_params.power_down);
32507 +       }
32508 +       if (dwc_otg_module_params.reload_ctl != -1) {
32509 +               retval +=
32510 +                   dwc_otg_set_param_reload_ctl(core_if,
32511 +                                                dwc_otg_module_params.reload_ctl);
32512 +       }
32513 +
32514 +       if (dwc_otg_module_params.dev_out_nak != -1) {
32515 +               retval +=
32516 +                       dwc_otg_set_param_dev_out_nak(core_if,
32517 +                       dwc_otg_module_params.dev_out_nak);
32518 +       }
32519 +
32520 +       if (dwc_otg_module_params.cont_on_bna != -1) {
32521 +               retval +=
32522 +                       dwc_otg_set_param_cont_on_bna(core_if,
32523 +                       dwc_otg_module_params.cont_on_bna);
32524 +       }
32525 +
32526 +       if (dwc_otg_module_params.ahb_single != -1) {
32527 +               retval +=
32528 +                       dwc_otg_set_param_ahb_single(core_if,
32529 +                       dwc_otg_module_params.ahb_single);
32530 +       }
32531 +
32532 +       if (dwc_otg_module_params.otg_ver != -1) {
32533 +               retval +=
32534 +                   dwc_otg_set_param_otg_ver(core_if,
32535 +                                             dwc_otg_module_params.otg_ver);
32536 +       }
32537 +       if (dwc_otg_module_params.adp_enable != -1) {
32538 +               retval +=
32539 +                   dwc_otg_set_param_adp_enable(core_if,
32540 +                                                dwc_otg_module_params.
32541 +                                                adp_enable);
32542 +       }
32543 +       return retval;
32544 +}
32545 +
32546 +/**
32547 + * This function is the top level interrupt handler for the Common
32548 + * (Device and host modes) interrupts.
32549 + */
32550 +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
32551 +{
32552 +       int32_t retval = IRQ_NONE;
32553 +
32554 +       retval = dwc_otg_handle_common_intr(dev);
32555 +       if (retval != 0) {
32556 +               S3C2410X_CLEAR_EINTPEND();
32557 +       }
32558 +       return IRQ_RETVAL(retval);
32559 +}
32560 +
32561 +/**
32562 + * This function is called when a lm_device is unregistered with the
32563 + * dwc_otg_driver. This happens, for example, when the rmmod command is
32564 + * executed. The device may or may not be electrically present. If it is
32565 + * present, the driver stops device processing. Any resources used on behalf
32566 + * of this device are freed.
32567 + *
32568 + * @param _dev
32569 + */
32570 +#ifdef LM_INTERFACE
32571 +#define REM_RETVAL(n)
32572 +static void dwc_otg_driver_remove(      struct lm_device *_dev )
32573 +{       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
32574 +#elif  defined(PCI_INTERFACE)
32575 +#define REM_RETVAL(n)
32576 +static void dwc_otg_driver_remove(      struct pci_dev *_dev )
32577 +{      dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
32578 +#elif  defined(PLATFORM_INTERFACE)
32579 +#define REM_RETVAL(n) n
32580 +static int dwc_otg_driver_remove(        struct platform_device *_dev )
32581 +{       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
32582 +#endif
32583 +
32584 +       DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
32585 +
32586 +       if (!otg_dev) {
32587 +               /* Memory allocation for the dwc_otg_device failed. */
32588 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
32589 +                return REM_RETVAL(-ENOMEM);
32590 +       }
32591 +#ifndef DWC_DEVICE_ONLY
32592 +       if (otg_dev->hcd) {
32593 +               hcd_remove(_dev);
32594 +       } else {
32595 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
32596 +                return REM_RETVAL(-EINVAL);
32597 +       }
32598 +#endif
32599 +
32600 +#ifndef DWC_HOST_ONLY
32601 +       if (otg_dev->pcd) {
32602 +               pcd_remove(_dev);
32603 +       } else {
32604 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);
32605 +                return REM_RETVAL(-EINVAL);
32606 +       }
32607 +#endif
32608 +       /*
32609 +        * Free the IRQ
32610 +        */
32611 +       if (otg_dev->common_irq_installed) {
32612 +#ifdef PLATFORM_INTERFACE
32613 +               free_irq(platform_get_irq(_dev, 0), otg_dev);
32614 +#else
32615 +               free_irq(_dev->irq, otg_dev);
32616 +#endif
32617 +        } else {
32618 +               DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
32619 +               return REM_RETVAL(-ENXIO);
32620 +       }
32621 +
32622 +       if (otg_dev->core_if) {
32623 +               dwc_otg_cil_remove(otg_dev->core_if);
32624 +       } else {
32625 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);
32626 +               return REM_RETVAL(-ENXIO);
32627 +       }
32628 +
32629 +       /*
32630 +        * Remove the device attributes
32631 +        */
32632 +       dwc_otg_attr_remove(_dev);
32633 +
32634 +       /*
32635 +        * Return the memory.
32636 +        */
32637 +       if (otg_dev->os_dep.base) {
32638 +               iounmap(otg_dev->os_dep.base);
32639 +       }
32640 +       DWC_FREE(otg_dev);
32641 +
32642 +       /*
32643 +        * Clear the drvdata pointer.
32644 +        */
32645 +#ifdef LM_INTERFACE
32646 +       lm_set_drvdata(_dev, 0);
32647 +#elif defined(PCI_INTERFACE)
32648 +        release_mem_region(otg_dev->os_dep.rsrc_start,
32649 +                           otg_dev->os_dep.rsrc_len);
32650 +       pci_set_drvdata(_dev, 0);
32651 +#elif  defined(PLATFORM_INTERFACE)
32652 +        platform_set_drvdata(_dev, 0);
32653 +#endif
32654 +        return REM_RETVAL(0);
32655 +}
32656 +
32657 +/**
32658 + * This function is called when an lm_device is bound to a
32659 + * dwc_otg_driver. It creates the driver components required to
32660 + * control the device (CIL, HCD, and PCD) and it initializes the
32661 + * device. The driver components are stored in a dwc_otg_device
32662 + * structure. A reference to the dwc_otg_device is saved in the
32663 + * lm_device. This allows the driver to access the dwc_otg_device
32664 + * structure on subsequent calls to driver methods for this device.
32665 + *
32666 + * @param _dev Bus device
32667 + */
32668 +static int dwc_otg_driver_probe(
32669 +#ifdef LM_INTERFACE
32670 +                                      struct lm_device *_dev
32671 +#elif defined(PCI_INTERFACE)
32672 +                                      struct pci_dev *_dev,
32673 +                                      const struct pci_device_id *id
32674 +#elif  defined(PLATFORM_INTERFACE)
32675 +                                       struct platform_device *_dev
32676 +#endif
32677 +    )
32678 +{
32679 +       int retval = 0;
32680 +       dwc_otg_device_t *dwc_otg_device;
32681 +        int devirq;
32682 +
32683 +       dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
32684 +#ifdef LM_INTERFACE
32685 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
32686 +#elif defined(PCI_INTERFACE)
32687 +       if (!id) {
32688 +               DWC_ERROR("Invalid pci_device_id %p", id);
32689 +               return -EINVAL;
32690 +       }
32691 +
32692 +       if (!_dev || (pci_enable_device(_dev) < 0)) {
32693 +               DWC_ERROR("Invalid pci_device %p", _dev);
32694 +               return -ENODEV;
32695 +       }
32696 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
32697 +       /* other stuff needed as well? */
32698 +
32699 +#elif  defined(PLATFORM_INTERFACE)
32700 +       dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
32701 +                (unsigned)_dev->resource->start,
32702 +                (unsigned)(_dev->resource->end - _dev->resource->start));
32703 +#endif
32704 +
32705 +       dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
32706 +
32707 +       if (!dwc_otg_device) {
32708 +               dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
32709 +               return -ENOMEM;
32710 +       }
32711 +
32712 +       memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
32713 +       dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
32714 +
32715 +       /*
32716 +        * Map the DWC_otg Core memory into virtual address space.
32717 +        */
32718 +#ifdef LM_INTERFACE
32719 +       dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);
32720 +
32721 +       if (!dwc_otg_device->os_dep.base) {
32722 +               dev_err(&_dev->dev, "ioremap() failed\n");
32723 +               DWC_FREE(dwc_otg_device);
32724 +               return -ENOMEM;
32725 +       }
32726 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32727 +               (unsigned)dwc_otg_device->os_dep.base);
32728 +#elif defined(PCI_INTERFACE)
32729 +       _dev->current_state = PCI_D0;
32730 +       _dev->dev.power.power_state = PMSG_ON;
32731 +
32732 +       if (!_dev->irq) {
32733 +               DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",
32734 +                         pci_name(_dev));
32735 +               iounmap(dwc_otg_device->os_dep.base);
32736 +               DWC_FREE(dwc_otg_device);
32737 +               return -ENODEV;
32738 +       }
32739 +
32740 +       dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);
32741 +       dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);
32742 +       DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",
32743 +                   (unsigned)dwc_otg_device->os_dep.rsrc_start,
32744 +                   (unsigned)dwc_otg_device->os_dep.rsrc_len);
32745 +       if (!request_mem_region
32746 +           (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,
32747 +            "dwc_otg")) {
32748 +               dev_dbg(&_dev->dev, "error requesting memory\n");
32749 +               iounmap(dwc_otg_device->os_dep.base);
32750 +               DWC_FREE(dwc_otg_device);
32751 +               return -EFAULT;
32752 +       }
32753 +
32754 +       dwc_otg_device->os_dep.base =
32755 +           ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,
32756 +                           dwc_otg_device->os_dep.rsrc_len);
32757 +       if (dwc_otg_device->os_dep.base == NULL) {
32758 +               dev_dbg(&_dev->dev, "error mapping memory\n");
32759 +               release_mem_region(dwc_otg_device->os_dep.rsrc_start,
32760 +                                  dwc_otg_device->os_dep.rsrc_len);
32761 +               iounmap(dwc_otg_device->os_dep.base);
32762 +               DWC_FREE(dwc_otg_device);
32763 +               return -EFAULT;
32764 +       }
32765 +       dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",
32766 +               dwc_otg_device->os_dep.base);
32767 +       dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;
32768 +       dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",
32769 +               dwc_otg_device->os_dep.base);
32770 +       dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
32771 +               (unsigned)dwc_otg_device->os_dep.rsrc_start,
32772 +               dwc_otg_device->os_dep.base);
32773 +
32774 +       pci_set_master(_dev);
32775 +       pci_set_drvdata(_dev, dwc_otg_device);
32776 +#elif defined(PLATFORM_INTERFACE)
32777 +        DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
32778 +                    _dev->resource->start,
32779 +                    _dev->resource->end - _dev->resource->start + 1);
32780 +#if 1
32781 +        if (!request_mem_region(_dev->resource->start,
32782 +                                _dev->resource->end - _dev->resource->start + 1,
32783 +                                "dwc_otg")) {
32784 +          dev_dbg(&_dev->dev, "error reserving mapped memory\n");
32785 +          retval = -EFAULT;
32786 +          goto fail;
32787 +        }
32788 +
32789 +       dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
32790 +                                                      _dev->resource->end -
32791 +                                                      _dev->resource->start+1);
32792 +#else
32793 +        {
32794 +                struct map_desc desc = {
32795 +                    .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
32796 +                    .pfn     = __phys_to_pfn((unsigned)_dev->resource->start),
32797 +                    .length  = SZ_128K,
32798 +                    .type    = MT_DEVICE
32799 +                };
32800 +                iotable_init(&desc, 1);
32801 +                dwc_otg_device->os_dep.base = (void *)desc.virtual;
32802 +        }
32803 +#endif
32804 +       if (!dwc_otg_device->os_dep.base) {
32805 +               dev_err(&_dev->dev, "ioremap() failed\n");
32806 +               retval = -ENOMEM;
32807 +               goto fail;
32808 +       }
32809 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32810 +                (unsigned)dwc_otg_device->os_dep.base);
32811 +#endif
32812 +
32813 +       /*
32814 +        * Initialize driver data to point to the global DWC_otg
32815 +        * Device structure.
32816 +        */
32817 +#ifdef LM_INTERFACE
32818 +       lm_set_drvdata(_dev, dwc_otg_device);
32819 +#elif defined(PLATFORM_INTERFACE)
32820 +       platform_set_drvdata(_dev, dwc_otg_device);
32821 +#endif
32822 +       dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
32823 +
32824 +       dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
32825 +        DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
32826 +                    dwc_otg_device, dwc_otg_device->core_if);//GRAYG
32827 +
32828 +       if (!dwc_otg_device->core_if) {
32829 +               dev_err(&_dev->dev, "CIL initialization failed!\n");
32830 +               retval = -ENOMEM;
32831 +               goto fail;
32832 +       }
32833 +
32834 +       dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
32835 +       /*
32836 +        * Attempt to ensure this device is really a DWC_otg Controller.
32837 +        * Read and verify the SNPSID register contents. The value should be
32838 +        * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",
32839 +        * as in "OTG version 2.XX" or "OTG version 3.XX".
32840 +        */
32841 +
32842 +       if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=     0x4F542000) &&
32843 +               ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
32844 +               dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
32845 +                       dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
32846 +               retval = -EINVAL;
32847 +               goto fail;
32848 +       }
32849 +
32850 +       /*
32851 +        * Validate parameter values.
32852 +        */
32853 +       dev_dbg(&_dev->dev, "Calling set_parameters\n");
32854 +       if (set_parameters(dwc_otg_device->core_if)) {
32855 +               retval = -EINVAL;
32856 +               goto fail;
32857 +       }
32858 +
32859 +       /*
32860 +        * Create Device Attributes in sysfs
32861 +        */
32862 +       dev_dbg(&_dev->dev, "Calling attr_create\n");
32863 +       dwc_otg_attr_create(_dev);
32864 +
32865 +       /*
32866 +        * Disable the global interrupt until all the interrupt
32867 +        * handlers are installed.
32868 +        */
32869 +       dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
32870 +       dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
32871 +
32872 +       /*
32873 +        * Install the interrupt handler for the common interrupts before
32874 +        * enabling common interrupts in core_init below.
32875 +        */
32876 +
32877 +#if defined(PLATFORM_INTERFACE)
32878 +        devirq = platform_get_irq(_dev, 0);
32879 +#else
32880 +        devirq = _dev->irq;
32881 +#endif
32882 +       DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
32883 +                   devirq);
32884 +       dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
32885 +       retval = request_irq(devirq, dwc_otg_common_irq,
32886 +                             IRQF_SHARED,
32887 +                             "dwc_otg", dwc_otg_device);
32888 +       if (retval) {
32889 +               DWC_ERROR("request of irq%d failed\n", devirq);
32890 +               retval = -EBUSY;
32891 +               goto fail;
32892 +       } else {
32893 +               dwc_otg_device->common_irq_installed = 1;
32894 +       }
32895 +
32896 +#ifndef IRQF_TRIGGER_LOW
32897 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
32898 +       dev_dbg(&_dev->dev, "Calling set_irq_type\n");
32899 +       set_irq_type(devirq,
32900 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
32901 +                     IRQT_LOW
32902 +#else
32903 +                     IRQ_TYPE_LEVEL_LOW
32904 +#endif
32905 +                    );
32906 +#endif
32907 +#endif /*IRQF_TRIGGER_LOW*/
32908 +
32909 +       /*
32910 +        * Initialize the DWC_otg core.
32911 +        */
32912 +       dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
32913 +       dwc_otg_core_init(dwc_otg_device->core_if);
32914 +
32915 +#ifndef DWC_HOST_ONLY
32916 +       /*
32917 +        * Initialize the PCD
32918 +        */
32919 +       dev_dbg(&_dev->dev, "Calling pcd_init\n");
32920 +       retval = pcd_init(_dev);
32921 +       if (retval != 0) {
32922 +               DWC_ERROR("pcd_init failed\n");
32923 +               dwc_otg_device->pcd = NULL;
32924 +               goto fail;
32925 +       }
32926 +#endif
32927 +#ifndef DWC_DEVICE_ONLY
32928 +       /*
32929 +        * Initialize the HCD
32930 +        */
32931 +       dev_dbg(&_dev->dev, "Calling hcd_init\n");
32932 +       retval = hcd_init(_dev);
32933 +       if (retval != 0) {
32934 +               DWC_ERROR("hcd_init failed\n");
32935 +               dwc_otg_device->hcd = NULL;
32936 +               goto fail;
32937 +       }
32938 +#endif
32939 +        /* Recover from drvdata having been overwritten by hcd_init() */
32940 +#ifdef LM_INTERFACE
32941 +       lm_set_drvdata(_dev, dwc_otg_device);
32942 +#elif defined(PLATFORM_INTERFACE)
32943 +       platform_set_drvdata(_dev, dwc_otg_device);
32944 +#elif defined(PCI_INTERFACE)
32945 +       pci_set_drvdata(_dev, dwc_otg_device);
32946 +       dwc_otg_device->os_dep.pcidev = _dev;
32947 +#endif
32948 +
32949 +       /*
32950 +        * Enable the global interrupt after all the interrupt
32951 +        * handlers are installed if there is no ADP support else
32952 +        * perform initial actions required for Internal ADP logic.
32953 +        */
32954 +       if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
32955 +               dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
32956 +               dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
32957 +               dev_dbg(&_dev->dev, "Done\n");
32958 +       } else
32959 +               dwc_otg_adp_start(dwc_otg_device->core_if,
32960 +                                                       dwc_otg_is_host_mode(dwc_otg_device->core_if));
32961 +
32962 +       return 0;
32963 +
32964 +fail:
32965 +       dwc_otg_driver_remove(_dev);
32966 +       return retval;
32967 +}
32968 +
32969 +/**
32970 + * This structure defines the methods to be called by a bus driver
32971 + * during the lifecycle of a device on that bus. Both drivers and
32972 + * devices are registered with a bus driver. The bus driver matches
32973 + * devices to drivers based on information in the device and driver
32974 + * structures.
32975 + *
32976 + * The probe function is called when the bus driver matches a device
32977 + * to this driver. The remove function is called when a device is
32978 + * unregistered with the bus driver.
32979 + */
32980 +#ifdef LM_INTERFACE
32981 +static struct lm_driver dwc_otg_driver = {
32982 +       .drv = {.name = (char *)dwc_driver_name,},
32983 +       .probe = dwc_otg_driver_probe,
32984 +       .remove = dwc_otg_driver_remove,
32985 +        // 'suspend' and 'resume' absent
32986 +};
32987 +#elif defined(PCI_INTERFACE)
32988 +static const struct pci_device_id pci_ids[] = { {
32989 +                                                PCI_DEVICE(0x16c3, 0xabcd),
32990 +                                                .driver_data =
32991 +                                                (unsigned long)0xdeadbeef,
32992 +                                                }, { /* end: all zeroes */ }
32993 +};
32994 +
32995 +MODULE_DEVICE_TABLE(pci, pci_ids);
32996 +
32997 +/* pci driver glue; this is a "new style" PCI driver module */
32998 +static struct pci_driver dwc_otg_driver = {
32999 +       .name = "dwc_otg",
33000 +       .id_table = pci_ids,
33001 +
33002 +       .probe = dwc_otg_driver_probe,
33003 +       .remove = dwc_otg_driver_remove,
33004 +
33005 +       .driver = {
33006 +                  .name = (char *)dwc_driver_name,
33007 +                  },
33008 +};
33009 +#elif defined(PLATFORM_INTERFACE)
33010 +static struct platform_device_id platform_ids[] = {
33011 +        {
33012 +              .name = "bcm2708_usb",
33013 +              .driver_data = (kernel_ulong_t) 0xdeadbeef,
33014 +        },
33015 +        { /* end: all zeroes */ }
33016 +};
33017 +MODULE_DEVICE_TABLE(platform, platform_ids);
33018 +
33019 +static struct platform_driver dwc_otg_driver = {
33020 +       .driver = {
33021 +               .name = (char *)dwc_driver_name,
33022 +               },
33023 +        .id_table = platform_ids,
33024 +
33025 +       .probe = dwc_otg_driver_probe,
33026 +       .remove = dwc_otg_driver_remove,
33027 +        // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early'
33028 +};
33029 +#endif
33030 +
33031 +/**
33032 + * This function is called when the dwc_otg_driver is installed with the
33033 + * insmod command. It registers the dwc_otg_driver structure with the
33034 + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
33035 + * to be called. In addition, the bus driver will automatically expose
33036 + * attributes defined for the device and driver in the special sysfs file
33037 + * system.
33038 + *
33039 + * @return
33040 + */
33041 +static int __init dwc_otg_driver_init(void)
33042 +{
33043 +       int retval = 0;
33044 +       int error;
33045 +        struct device_driver *drv;
33046 +       printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
33047 +              DWC_DRIVER_VERSION,
33048 +#ifdef LM_INTERFACE
33049 +               "logicmodule");
33050 +       retval = lm_driver_register(&dwc_otg_driver);
33051 +        drv = &dwc_otg_driver.drv;
33052 +#elif defined(PCI_INTERFACE)
33053 +               "pci");
33054 +       retval = pci_register_driver(&dwc_otg_driver);
33055 +        drv = &dwc_otg_driver.driver;
33056 +#elif defined(PLATFORM_INTERFACE)
33057 +               "platform");
33058 +       retval = platform_driver_register(&dwc_otg_driver);
33059 +        drv = &dwc_otg_driver.driver;
33060 +#endif
33061 +       if (retval < 0) {
33062 +               printk(KERN_ERR "%s retval=%d\n", __func__, retval);
33063 +               return retval;
33064 +       }
33065 +
33066 +       error = driver_create_file(drv, &driver_attr_version);
33067 +#ifdef DEBUG
33068 +       error = driver_create_file(drv, &driver_attr_debuglevel);
33069 +#endif
33070 +       return retval;
33071 +}
33072 +
33073 +module_init(dwc_otg_driver_init);
33074 +
33075 +/**
33076 + * This function is called when the driver is removed from the kernel
33077 + * with the rmmod command. The driver unregisters itself with its bus
33078 + * driver.
33079 + *
33080 + */
33081 +static void __exit dwc_otg_driver_cleanup(void)
33082 +{
33083 +       printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
33084 +
33085 +#ifdef LM_INTERFACE
33086 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
33087 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
33088 +       lm_driver_unregister(&dwc_otg_driver);
33089 +#elif defined(PCI_INTERFACE)
33090 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33091 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33092 +       pci_unregister_driver(&dwc_otg_driver);
33093 +#elif defined(PLATFORM_INTERFACE)
33094 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33095 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33096 +       platform_driver_unregister(&dwc_otg_driver);
33097 +#endif
33098 +
33099 +       printk(KERN_INFO "%s module removed\n", dwc_driver_name);
33100 +}
33101 +
33102 +module_exit(dwc_otg_driver_cleanup);
33103 +
33104 +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
33105 +MODULE_AUTHOR("Synopsys Inc.");
33106 +MODULE_LICENSE("GPL");
33107 +
33108 +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
33109 +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
33110 +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
33111 +MODULE_PARM_DESC(opt, "OPT Mode");
33112 +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
33113 +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
33114 +
33115 +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
33116 +                  0444);
33117 +MODULE_PARM_DESC(dma_desc_enable,
33118 +                "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
33119 +
33120 +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
33121 +                  0444);
33122 +MODULE_PARM_DESC(dma_burst_size,
33123 +                "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
33124 +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
33125 +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
33126 +module_param_named(host_support_fs_ls_low_power,
33127 +                  dwc_otg_module_params.host_support_fs_ls_low_power, int,
33128 +                  0444);
33129 +MODULE_PARM_DESC(host_support_fs_ls_low_power,
33130 +                "Support Low Power w/FS or LS 0=Support 1=Don't Support");
33131 +module_param_named(host_ls_low_power_phy_clk,
33132 +                  dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
33133 +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
33134 +                "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
33135 +module_param_named(enable_dynamic_fifo,
33136 +                  dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
33137 +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
33138 +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
33139 +                  0444);
33140 +MODULE_PARM_DESC(data_fifo_size,
33141 +                "Total number of words in the data FIFO memory 32-32768");
33142 +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
33143 +                  int, 0444);
33144 +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33145 +module_param_named(dev_nperio_tx_fifo_size,
33146 +                  dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
33147 +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
33148 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33149 +module_param_named(dev_perio_tx_fifo_size_1,
33150 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
33151 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
33152 +                "Number of words in the periodic Tx FIFO 4-768");
33153 +module_param_named(dev_perio_tx_fifo_size_2,
33154 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
33155 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
33156 +                "Number of words in the periodic Tx FIFO 4-768");
33157 +module_param_named(dev_perio_tx_fifo_size_3,
33158 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
33159 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
33160 +                "Number of words in the periodic Tx FIFO 4-768");
33161 +module_param_named(dev_perio_tx_fifo_size_4,
33162 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
33163 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
33164 +                "Number of words in the periodic Tx FIFO 4-768");
33165 +module_param_named(dev_perio_tx_fifo_size_5,
33166 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
33167 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
33168 +                "Number of words in the periodic Tx FIFO 4-768");
33169 +module_param_named(dev_perio_tx_fifo_size_6,
33170 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
33171 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
33172 +                "Number of words in the periodic Tx FIFO 4-768");
33173 +module_param_named(dev_perio_tx_fifo_size_7,
33174 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
33175 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
33176 +                "Number of words in the periodic Tx FIFO 4-768");
33177 +module_param_named(dev_perio_tx_fifo_size_8,
33178 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
33179 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
33180 +                "Number of words in the periodic Tx FIFO 4-768");
33181 +module_param_named(dev_perio_tx_fifo_size_9,
33182 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
33183 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
33184 +                "Number of words in the periodic Tx FIFO 4-768");
33185 +module_param_named(dev_perio_tx_fifo_size_10,
33186 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
33187 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
33188 +                "Number of words in the periodic Tx FIFO 4-768");
33189 +module_param_named(dev_perio_tx_fifo_size_11,
33190 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
33191 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
33192 +                "Number of words in the periodic Tx FIFO 4-768");
33193 +module_param_named(dev_perio_tx_fifo_size_12,
33194 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
33195 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
33196 +                "Number of words in the periodic Tx FIFO 4-768");
33197 +module_param_named(dev_perio_tx_fifo_size_13,
33198 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
33199 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
33200 +                "Number of words in the periodic Tx FIFO 4-768");
33201 +module_param_named(dev_perio_tx_fifo_size_14,
33202 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
33203 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
33204 +                "Number of words in the periodic Tx FIFO 4-768");
33205 +module_param_named(dev_perio_tx_fifo_size_15,
33206 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
33207 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
33208 +                "Number of words in the periodic Tx FIFO 4-768");
33209 +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
33210 +                  int, 0444);
33211 +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33212 +module_param_named(host_nperio_tx_fifo_size,
33213 +                  dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
33214 +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
33215 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33216 +module_param_named(host_perio_tx_fifo_size,
33217 +                  dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
33218 +MODULE_PARM_DESC(host_perio_tx_fifo_size,
33219 +                "Number of words in the host periodic Tx FIFO 16-32768");
33220 +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
33221 +                  int, 0444);
33222 +/** @todo Set the max to 512K, modify checks */
33223 +MODULE_PARM_DESC(max_transfer_size,
33224 +                "The maximum transfer size supported in bytes 2047-65535");
33225 +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
33226 +                  int, 0444);
33227 +MODULE_PARM_DESC(max_packet_count,
33228 +                "The maximum number of packets in a transfer 15-511");
33229 +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
33230 +                  0444);
33231 +MODULE_PARM_DESC(host_channels,
33232 +                "The number of host channel registers to use 1-16");
33233 +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
33234 +                  0444);
33235 +MODULE_PARM_DESC(dev_endpoints,
33236 +                "The number of endpoints in addition to EP0 available for device mode 1-15");
33237 +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
33238 +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
33239 +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
33240 +                  0444);
33241 +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
33242 +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
33243 +MODULE_PARM_DESC(phy_ulpi_ddr,
33244 +                "ULPI at double or single data rate 0=Single 1=Double");
33245 +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
33246 +                  int, 0444);
33247 +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
33248 +                "ULPI PHY using internal or external vbus 0=Internal");
33249 +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
33250 +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
33251 +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
33252 +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
33253 +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
33254 +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
33255 +module_param_named(debug, g_dbg_lvl, int, 0444);
33256 +MODULE_PARM_DESC(debug, "");
33257 +
33258 +module_param_named(en_multiple_tx_fifo,
33259 +                  dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
33260 +MODULE_PARM_DESC(en_multiple_tx_fifo,
33261 +                "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
33262 +module_param_named(dev_tx_fifo_size_1,
33263 +                  dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
33264 +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
33265 +module_param_named(dev_tx_fifo_size_2,
33266 +                  dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
33267 +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
33268 +module_param_named(dev_tx_fifo_size_3,
33269 +                  dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
33270 +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
33271 +module_param_named(dev_tx_fifo_size_4,
33272 +                  dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
33273 +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
33274 +module_param_named(dev_tx_fifo_size_5,
33275 +                  dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
33276 +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
33277 +module_param_named(dev_tx_fifo_size_6,
33278 +                  dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
33279 +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
33280 +module_param_named(dev_tx_fifo_size_7,
33281 +                  dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
33282 +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
33283 +module_param_named(dev_tx_fifo_size_8,
33284 +                  dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
33285 +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
33286 +module_param_named(dev_tx_fifo_size_9,
33287 +                  dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
33288 +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
33289 +module_param_named(dev_tx_fifo_size_10,
33290 +                  dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
33291 +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
33292 +module_param_named(dev_tx_fifo_size_11,
33293 +                  dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
33294 +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
33295 +module_param_named(dev_tx_fifo_size_12,
33296 +                  dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
33297 +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
33298 +module_param_named(dev_tx_fifo_size_13,
33299 +                  dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
33300 +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
33301 +module_param_named(dev_tx_fifo_size_14,
33302 +                  dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
33303 +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
33304 +module_param_named(dev_tx_fifo_size_15,
33305 +                  dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
33306 +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
33307 +
33308 +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
33309 +MODULE_PARM_DESC(thr_ctl,
33310 +                "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
33311 +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
33312 +                  0444);
33313 +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
33314 +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
33315 +                  0444);
33316 +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
33317 +
33318 +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
33319 +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
33320 +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
33321 +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
33322 +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
33323 +MODULE_PARM_DESC(ic_usb_cap,
33324 +                "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
33325 +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,
33326 +                  0444);
33327 +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
33328 +module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);
33329 +MODULE_PARM_DESC(power_down, "Power Down Mode");
33330 +module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);
33331 +MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
33332 +module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
33333 +MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
33334 +module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
33335 +MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
33336 +module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
33337 +MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
33338 +module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
33339 +MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
33340 +module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
33341 +MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
33342 +module_param(microframe_schedule, bool, 0444);
33343 +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
33344 +
33345 +/** @page "Module Parameters"
33346 + *
33347 + * The following parameters may be specified when starting the module.
33348 + * These parameters define how the DWC_otg controller should be
33349 + * configured. Parameter values are passed to the CIL initialization
33350 + * function dwc_otg_cil_init
33351 + *
33352 + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
33353 + *
33354 +
33355 + <table>
33356 + <tr><td>Parameter Name</td><td>Meaning</td></tr>
33357 +
33358 + <tr>
33359 + <td>otg_cap</td>
33360 + <td>Specifies the OTG capabilities. The driver will automatically detect the
33361 + value for this parameter if none is specified.
33362 + - 0: HNP and SRP capable (default, if available)
33363 + - 1: SRP Only capable
33364 + - 2: No HNP/SRP capable
33365 + </td></tr>
33366 +
33367 + <tr>
33368 + <td>dma_enable</td>
33369 + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
33370 + The driver will automatically detect the value for this parameter if none is
33371 + specified.
33372 + - 0: Slave
33373 + - 1: DMA (default, if available)
33374 + </td></tr>
33375 +
33376 + <tr>
33377 + <td>dma_burst_size</td>
33378 + <td>The DMA Burst size (applicable only for External DMA Mode).
33379 + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
33380 + </td></tr>
33381 +
33382 + <tr>
33383 + <td>speed</td>
33384 + <td>Specifies the maximum speed of operation in host and device mode. The
33385 + actual speed depends on the speed of the attached device and the value of
33386 + phy_type.
33387 + - 0: High Speed (default)
33388 + - 1: Full Speed
33389 + </td></tr>
33390 +
33391 + <tr>
33392 + <td>host_support_fs_ls_low_power</td>
33393 + <td>Specifies whether low power mode is supported when attached to a Full
33394 + Speed or Low Speed device in host mode.
33395 + - 0: Don't support low power mode (default)
33396 + - 1: Support low power mode
33397 + </td></tr>
33398 +
33399 + <tr>
33400 + <td>host_ls_low_power_phy_clk</td>
33401 + <td>Specifies the PHY clock rate in low power mode when connected to a Low
33402 + Speed device in host mode. This parameter is applicable only if
33403 + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
33404 + - 0: 48 MHz (default)
33405 + - 1: 6 MHz
33406 + </td></tr>
33407 +
33408 + <tr>
33409 + <td>enable_dynamic_fifo</td>
33410 + <td> Specifies whether FIFOs may be resized by the driver software.
33411 + - 0: Use cC FIFO size parameters
33412 + - 1: Allow dynamic FIFO sizing (default)
33413 + </td></tr>
33414 +
33415 + <tr>
33416 + <td>data_fifo_size</td>
33417 + <td>Total number of 4-byte words in the data FIFO memory. This memory
33418 + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
33419 + - Values: 32 to 32768 (default 8192)
33420 +
33421 + Note: The total FIFO memory depth in the FPGA configuration is 8192.
33422 + </td></tr>
33423 +
33424 + <tr>
33425 + <td>dev_rx_fifo_size</td>
33426 + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
33427 + FIFO sizing is enabled.
33428 + - Values: 16 to 32768 (default 1064)
33429 + </td></tr>
33430 +
33431 + <tr>
33432 + <td>dev_nperio_tx_fifo_size</td>
33433 + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
33434 + dynamic FIFO sizing is enabled.
33435 + - Values: 16 to 32768 (default 1024)
33436 + </td></tr>
33437 +
33438 + <tr>
33439 + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
33440 + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
33441 + when dynamic FIFO sizing is enabled.
33442 + - Values: 4 to 768 (default 256)
33443 + </td></tr>
33444 +
33445 + <tr>
33446 + <td>host_rx_fifo_size</td>
33447 + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
33448 + sizing is enabled.
33449 + - Values: 16 to 32768 (default 1024)
33450 + </td></tr>
33451 +
33452 + <tr>
33453 + <td>host_nperio_tx_fifo_size</td>
33454 + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
33455 + dynamic FIFO sizing is enabled in the core.
33456 + - Values: 16 to 32768 (default 1024)
33457 + </td></tr>
33458 +
33459 + <tr>
33460 + <td>host_perio_tx_fifo_size</td>
33461 + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
33462 + sizing is enabled.
33463 + - Values: 16 to 32768 (default 1024)
33464 + </td></tr>
33465 +
33466 + <tr>
33467 + <td>max_transfer_size</td>
33468 + <td>The maximum transfer size supported in bytes.
33469 + - Values: 2047 to 65,535 (default 65,535)
33470 + </td></tr>
33471 +
33472 + <tr>
33473 + <td>max_packet_count</td>
33474 + <td>The maximum number of packets in a transfer.
33475 + - Values: 15 to 511 (default 511)
33476 + </td></tr>
33477 +
33478 + <tr>
33479 + <td>host_channels</td>
33480 + <td>The number of host channel registers to use.
33481 + - Values: 1 to 16 (default 12)
33482 +
33483 + Note: The FPGA configuration supports a maximum of 12 host channels.
33484 + </td></tr>
33485 +
33486 + <tr>
33487 + <td>dev_endpoints</td>
33488 + <td>The number of endpoints in addition to EP0 available for device mode
33489 + operations.
33490 + - Values: 1 to 15 (default 6 IN and OUT)
33491 +
33492 + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
33493 + addition to EP0.
33494 + </td></tr>
33495 +
33496 + <tr>
33497 + <td>phy_type</td>
33498 + <td>Specifies the type of PHY interface to use. By default, the driver will
33499 + automatically detect the phy_type.
33500 + - 0: Full Speed
33501 + - 1: UTMI+ (default, if available)
33502 + - 2: ULPI
33503 + </td></tr>
33504 +
33505 + <tr>
33506 + <td>phy_utmi_width</td>
33507 + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
33508 + phy_type of UTMI+. Also, this parameter is applicable only if the
33509 + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
33510 + core has been configured to work at either data path width.
33511 + - Values: 8 or 16 bits (default 16)
33512 + </td></tr>
33513 +
33514 + <tr>
33515 + <td>phy_ulpi_ddr</td>
33516 + <td>Specifies whether the ULPI operates at double or single data rate. This
33517 + parameter is only applicable if phy_type is ULPI.
33518 + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
33519 + - 1: double data rate ULPI interface with 4 bit wide data bus
33520 + </td></tr>
33521 +
33522 + <tr>
33523 + <td>i2c_enable</td>
33524 + <td>Specifies whether to use the I2C interface for full speed PHY. This
33525 + parameter is only applicable if PHY_TYPE is FS.
33526 + - 0: Disabled (default)
33527 + - 1: Enabled
33528 + </td></tr>
33529 +
33530 + <tr>
33531 + <td>ulpi_fs_ls</td>
33532 + <td>Specifies whether to use ULPI FS/LS mode only.
33533 + - 0: Disabled (default)
33534 + - 1: Enabled
33535 + </td></tr>
33536 +
33537 + <tr>
33538 + <td>ts_dline</td>
33539 + <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.
33540 + - 0: Disabled (default)
33541 + - 1: Enabled
33542 + </td></tr>
33543 +
33544 + <tr>
33545 + <td>en_multiple_tx_fifo</td>
33546 + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
33547 + The driver will automatically detect the value for this parameter if none is
33548 + specified.
33549 + - 0: Disabled
33550 + - 1: Enabled (default, if available)
33551 + </td></tr>
33552 +
33553 + <tr>
33554 + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
33555 + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
33556 + when dynamic FIFO sizing is enabled.
33557 + - Values: 4 to 768 (default 256)
33558 + </td></tr>
33559 +
33560 + <tr>
33561 + <td>tx_thr_length</td>
33562 + <td>Transmit Threshold length in 32 bit double words
33563 + - Values: 8 to 128 (default 64)
33564 + </td></tr>
33565 +
33566 + <tr>
33567 + <td>rx_thr_length</td>
33568 + <td>Receive Threshold length in 32 bit double words
33569 + - Values: 8 to 128 (default 64)
33570 + </td></tr>
33571 +
33572 +<tr>
33573 + <td>thr_ctl</td>
33574 + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
33575 + this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
33576 + Rx transfers accordingly.
33577 + The driver will automatically detect the value for this parameter if none is
33578 + specified.
33579 + - Values: 0 to 7 (default 0)
33580 + Bit values indicate:
33581 + - 0: Thresholding disabled
33582 + - 1: Thresholding enabled
33583 + </td></tr>
33584 +
33585 +<tr>
33586 + <td>dma_desc_enable</td>
33587 + <td>Specifies whether to enable Descriptor DMA mode.
33588 + The driver will automatically detect the value for this parameter if none is
33589 + specified.
33590 + - 0: Descriptor DMA disabled
33591 + - 1: Descriptor DMA (default, if available)
33592 + </td></tr>
33593 +
33594 +<tr>
33595 + <td>mpi_enable</td>
33596 + <td>Specifies whether to enable MPI enhancement mode.
33597 + The driver will automatically detect the value for this parameter if none is
33598 + specified.
33599 + - 0: MPI disabled (default)
33600 + - 1: MPI enable
33601 + </td></tr>
33602 +
33603 +<tr>
33604 + <td>pti_enable</td>
33605 + <td>Specifies whether to enable PTI enhancement support.
33606 + The driver will automatically detect the value for this parameter if none is
33607 + specified.
33608 + - 0: PTI disabled (default)
33609 + - 1: PTI enable
33610 + </td></tr>
33611 +
33612 +<tr>
33613 + <td>lpm_enable</td>
33614 + <td>Specifies whether to enable LPM support.
33615 + The driver will automatically detect the value for this parameter if none is
33616 + specified.
33617 + - 0: LPM disabled
33618 + - 1: LPM enable (default, if available)
33619 + </td></tr>
33620 +
33621 +<tr>
33622 + <td>ic_usb_cap</td>
33623 + <td>Specifies whether to enable IC_USB capability.
33624 + The driver will automatically detect the value for this parameter if none is
33625 + specified.
33626 + - 0: IC_USB disabled (default, if available)
33627 + - 1: IC_USB enable
33628 + </td></tr>
33629 +
33630 +<tr>
33631 + <td>ahb_thr_ratio</td>
33632 + <td>Specifies AHB Threshold ratio.
33633 + - Values: 0 to 3 (default 0)
33634 + </td></tr>
33635 +
33636 +<tr>
33637 + <td>power_down</td>
33638 + <td>Specifies Power Down(Hibernation) Mode.
33639 + The driver will automatically detect the value for this parameter if none is
33640 + specified.
33641 + - 0: Power Down disabled (default)
33642 + - 2: Power Down enabled
33643 + </td></tr>
33644 +
33645 + <tr>
33646 + <td>reload_ctl</td>
33647 + <td>Specifies whether dynamic reloading of the HFIR register is allowed during
33648 + run time. The driver will automatically detect the value for this parameter if
33649 + none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0
33650 + the core might misbehave.
33651 + - 0: Reload Control disabled (default)
33652 + - 1: Reload Control enabled
33653 + </td></tr>
33654 +
33655 + <tr>
33656 + <td>dev_out_nak</td>
33657 + <td>Specifies whether  Device OUT NAK enhancement enabled or no.
33658 + The driver will automatically detect the value for this parameter if
33659 + none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33660 + - 0: The core does not set NAK after Bulk OUT transfer complete (default)
33661 + - 1: The core sets NAK after Bulk OUT transfer complete
33662 + </td></tr>
33663 +
33664 + <tr>
33665 + <td>cont_on_bna</td>
33666 + <td>Specifies whether Enable Continue on BNA enabled or no.
33667 + After receiving BNA interrupt the core disables the endpoint,when the
33668 + endpoint is re-enabled by the application the
33669 + - 0: Core starts processing from the DOEPDMA descriptor (default)
33670 + - 1: Core starts processing from the descriptor which received the BNA.
33671 + This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33672 + </td></tr>
33673 +
33674 + <tr>
33675 + <td>ahb_single</td>
33676 + <td>This bit when programmed supports SINGLE transfers for remainder data
33677 + in a transfer for DMA mode of operation.
33678 + - 0: The remainder data will be sent using INCR burst size (default)
33679 + - 1: The remainder data will be sent using SINGLE burst size.
33680 + </td></tr>
33681 +
33682 +<tr>
33683 + <td>adp_enable</td>
33684 + <td>Specifies whether ADP feature is enabled.
33685 + The driver will automatically detect the value for this parameter if none is
33686 + specified.
33687 + - 0: ADP feature disabled (default)
33688 + - 1: ADP feature enabled
33689 + </td></tr>
33690 +
33691 +  <tr>
33692 + <td>otg_ver</td>
33693 + <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
33694 + USB OTG device.
33695 + - 0: OTG 2.0 support disabled (default)
33696 + - 1: OTG 2.0 support enabled
33697 + </td></tr>
33698 +
33699 +*/
33700 --- /dev/null
33701 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33702 @@ -0,0 +1,86 @@
33703 +/* ==========================================================================
33704 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
33705 + * $Revision: #19 $
33706 + * $Date: 2010/11/15 $
33707 + * $Change: 1627671 $
33708 + *
33709 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33710 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33711 + * otherwise expressly agreed to in writing between Synopsys and you.
33712 + *
33713 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33714 + * any End User Software License Agreement or Agreement for Licensed Product
33715 + * with Synopsys or any supplement thereto. You are permitted to use and
33716 + * redistribute this Software in source and binary forms, with or without
33717 + * modification, provided that redistributions of source code must retain this
33718 + * notice. You may not view, use, disclose, copy or distribute this file or
33719 + * any information contained herein except pursuant to this license grant from
33720 + * Synopsys. If you do not agree with this notice, including the disclaimer
33721 + * below, then you are not authorized to use the Software.
33722 + *
33723 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33724 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33725 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33726 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33727 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33728 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33729 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33730 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33731 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33732 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33733 + * DAMAGE.
33734 + * ========================================================================== */
33735 +
33736 +#ifndef __DWC_OTG_DRIVER_H__
33737 +#define __DWC_OTG_DRIVER_H__
33738 +
33739 +/** @file
33740 + * This file contains the interface to the Linux driver.
33741 + */
33742 +#include "dwc_otg_os_dep.h"
33743 +#include "dwc_otg_core_if.h"
33744 +
33745 +/* Type declarations */
33746 +struct dwc_otg_pcd;
33747 +struct dwc_otg_hcd;
33748 +
33749 +/**
33750 + * This structure is a wrapper that encapsulates the driver components used to
33751 + * manage a single DWC_otg controller.
33752 + */
33753 +typedef struct dwc_otg_device {
33754 +       /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE
33755 +        * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD
33756 +        * require this. */
33757 +       struct os_dependent os_dep;
33758 +
33759 +       /** Pointer to the core interface structure. */
33760 +       dwc_otg_core_if_t *core_if;
33761 +
33762 +       /** Pointer to the PCD structure. */
33763 +       struct dwc_otg_pcd *pcd;
33764 +
33765 +       /** Pointer to the HCD structure. */
33766 +       struct dwc_otg_hcd *hcd;
33767 +
33768 +       /** Flag to indicate whether the common IRQ handler is installed. */
33769 +       uint8_t common_irq_installed;
33770 +
33771 +} dwc_otg_device_t;
33772 +
33773 +/*We must clear S3C24XX_EINTPEND external interrupt register
33774 + * because after clearing in this register trigerred IRQ from
33775 + * H/W core in kernel interrupt can be occured again before OTG
33776 + * handlers clear all IRQ sources of Core registers because of
33777 + * timing latencies and Low Level IRQ Type.
33778 + */
33779 +#ifdef CONFIG_MACH_IPMATE
33780 +#define  S3C2410X_CLEAR_EINTPEND()   \
33781 +do { \
33782 +       __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
33783 +} while (0)
33784 +#else
33785 +#define  S3C2410X_CLEAR_EINTPEND()   do { } while (0)
33786 +#endif
33787 +
33788 +#endif
33789 --- /dev/null
33790 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33791 @@ -0,0 +1,3479 @@
33792 +
33793 +/* ==========================================================================
33794 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
33795 + * $Revision: #104 $
33796 + * $Date: 2011/10/24 $
33797 + * $Change: 1871159 $
33798 + *
33799 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33800 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33801 + * otherwise expressly agreed to in writing between Synopsys and you.
33802 + *
33803 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33804 + * any End User Software License Agreement or Agreement for Licensed Product
33805 + * with Synopsys or any supplement thereto. You are permitted to use and
33806 + * redistribute this Software in source and binary forms, with or without
33807 + * modification, provided that redistributions of source code must retain this
33808 + * notice. You may not view, use, disclose, copy or distribute this file or
33809 + * any information contained herein except pursuant to this license grant from
33810 + * Synopsys. If you do not agree with this notice, including the disclaimer
33811 + * below, then you are not authorized to use the Software.
33812 + *
33813 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33814 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33815 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33816 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33817 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33818 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33819 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33820 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33821 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33822 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33823 + * DAMAGE.
33824 + * ========================================================================== */
33825 +#ifndef DWC_DEVICE_ONLY
33826 +
33827 +/** @file
33828 + * This file implements HCD Core. All code in this file is portable and doesn't
33829 + * use any OS specific functions.
33830 + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
33831 + * header file.
33832 + */
33833 +
33834 +#include "dwc_otg_hcd.h"
33835 +#include "dwc_otg_regs.h"
33836 +
33837 +extern bool microframe_schedule;
33838 +
33839 +//#define DEBUG_HOST_CHANNELS
33840 +#ifdef DEBUG_HOST_CHANNELS
33841 +static int last_sel_trans_num_per_scheduled = 0;
33842 +static int last_sel_trans_num_nonper_scheduled = 0;
33843 +static int last_sel_trans_num_avail_hc_at_start = 0;
33844 +static int last_sel_trans_num_avail_hc_at_end = 0;
33845 +#endif /* DEBUG_HOST_CHANNELS */
33846 +
33847 +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
33848 +{
33849 +       return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
33850 +}
33851 +
33852 +/**
33853 + * Connection timeout function.  An OTG host is required to display a
33854 + * message if the device does not connect within 10 seconds.
33855 + */
33856 +void dwc_otg_hcd_connect_timeout(void *ptr)
33857 +{
33858 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
33859 +       DWC_PRINTF("Connect Timeout\n");
33860 +       __DWC_ERROR("Device Not Connected/Responding\n");
33861 +}
33862 +
33863 +#if defined(DEBUG)
33864 +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
33865 +{
33866 +       if (qh->channel != NULL) {
33867 +               dwc_hc_t *hc = qh->channel;
33868 +               dwc_list_link_t *item;
33869 +               dwc_otg_qh_t *qh_item;
33870 +               int num_channels = hcd->core_if->core_params->host_channels;
33871 +               int i;
33872 +
33873 +               dwc_otg_hc_regs_t *hc_regs;
33874 +               hcchar_data_t hcchar;
33875 +               hcsplt_data_t hcsplt;
33876 +               hctsiz_data_t hctsiz;
33877 +               uint32_t hcdma;
33878 +
33879 +               hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
33880 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
33881 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
33882 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
33883 +               hcdma = DWC_READ_REG32(&hc_regs->hcdma);
33884 +
33885 +               DWC_PRINTF("  Assigned to channel %p:\n", hc);
33886 +               DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
33887 +                          hcsplt.d32);
33888 +               DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
33889 +                          hcdma);
33890 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
33891 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
33892 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
33893 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
33894 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
33895 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
33896 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
33897 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
33898 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
33899 +               DWC_PRINTF("    qh: %p\n", hc->qh);
33900 +               DWC_PRINTF("  NP inactive sched:\n");
33901 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
33902 +                       qh_item =
33903 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
33904 +                       DWC_PRINTF("    %p\n", qh_item);
33905 +               }
33906 +               DWC_PRINTF("  NP active sched:\n");
33907 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
33908 +                       qh_item =
33909 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
33910 +                       DWC_PRINTF("    %p\n", qh_item);
33911 +               }
33912 +               DWC_PRINTF("  Channels: \n");
33913 +               for (i = 0; i < num_channels; i++) {
33914 +                       dwc_hc_t *hc = hcd->hc_ptr_array[i];
33915 +                       DWC_PRINTF("    %2d: %p\n", i, hc);
33916 +               }
33917 +       }
33918 +}
33919 +#else
33920 +#define dump_channel_info(hcd, qh)
33921 +#endif /* DEBUG */
33922 +
33923 +/**
33924 + * Work queue function for starting the HCD when A-Cable is connected.
33925 + * The hcd_start() must be called in a process context.
33926 + */
33927 +static void hcd_start_func(void *_vp)
33928 +{
33929 +       dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
33930 +
33931 +       DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
33932 +       if (hcd) {
33933 +               hcd->fops->start(hcd);
33934 +       }
33935 +}
33936 +
33937 +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
33938 +{
33939 +#ifdef DEBUG
33940 +       int i;
33941 +       int num_channels = hcd->core_if->core_params->host_channels;
33942 +       for (i = 0; i < num_channels; i++) {
33943 +               DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
33944 +       }
33945 +#endif
33946 +}
33947 +
33948 +static void del_timers(dwc_otg_hcd_t * hcd)
33949 +{
33950 +       del_xfer_timers(hcd);
33951 +       DWC_TIMER_CANCEL(hcd->conn_timer);
33952 +}
33953 +
33954 +/**
33955 + * Processes all the URBs in a single list of QHs. Completes them with
33956 + * -ETIMEDOUT and frees the QTD.
33957 + */
33958 +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
33959 +{
33960 +       dwc_list_link_t *qh_item;
33961 +       dwc_otg_qh_t *qh;
33962 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
33963 +
33964 +       DWC_LIST_FOREACH(qh_item, qh_list) {
33965 +               qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
33966 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
33967 +                                        &qh->qtd_list, qtd_list_entry) {
33968 +                       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
33969 +                       if (qtd->urb != NULL) {
33970 +                               hcd->fops->complete(hcd, qtd->urb->priv,
33971 +                                                   qtd->urb, -DWC_E_TIMEOUT);
33972 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
33973 +                       }
33974 +
33975 +               }
33976 +       }
33977 +}
33978 +
33979 +/**
33980 + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
33981 + * and periodic schedules. The QTD associated with each URB is removed from
33982 + * the schedule and freed. This function may be called when a disconnect is
33983 + * detected or when the HCD is being stopped.
33984 + */
33985 +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
33986 +{
33987 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
33988 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
33989 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
33990 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
33991 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
33992 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
33993 +}
33994 +
33995 +/**
33996 + * Start the connection timer.  An OTG host is required to display a
33997 + * message if the device does not connect within 10 seconds.  The
33998 + * timer is deleted if a port connect interrupt occurs before the
33999 + * timer expires.
34000 + */
34001 +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
34002 +{
34003 +       DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
34004 +}
34005 +
34006 +/**
34007 + * HCD Callback function for disconnect of the HCD.
34008 + *
34009 + * @param p void pointer to the <code>struct usb_hcd</code>
34010 + */
34011 +static int32_t dwc_otg_hcd_session_start_cb(void *p)
34012 +{
34013 +       dwc_otg_hcd_t *dwc_otg_hcd;
34014 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34015 +       dwc_otg_hcd = p;
34016 +       dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
34017 +       return 1;
34018 +}
34019 +
34020 +/**
34021 + * HCD Callback function for starting the HCD when A-Cable is
34022 + * connected.
34023 + *
34024 + * @param p void pointer to the <code>struct usb_hcd</code>
34025 + */
34026 +static int32_t dwc_otg_hcd_start_cb(void *p)
34027 +{
34028 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34029 +       dwc_otg_core_if_t *core_if;
34030 +       hprt0_data_t hprt0;
34031 +
34032 +       core_if = dwc_otg_hcd->core_if;
34033 +
34034 +       if (core_if->op_state == B_HOST) {
34035 +               /*
34036 +                * Reset the port.  During a HNP mode switch the reset
34037 +                * needs to occur within 1ms and have a duration of at
34038 +                * least 50ms.
34039 +                */
34040 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
34041 +               hprt0.b.prtrst = 1;
34042 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34043 +       }
34044 +       DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
34045 +                                  hcd_start_func, dwc_otg_hcd, 50,
34046 +                                  "start hcd");
34047 +
34048 +       return 1;
34049 +}
34050 +
34051 +/**
34052 + * HCD Callback function for disconnect of the HCD.
34053 + *
34054 + * @param p void pointer to the <code>struct usb_hcd</code>
34055 + */
34056 +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
34057 +{
34058 +       gintsts_data_t intr;
34059 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34060 +
34061 +       /*
34062 +        * Set status flags for the hub driver.
34063 +        */
34064 +       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
34065 +       dwc_otg_hcd->flags.b.port_connect_status = 0;
34066 +
34067 +       /*
34068 +        * Shutdown any transfers in process by clearing the Tx FIFO Empty
34069 +        * interrupt mask and status bits and disabling subsequent host
34070 +        * channel interrupts.
34071 +        */
34072 +       intr.d32 = 0;
34073 +       intr.b.nptxfempty = 1;
34074 +       intr.b.ptxfempty = 1;
34075 +       intr.b.hcintr = 1;
34076 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
34077 +                        intr.d32, 0);
34078 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
34079 +                        intr.d32, 0);
34080 +
34081 +       del_timers(dwc_otg_hcd);
34082 +
34083 +       /*
34084 +        * Turn off the vbus power only if the core has transitioned to device
34085 +        * mode. If still in host mode, need to keep power on to detect a
34086 +        * reconnection.
34087 +        */
34088 +       if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
34089 +               if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
34090 +                       hprt0_data_t hprt0 = {.d32 = 0 };
34091 +                       DWC_PRINTF("Disconnect: PortPower off\n");
34092 +                       hprt0.b.prtpwr = 0;
34093 +                       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
34094 +                                       hprt0.d32);
34095 +               }
34096 +
34097 +               dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
34098 +       }
34099 +
34100 +       /* Respond with an error status to all URBs in the schedule. */
34101 +       kill_all_urbs(dwc_otg_hcd);
34102 +
34103 +       if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
34104 +               /* Clean up any host channels that were in use. */
34105 +               int num_channels;
34106 +               int i;
34107 +               dwc_hc_t *channel;
34108 +               dwc_otg_hc_regs_t *hc_regs;
34109 +               hcchar_data_t hcchar;
34110 +
34111 +               num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
34112 +
34113 +               if (!dwc_otg_hcd->core_if->dma_enable) {
34114 +                       /* Flush out any channel requests in slave mode. */
34115 +                       for (i = 0; i < num_channels; i++) {
34116 +                               channel = dwc_otg_hcd->hc_ptr_array[i];
34117 +                               if (DWC_CIRCLEQ_EMPTY_ENTRY
34118 +                                   (channel, hc_list_entry)) {
34119 +                                       hc_regs =
34120 +                                           dwc_otg_hcd->core_if->
34121 +                                           host_if->hc_regs[i];
34122 +                                       hcchar.d32 =
34123 +                                           DWC_READ_REG32(&hc_regs->hcchar);
34124 +                                       if (hcchar.b.chen) {
34125 +                                               hcchar.b.chen = 0;
34126 +                                               hcchar.b.chdis = 1;
34127 +                                               hcchar.b.epdir = 0;
34128 +                                               DWC_WRITE_REG32
34129 +                                                   (&hc_regs->hcchar,
34130 +                                                    hcchar.d32);
34131 +                                       }
34132 +                               }
34133 +                       }
34134 +               }
34135 +
34136 +               for (i = 0; i < num_channels; i++) {
34137 +                       channel = dwc_otg_hcd->hc_ptr_array[i];
34138 +                       if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
34139 +                               hc_regs =
34140 +                                   dwc_otg_hcd->core_if->host_if->hc_regs[i];
34141 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34142 +                               if (hcchar.b.chen) {
34143 +                                       /* Halt the channel. */
34144 +                                       hcchar.b.chdis = 1;
34145 +                                       DWC_WRITE_REG32(&hc_regs->hcchar,
34146 +                                                       hcchar.d32);
34147 +                               }
34148 +
34149 +                               dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
34150 +                                                  channel);
34151 +                               DWC_CIRCLEQ_INSERT_TAIL
34152 +                                   (&dwc_otg_hcd->free_hc_list, channel,
34153 +                                    hc_list_entry);
34154 +                               /*
34155 +                                * Added for Descriptor DMA to prevent channel double cleanup
34156 +                                * in release_channel_ddma(). Which called from ep_disable
34157 +                                * when device disconnect.
34158 +                                */
34159 +                               channel->qh = NULL;
34160 +                       }
34161 +               }
34162 +       }
34163 +
34164 +       if (dwc_otg_hcd->fops->disconnect) {
34165 +               dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
34166 +       }
34167 +
34168 +       return 1;
34169 +}
34170 +
34171 +/**
34172 + * HCD Callback function for stopping the HCD.
34173 + *
34174 + * @param p void pointer to the <code>struct usb_hcd</code>
34175 + */
34176 +static int32_t dwc_otg_hcd_stop_cb(void *p)
34177 +{
34178 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34179 +
34180 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34181 +       dwc_otg_hcd_stop(dwc_otg_hcd);
34182 +       return 1;
34183 +}
34184 +
34185 +#ifdef CONFIG_USB_DWC_OTG_LPM
34186 +/**
34187 + * HCD Callback function for sleep of HCD.
34188 + *
34189 + * @param p void pointer to the <code>struct usb_hcd</code>
34190 + */
34191 +static int dwc_otg_hcd_sleep_cb(void *p)
34192 +{
34193 +       dwc_otg_hcd_t *hcd = p;
34194 +
34195 +       dwc_otg_hcd_free_hc_from_lpm(hcd);
34196 +
34197 +       return 0;
34198 +}
34199 +#endif
34200 +
34201 +/**
34202 + * HCD Callback function for Remote Wakeup.
34203 + *
34204 + * @param p void pointer to the <code>struct usb_hcd</code>
34205 + */
34206 +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
34207 +{
34208 +       dwc_otg_hcd_t *hcd = p;
34209 +
34210 +       if (hcd->core_if->lx_state == DWC_OTG_L2) {
34211 +               hcd->flags.b.port_suspend_change = 1;
34212 +       }
34213 +#ifdef CONFIG_USB_DWC_OTG_LPM
34214 +       else {
34215 +               hcd->flags.b.port_l1_change = 1;
34216 +       }
34217 +#endif
34218 +       return 0;
34219 +}
34220 +
34221 +/**
34222 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
34223 + * stopped.
34224 + */
34225 +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
34226 +{
34227 +       hprt0_data_t hprt0 = {.d32 = 0 };
34228 +
34229 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
34230 +
34231 +       /*
34232 +        * The root hub should be disconnected before this function is called.
34233 +        * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
34234 +        * and the QH lists (via ..._hcd_endpoint_disable).
34235 +        */
34236 +
34237 +       /* Turn off all host-specific interrupts. */
34238 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34239 +
34240 +       /* Turn off the vbus power */
34241 +       DWC_PRINTF("PortPower off\n");
34242 +       hprt0.b.prtpwr = 0;
34243 +       DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
34244 +       dwc_mdelay(1);
34245 +}
34246 +
34247 +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
34248 +                           dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
34249 +                           int atomic_alloc)
34250 +{
34251 +       dwc_irqflags_t flags;
34252 +       int retval = 0;
34253 +       dwc_otg_qtd_t *qtd;
34254 +       gintmsk_data_t intr_mask = {.d32 = 0 };
34255 +
34256 +#ifdef DEBUG /* integrity checks (Broadcom) */
34257 +       if (NULL == hcd->core_if) {
34258 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
34259 +               /* No longer connected. */
34260 +               return -DWC_E_INVALID;
34261 +       }
34262 +#endif
34263 +       if (!hcd->flags.b.port_connect_status) {
34264 +               /* No longer connected. */
34265 +               DWC_ERROR("Not connected\n");
34266 +               return -DWC_E_NO_DEVICE;
34267 +       }
34268 +
34269 +       qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
34270 +       if (qtd == NULL) {
34271 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
34272 +               return -DWC_E_NO_MEMORY;
34273 +       }
34274 +#ifdef DEBUG /* integrity checks (Broadcom) */
34275 +       if (qtd->urb == NULL) {
34276 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
34277 +               return -DWC_E_NO_MEMORY;
34278 +       }
34279 +       if (qtd->urb->priv == NULL) {
34280 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
34281 +               return -DWC_E_NO_MEMORY;
34282 +       }
34283 +#endif
34284 +       retval =
34285 +           dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
34286 +            // creates a new queue in ep_handle if it doesn't exist already
34287 +       if (retval < 0) {
34288 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
34289 +                         "Error status %d\n", retval);
34290 +               dwc_otg_hcd_qtd_free(qtd);
34291 +       } else {
34292 +               qtd->qh = *ep_handle;
34293 +       }
34294 +       intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
34295 +       if (!intr_mask.b.sofintr && retval == 0) {
34296 +               dwc_otg_transaction_type_e tr_type;
34297 +               if ((qtd->qh->ep_type == UE_BULK)
34298 +                   && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
34299 +                       /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
34300 +                       return 0;
34301 +               }
34302 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34303 +               tr_type = dwc_otg_hcd_select_transactions(hcd);
34304 +               if (tr_type != DWC_OTG_TRANSACTION_NONE) {
34305 +                       dwc_otg_hcd_queue_transactions(hcd, tr_type);
34306 +               }
34307 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34308 +       }
34309 +
34310 +       return retval;
34311 +}
34312 +
34313 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
34314 +                           dwc_otg_hcd_urb_t * dwc_otg_urb)
34315 +{
34316 +       dwc_otg_qh_t *qh;
34317 +       dwc_otg_qtd_t *urb_qtd;
34318 +
34319 +#ifdef DEBUG /* integrity checks (Broadcom) */
34320 +
34321 +       if (hcd == NULL) {
34322 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
34323 +               return -DWC_E_INVALID;
34324 +       }
34325 +       if (dwc_otg_urb == NULL) {
34326 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
34327 +               return -DWC_E_INVALID;
34328 +       }
34329 +       if (dwc_otg_urb->qtd == NULL) {
34330 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
34331 +               return -DWC_E_INVALID;
34332 +       }
34333 +       urb_qtd = dwc_otg_urb->qtd;
34334 +       if (urb_qtd->qh == NULL) {
34335 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
34336 +               return -DWC_E_INVALID;
34337 +       }
34338 +#else
34339 +       urb_qtd = dwc_otg_urb->qtd;
34340 +#endif
34341 +       qh = urb_qtd->qh;
34342 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
34343 +               if (urb_qtd->in_process) {
34344 +                       dump_channel_info(hcd, qh);
34345 +               }
34346 +       }
34347 +#ifdef DEBUG /* integrity checks (Broadcom) */
34348 +       if (hcd->core_if == NULL) {
34349 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
34350 +               return -DWC_E_INVALID;
34351 +       }
34352 +#endif
34353 +       if (urb_qtd->in_process && qh->channel) {
34354 +               /* The QTD is in process (it has been assigned to a channel). */
34355 +               if (hcd->flags.b.port_connect_status) {
34356 +                       /*
34357 +                        * If still connected (i.e. in host mode), halt the
34358 +                        * channel so it can be used for other transfers. If
34359 +                        * no longer connected, the host registers can't be
34360 +                        * written to halt the channel since the core is in
34361 +                        * device mode.
34362 +                        */
34363 +                       dwc_otg_hc_halt(hcd->core_if, qh->channel,
34364 +                                       DWC_OTG_HC_XFER_URB_DEQUEUE);
34365 +               }
34366 +       }
34367 +
34368 +       /*
34369 +        * Free the QTD and clean up the associated QH. Leave the QH in the
34370 +        * schedule if it has any remaining QTDs.
34371 +        */
34372 +
34373 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
34374 +                    "delete %sQueue handler\n",
34375 +                    hcd->core_if->dma_desc_enable?"DMA ":"");
34376 +       if (!hcd->core_if->dma_desc_enable) {
34377 +               uint8_t b = urb_qtd->in_process;
34378 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34379 +               if (b) {
34380 +                       dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
34381 +                       qh->channel = NULL;
34382 +               } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
34383 +                       dwc_otg_hcd_qh_remove(hcd, qh);
34384 +               }
34385 +       } else {
34386 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34387 +       }
34388 +       return 0;
34389 +}
34390 +
34391 +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
34392 +                                int retry)
34393 +{
34394 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34395 +       int retval = 0;
34396 +       dwc_irqflags_t flags;
34397 +
34398 +       if (retry < 0) {
34399 +               retval = -DWC_E_INVALID;
34400 +               goto done;
34401 +       }
34402 +
34403 +       if (!qh) {
34404 +               retval = -DWC_E_INVALID;
34405 +               goto done;
34406 +       }
34407 +
34408 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34409 +
34410 +       while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
34411 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34412 +               retry--;
34413 +               dwc_msleep(5);
34414 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34415 +       }
34416 +
34417 +       dwc_otg_hcd_qh_remove(hcd, qh);
34418 +
34419 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34420 +       /*
34421 +        * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
34422 +        * and qh_free to prevent stack dump on DWC_DMA_FREE() with
34423 +        * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
34424 +        * and dwc_otg_hcd_frame_list_alloc().
34425 +        */
34426 +       dwc_otg_hcd_qh_free(hcd, qh);
34427 +
34428 +done:
34429 +       return retval;
34430 +}
34431 +
34432 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
34433 +int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
34434 +{
34435 +       int retval = 0;
34436 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34437 +       if (!qh)
34438 +               return -DWC_E_INVALID;
34439 +
34440 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
34441 +       return retval;
34442 +}
34443 +#endif
34444 +
34445 +/**
34446 + * HCD Callback structure for handling mode switching.
34447 + */
34448 +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
34449 +       .start = dwc_otg_hcd_start_cb,
34450 +       .stop = dwc_otg_hcd_stop_cb,
34451 +       .disconnect = dwc_otg_hcd_disconnect_cb,
34452 +       .session_start = dwc_otg_hcd_session_start_cb,
34453 +       .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
34454 +#ifdef CONFIG_USB_DWC_OTG_LPM
34455 +       .sleep = dwc_otg_hcd_sleep_cb,
34456 +#endif
34457 +       .p = 0,
34458 +};
34459 +
34460 +/**
34461 + * Reset tasklet function
34462 + */
34463 +static void reset_tasklet_func(void *data)
34464 +{
34465 +       dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
34466 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
34467 +       hprt0_data_t hprt0;
34468 +
34469 +       DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
34470 +
34471 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
34472 +       hprt0.b.prtrst = 1;
34473 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34474 +       dwc_mdelay(60);
34475 +
34476 +       hprt0.b.prtrst = 0;
34477 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34478 +       dwc_otg_hcd->flags.b.port_reset_change = 1;
34479 +}
34480 +
34481 +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34482 +{
34483 +       dwc_list_link_t *item;
34484 +       dwc_otg_qh_t *qh;
34485 +       dwc_irqflags_t flags;
34486 +
34487 +       if (!qh_list->next) {
34488 +               /* The list hasn't been initialized yet. */
34489 +               return;
34490 +       }
34491 +       /*
34492 +        * Hold spinlock here. Not needed in that case if bellow
34493 +        * function is being called from ISR
34494 +        */
34495 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34496 +       /* Ensure there are no QTDs or URBs left. */
34497 +       kill_urbs_in_qh_list(hcd, qh_list);
34498 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34499 +
34500 +       DWC_LIST_FOREACH(item, qh_list) {
34501 +               qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34502 +               dwc_otg_hcd_qh_remove_and_free(hcd, qh);
34503 +       }
34504 +}
34505 +
34506 +/**
34507 + * Exit from Hibernation if Host did not detect SRP from connected SRP capable
34508 + * Device during SRP time by host power up.
34509 + */
34510 +void dwc_otg_hcd_power_up(void *ptr)
34511 +{
34512 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
34513 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
34514 +
34515 +       DWC_PRINTF("%s called\n", __FUNCTION__);
34516 +
34517 +       if (!core_if->hibernation_suspend) {
34518 +               DWC_PRINTF("Already exited from Hibernation\n");
34519 +               return;
34520 +       }
34521 +
34522 +       /* Switch on the voltage to the core */
34523 +       gpwrdn.b.pwrdnswtch = 1;
34524 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34525 +       dwc_udelay(10);
34526 +
34527 +       /* Reset the core */
34528 +       gpwrdn.d32 = 0;
34529 +       gpwrdn.b.pwrdnrstn = 1;
34530 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34531 +       dwc_udelay(10);
34532 +
34533 +       /* Disable power clamps */
34534 +       gpwrdn.d32 = 0;
34535 +       gpwrdn.b.pwrdnclmp = 1;
34536 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34537 +
34538 +       /* Remove reset the core signal */
34539 +       gpwrdn.d32 = 0;
34540 +       gpwrdn.b.pwrdnrstn = 1;
34541 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
34542 +       dwc_udelay(10);
34543 +
34544 +       /* Disable PMU interrupt */
34545 +       gpwrdn.d32 = 0;
34546 +       gpwrdn.b.pmuintsel = 1;
34547 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34548 +
34549 +       core_if->hibernation_suspend = 0;
34550 +
34551 +       /* Disable PMU */
34552 +       gpwrdn.d32 = 0;
34553 +       gpwrdn.b.pmuactv = 1;
34554 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34555 +       dwc_udelay(10);
34556 +
34557 +       /* Enable VBUS */
34558 +       gpwrdn.d32 = 0;
34559 +       gpwrdn.b.dis_vbus = 1;
34560 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34561 +
34562 +       core_if->op_state = A_HOST;
34563 +       dwc_otg_core_init(core_if);
34564 +       dwc_otg_enable_global_interrupts(core_if);
34565 +       cil_hcd_start(core_if);
34566 +}
34567 +
34568 +/**
34569 + * Frees secondary storage associated with the dwc_otg_hcd structure contained
34570 + * in the struct usb_hcd field.
34571 + */
34572 +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
34573 +{
34574 +       int i;
34575 +
34576 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
34577 +
34578 +       del_timers(dwc_otg_hcd);
34579 +
34580 +       /* Free memory for QH/QTD lists */
34581 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
34582 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
34583 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
34584 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
34585 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
34586 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
34587 +
34588 +       /* Free memory for the host channels. */
34589 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
34590 +               dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
34591 +
34592 +#ifdef DEBUG
34593 +               if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
34594 +                       DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
34595 +               }
34596 +#endif
34597 +               if (hc != NULL) {
34598 +                       DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
34599 +                                   i, hc);
34600 +                       DWC_FREE(hc);
34601 +               }
34602 +       }
34603 +
34604 +       if (dwc_otg_hcd->core_if->dma_enable) {
34605 +               if (dwc_otg_hcd->status_buf_dma) {
34606 +                       DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
34607 +                                    dwc_otg_hcd->status_buf,
34608 +                                    dwc_otg_hcd->status_buf_dma);
34609 +               }
34610 +       } else if (dwc_otg_hcd->status_buf != NULL) {
34611 +               DWC_FREE(dwc_otg_hcd->status_buf);
34612 +       }
34613 +       DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
34614 +       /* Set core_if's lock pointer to NULL */
34615 +       dwc_otg_hcd->core_if->lock = NULL;
34616 +
34617 +       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
34618 +       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
34619 +
34620 +#ifdef DWC_DEV_SRPCAP
34621 +       if (dwc_otg_hcd->core_if->power_down == 2 &&
34622 +           dwc_otg_hcd->core_if->pwron_timer) {
34623 +               DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
34624 +       }
34625 +#endif
34626 +       DWC_FREE(dwc_otg_hcd);
34627 +}
34628 +
34629 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
34630 +
34631 +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
34632 +{
34633 +       int retval = 0;
34634 +       int num_channels;
34635 +       int i;
34636 +       dwc_hc_t *channel;
34637 +
34638 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
34639 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->lock);
34640 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->channel_lock);
34641 +#else
34642 +       hcd->lock = DWC_SPINLOCK_ALLOC();
34643 +       hcd->channel_lock = DWC_SPINLOCK_ALLOC();
34644 +#endif
34645 +        DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
34646 +                    hcd, core_if);
34647 +       if (!hcd->lock) {
34648 +               DWC_ERROR("Could not allocate lock for pcd");
34649 +               DWC_FREE(hcd);
34650 +               retval = -DWC_E_NO_MEMORY;
34651 +               goto out;
34652 +       }
34653 +       hcd->core_if = core_if;
34654 +
34655 +       /* Register the HCD CIL Callbacks */
34656 +       dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
34657 +                                          &hcd_cil_callbacks, hcd);
34658 +
34659 +       /* Initialize the non-periodic schedule. */
34660 +       DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
34661 +       DWC_LIST_INIT(&hcd->non_periodic_sched_active);
34662 +
34663 +       /* Initialize the periodic schedule. */
34664 +       DWC_LIST_INIT(&hcd->periodic_sched_inactive);
34665 +       DWC_LIST_INIT(&hcd->periodic_sched_ready);
34666 +       DWC_LIST_INIT(&hcd->periodic_sched_assigned);
34667 +       DWC_LIST_INIT(&hcd->periodic_sched_queued);
34668 +
34669 +       /*
34670 +        * Create a host channel descriptor for each host channel implemented
34671 +        * in the controller. Initialize the channel descriptor array.
34672 +        */
34673 +       DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
34674 +       num_channels = hcd->core_if->core_params->host_channels;
34675 +       DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
34676 +       for (i = 0; i < num_channels; i++) {
34677 +               channel = DWC_ALLOC(sizeof(dwc_hc_t));
34678 +               if (channel == NULL) {
34679 +                       retval = -DWC_E_NO_MEMORY;
34680 +                       DWC_ERROR("%s: host channel allocation failed\n",
34681 +                                 __func__);
34682 +                       dwc_otg_hcd_free(hcd);
34683 +                       goto out;
34684 +               }
34685 +               channel->hc_num = i;
34686 +               hcd->hc_ptr_array[i] = channel;
34687 +#ifdef DEBUG
34688 +               hcd->core_if->hc_xfer_timer[i] =
34689 +                   DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
34690 +                                   &hcd->core_if->hc_xfer_info[i]);
34691 +#endif
34692 +               DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
34693 +                           channel);
34694 +       }
34695 +
34696 +       /* Initialize the Connection timeout timer. */
34697 +       hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
34698 +                                         dwc_otg_hcd_connect_timeout, 0);
34699 +
34700 +       printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
34701 +       if (microframe_schedule)
34702 +               init_hcd_usecs(hcd);
34703 +
34704 +       /* Initialize reset tasklet. */
34705 +       hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
34706 +#ifdef DWC_DEV_SRPCAP
34707 +       if (hcd->core_if->power_down == 2) {
34708 +               /* Initialize Power on timer for Host power up in case hibernation */
34709 +               hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
34710 +                                                                       dwc_otg_hcd_power_up, core_if);
34711 +       }
34712 +#endif
34713 +
34714 +       /*
34715 +        * Allocate space for storing data on status transactions. Normally no
34716 +        * data is sent, but this space acts as a bit bucket. This must be
34717 +        * done after usb_add_hcd since that function allocates the DMA buffer
34718 +        * pool.
34719 +        */
34720 +       if (hcd->core_if->dma_enable) {
34721 +               hcd->status_buf =
34722 +                   DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
34723 +                                 &hcd->status_buf_dma);
34724 +       } else {
34725 +               hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
34726 +       }
34727 +       if (!hcd->status_buf) {
34728 +               retval = -DWC_E_NO_MEMORY;
34729 +               DWC_ERROR("%s: status_buf allocation failed\n", __func__);
34730 +               dwc_otg_hcd_free(hcd);
34731 +               goto out;
34732 +       }
34733 +
34734 +       hcd->otg_port = 1;
34735 +       hcd->frame_list = NULL;
34736 +       hcd->frame_list_dma = 0;
34737 +       hcd->periodic_qh_count = 0;
34738 +out:
34739 +       return retval;
34740 +}
34741 +
34742 +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
34743 +{
34744 +       /* Turn off all host-specific interrupts. */
34745 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34746 +
34747 +       dwc_otg_hcd_free(hcd);
34748 +}
34749 +
34750 +/**
34751 + * Initializes dynamic portions of the DWC_otg HCD state.
34752 + */
34753 +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
34754 +{
34755 +       int num_channels;
34756 +       int i;
34757 +       dwc_hc_t *channel;
34758 +       dwc_hc_t *channel_tmp;
34759 +
34760 +       hcd->flags.d32 = 0;
34761 +
34762 +       hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
34763 +       if (!microframe_schedule) {
34764 +               hcd->non_periodic_channels = 0;
34765 +               hcd->periodic_channels = 0;
34766 +       } else {
34767 +               hcd->available_host_channels = hcd->core_if->core_params->host_channels;
34768 +       }
34769 +       /*
34770 +        * Put all channels in the free channel list and clean up channel
34771 +        * states.
34772 +        */
34773 +       DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
34774 +                                &hcd->free_hc_list, hc_list_entry) {
34775 +               DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
34776 +       }
34777 +
34778 +       num_channels = hcd->core_if->core_params->host_channels;
34779 +       for (i = 0; i < num_channels; i++) {
34780 +               channel = hcd->hc_ptr_array[i];
34781 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
34782 +                                       hc_list_entry);
34783 +               dwc_otg_hc_cleanup(hcd->core_if, channel);
34784 +       }
34785 +
34786 +       /* Initialize the DWC core for host mode operation. */
34787 +       dwc_otg_core_host_init(hcd->core_if);
34788 +
34789 +       /* Set core_if's lock pointer to the hcd->lock */
34790 +       hcd->core_if->lock = hcd->lock;
34791 +}
34792 +
34793 +/**
34794 + * Assigns transactions from a QTD to a free host channel and initializes the
34795 + * host channel to perform the transactions. The host channel is removed from
34796 + * the free list.
34797 + *
34798 + * @param hcd The HCD state structure.
34799 + * @param qh Transactions from the first QTD for this QH are selected and
34800 + * assigned to a free host channel.
34801 + */
34802 +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34803 +{
34804 +       dwc_hc_t *hc;
34805 +       dwc_otg_qtd_t *qtd;
34806 +       dwc_otg_hcd_urb_t *urb;
34807 +       void* ptr = NULL;
34808 +
34809 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34810 +
34811 +       urb = qtd->urb;
34812 +
34813 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
34814 +
34815 +       if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
34816 +               urb->actual_length = urb->length;
34817 +
34818 +
34819 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
34820 +
34821 +       /* Remove the host channel from the free list. */
34822 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
34823 +
34824 +       qh->channel = hc;
34825 +
34826 +       qtd->in_process = 1;
34827 +
34828 +       /*
34829 +        * Use usb_pipedevice to determine device address. This address is
34830 +        * 0 before the SET_ADDRESS command and the correct address afterward.
34831 +        */
34832 +       hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
34833 +       hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
34834 +       hc->speed = qh->dev_speed;
34835 +       hc->max_packet = dwc_max_packet(qh->maxp);
34836 +
34837 +       hc->xfer_started = 0;
34838 +       hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
34839 +       hc->error_state = (qtd->error_count > 0);
34840 +       hc->halt_on_queue = 0;
34841 +       hc->halt_pending = 0;
34842 +       hc->requests = 0;
34843 +
34844 +       /*
34845 +        * The following values may be modified in the transfer type section
34846 +        * below. The xfer_len value may be reduced when the transfer is
34847 +        * started to accommodate the max widths of the XferSize and PktCnt
34848 +        * fields in the HCTSIZn register.
34849 +        */
34850 +
34851 +       hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
34852 +       if (hc->ep_is_in) {
34853 +               hc->do_ping = 0;
34854 +       } else {
34855 +               hc->do_ping = qh->ping_state;
34856 +       }
34857 +
34858 +       hc->data_pid_start = qh->data_toggle;
34859 +       hc->multi_count = 1;
34860 +
34861 +       if (hcd->core_if->dma_enable) {
34862 +               hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
34863 +
34864 +               /* For non-dword aligned case */
34865 +               if (((unsigned long)hc->xfer_buff & 0x3)
34866 +                   && !hcd->core_if->dma_desc_enable) {
34867 +                       ptr = (uint8_t *) urb->buf + urb->actual_length;
34868 +               }
34869 +       } else {
34870 +               hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
34871 +       }
34872 +       hc->xfer_len = urb->length - urb->actual_length;
34873 +       hc->xfer_count = 0;
34874 +
34875 +       /*
34876 +        * Set the split attributes
34877 +        */
34878 +       hc->do_split = 0;
34879 +       if (qh->do_split) {
34880 +               uint32_t hub_addr, port_addr;
34881 +               hc->do_split = 1;
34882 +               hc->xact_pos = qtd->isoc_split_pos;
34883 +               hc->complete_split = qtd->complete_split;
34884 +               hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
34885 +               hc->hub_addr = (uint8_t) hub_addr;
34886 +               hc->port_addr = (uint8_t) port_addr;
34887 +       }
34888 +
34889 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
34890 +       case UE_CONTROL:
34891 +               hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
34892 +               switch (qtd->control_phase) {
34893 +               case DWC_OTG_CONTROL_SETUP:
34894 +                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
34895 +                       hc->do_ping = 0;
34896 +                       hc->ep_is_in = 0;
34897 +                       hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
34898 +                       if (hcd->core_if->dma_enable) {
34899 +                               hc->xfer_buff = (uint8_t *) urb->setup_dma;
34900 +                       } else {
34901 +                               hc->xfer_buff = (uint8_t *) urb->setup_packet;
34902 +                       }
34903 +                       hc->xfer_len = 8;
34904 +                       ptr = NULL;
34905 +                       break;
34906 +               case DWC_OTG_CONTROL_DATA:
34907 +                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
34908 +                       hc->data_pid_start = qtd->data_toggle;
34909 +                       break;
34910 +               case DWC_OTG_CONTROL_STATUS:
34911 +                       /*
34912 +                        * Direction is opposite of data direction or IN if no
34913 +                        * data.
34914 +                        */
34915 +                       DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
34916 +                       if (urb->length == 0) {
34917 +                               hc->ep_is_in = 1;
34918 +                       } else {
34919 +                               hc->ep_is_in =
34920 +                                   dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
34921 +                       }
34922 +                       if (hc->ep_is_in) {
34923 +                               hc->do_ping = 0;
34924 +                       }
34925 +
34926 +                       hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
34927 +
34928 +                       hc->xfer_len = 0;
34929 +                       if (hcd->core_if->dma_enable) {
34930 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
34931 +                       } else {
34932 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf;
34933 +                       }
34934 +                       ptr = NULL;
34935 +                       break;
34936 +               }
34937 +               break;
34938 +       case UE_BULK:
34939 +               hc->ep_type = DWC_OTG_EP_TYPE_BULK;
34940 +               break;
34941 +       case UE_INTERRUPT:
34942 +               hc->ep_type = DWC_OTG_EP_TYPE_INTR;
34943 +               break;
34944 +       case UE_ISOCHRONOUS:
34945 +               {
34946 +                       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
34947 +
34948 +                       hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
34949 +
34950 +                       if (hcd->core_if->dma_desc_enable)
34951 +                               break;
34952 +
34953 +                       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
34954 +
34955 +                       frame_desc->status = 0;
34956 +
34957 +                       if (hcd->core_if->dma_enable) {
34958 +                               hc->xfer_buff = (uint8_t *) urb->dma;
34959 +                       } else {
34960 +                               hc->xfer_buff = (uint8_t *) urb->buf;
34961 +                       }
34962 +                       hc->xfer_buff +=
34963 +                           frame_desc->offset + qtd->isoc_split_offset;
34964 +                       hc->xfer_len =
34965 +                           frame_desc->length - qtd->isoc_split_offset;
34966 +
34967 +                       /* For non-dword aligned buffers */
34968 +                       if (((unsigned long)hc->xfer_buff & 0x3)
34969 +                           && hcd->core_if->dma_enable) {
34970 +                               ptr =
34971 +                                   (uint8_t *) urb->buf + frame_desc->offset +
34972 +                                   qtd->isoc_split_offset;
34973 +                       } else
34974 +                               ptr = NULL;
34975 +
34976 +                       if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
34977 +                               if (hc->xfer_len <= 188) {
34978 +                                       hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
34979 +                               } else {
34980 +                                       hc->xact_pos =
34981 +                                           DWC_HCSPLIT_XACTPOS_BEGIN;
34982 +                               }
34983 +                       }
34984 +               }
34985 +               break;
34986 +       }
34987 +       /* non DWORD-aligned buffer case */
34988 +       if (ptr) {
34989 +               uint32_t buf_size;
34990 +               if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
34991 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
34992 +               } else {
34993 +                       buf_size = 4096;
34994 +               }
34995 +               if (!qh->dw_align_buf) {
34996 +                       qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
34997 +                                                        &qh->dw_align_buf_dma);
34998 +                       if (!qh->dw_align_buf) {
34999 +                               DWC_ERROR
35000 +                                   ("%s: Failed to allocate memory to handle "
35001 +                                    "non-dword aligned buffer case\n",
35002 +                                    __func__);
35003 +                               return;
35004 +                       }
35005 +               }
35006 +               if (!hc->ep_is_in) {
35007 +                       dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
35008 +               }
35009 +               hc->align_buff = qh->dw_align_buf_dma;
35010 +       } else {
35011 +               hc->align_buff = 0;
35012 +       }
35013 +
35014 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
35015 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
35016 +               /*
35017 +                * This value may be modified when the transfer is started to
35018 +                * reflect the actual transfer length.
35019 +                */
35020 +               hc->multi_count = dwc_hb_mult(qh->maxp);
35021 +       }
35022 +
35023 +       if (hcd->core_if->dma_desc_enable)
35024 +               hc->desc_list_addr = qh->desc_list_dma;
35025 +
35026 +       dwc_otg_hc_init(hcd->core_if, hc);
35027 +       hc->qh = qh;
35028 +}
35029 +
35030 +/**
35031 + * This function selects transactions from the HCD transfer schedule and
35032 + * assigns them to available host channels. It is called from HCD interrupt
35033 + * handler functions.
35034 + *
35035 + * @param hcd The HCD state structure.
35036 + *
35037 + * @return The types of new transactions that were assigned to host channels.
35038 + */
35039 +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
35040 +{
35041 +       dwc_list_link_t *qh_ptr;
35042 +       dwc_otg_qh_t *qh;
35043 +       int num_channels;
35044 +       dwc_irqflags_t flags;
35045 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
35046 +       dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
35047 +
35048 +#ifdef DEBUG_SOF
35049 +       DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");
35050 +#endif
35051 +
35052 +#ifdef DEBUG_HOST_CHANNELS
35053 +       last_sel_trans_num_per_scheduled = 0;
35054 +       last_sel_trans_num_nonper_scheduled = 0;
35055 +       last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
35056 +#endif /* DEBUG_HOST_CHANNELS */
35057 +
35058 +       /* Process entries in the periodic ready list. */
35059 +       qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
35060 +
35061 +       while (qh_ptr != &hcd->periodic_sched_ready &&
35062 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35063 +               if (microframe_schedule) {
35064 +                       // Make sure we leave one channel for non periodic transactions.
35065 +                       DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35066 +                       if (hcd->available_host_channels <= 1) {
35067 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35068 +                               break;
35069 +                       }
35070 +                       hcd->available_host_channels--;
35071 +                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35072 +#ifdef DEBUG_HOST_CHANNELS
35073 +                       last_sel_trans_num_per_scheduled++;
35074 +#endif /* DEBUG_HOST_CHANNELS */
35075 +               }
35076 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35077 +               assign_and_init_hc(hcd, qh);
35078 +
35079 +               /*
35080 +                * Move the QH from the periodic ready schedule to the
35081 +                * periodic assigned schedule.
35082 +                */
35083 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35084 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35085 +               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
35086 +                                  &qh->qh_list_entry);
35087 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35088 +
35089 +               ret_val = DWC_OTG_TRANSACTION_PERIODIC;
35090 +       }
35091 +
35092 +       /*
35093 +        * Process entries in the inactive portion of the non-periodic
35094 +        * schedule. Some free host channels may not be used if they are
35095 +        * reserved for periodic transfers.
35096 +        */
35097 +       qh_ptr = hcd->non_periodic_sched_inactive.next;
35098 +       num_channels = hcd->core_if->core_params->host_channels;
35099 +       while (qh_ptr != &hcd->non_periodic_sched_inactive &&
35100 +              (microframe_schedule || hcd->non_periodic_channels <
35101 +               num_channels - hcd->periodic_channels) &&
35102 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35103 +
35104 +               if (microframe_schedule) {
35105 +                               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35106 +                               if (hcd->available_host_channels < 1) {
35107 +                                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35108 +                                       break;
35109 +                               }
35110 +                               hcd->available_host_channels--;
35111 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35112 +#ifdef DEBUG_HOST_CHANNELS
35113 +                               last_sel_trans_num_nonper_scheduled++;
35114 +#endif /* DEBUG_HOST_CHANNELS */
35115 +               }
35116 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35117 +
35118 +               assign_and_init_hc(hcd, qh);
35119 +
35120 +               /*
35121 +                * Move the QH from the non-periodic inactive schedule to the
35122 +                * non-periodic active schedule.
35123 +                */
35124 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35125 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35126 +               DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
35127 +                                  &qh->qh_list_entry);
35128 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35129 +
35130 +               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
35131 +                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
35132 +               } else {
35133 +                       ret_val = DWC_OTG_TRANSACTION_ALL;
35134 +               }
35135 +
35136 +               if (!microframe_schedule)
35137 +                       hcd->non_periodic_channels++;
35138 +       }
35139 +
35140 +#ifdef DEBUG_HOST_CHANNELS
35141 +       last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
35142 +#endif /* DEBUG_HOST_CHANNELS */
35143 +
35144 +       DWC_SPINLOCK_FREE(channel_lock);
35145 +       return ret_val;
35146 +}
35147 +
35148 +/**
35149 + * Attempts to queue a single transaction request for a host channel
35150 + * associated with either a periodic or non-periodic transfer. This function
35151 + * assumes that there is space available in the appropriate request queue. For
35152 + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
35153 + * is available in the appropriate Tx FIFO.
35154 + *
35155 + * @param hcd The HCD state structure.
35156 + * @param hc Host channel descriptor associated with either a periodic or
35157 + * non-periodic transfer.
35158 + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
35159 + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
35160 + * transfers.
35161 + *
35162 + * @return 1 if a request is queued and more requests may be needed to
35163 + * complete the transfer, 0 if no more requests are required for this
35164 + * transfer, -1 if there is insufficient space in the Tx FIFO.
35165 + */
35166 +static int queue_transaction(dwc_otg_hcd_t * hcd,
35167 +                            dwc_hc_t * hc, uint16_t fifo_dwords_avail)
35168 +{
35169 +       int retval;
35170 +
35171 +       if (hcd->core_if->dma_enable) {
35172 +               if (hcd->core_if->dma_desc_enable) {
35173 +                       if (!hc->xfer_started
35174 +                           || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
35175 +                               dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
35176 +                               hc->qh->ping_state = 0;
35177 +                       }
35178 +               } else if (!hc->xfer_started) {
35179 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35180 +                       hc->qh->ping_state = 0;
35181 +               }
35182 +               retval = 0;
35183 +       } else if (hc->halt_pending) {
35184 +               /* Don't queue a request if the channel has been halted. */
35185 +               retval = 0;
35186 +       } else if (hc->halt_on_queue) {
35187 +               dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
35188 +               retval = 0;
35189 +       } else if (hc->do_ping) {
35190 +               if (!hc->xfer_started) {
35191 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35192 +               }
35193 +               retval = 0;
35194 +       } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
35195 +               if ((fifo_dwords_avail * 4) >= hc->max_packet) {
35196 +                       if (!hc->xfer_started) {
35197 +                               dwc_otg_hc_start_transfer(hcd->core_if, hc);
35198 +                               retval = 1;
35199 +                       } else {
35200 +                               retval =
35201 +                                   dwc_otg_hc_continue_transfer(hcd->core_if,
35202 +                                                                hc);
35203 +                       }
35204 +               } else {
35205 +                       retval = -1;
35206 +               }
35207 +       } else {
35208 +               if (!hc->xfer_started) {
35209 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35210 +                       retval = 1;
35211 +               } else {
35212 +                       retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
35213 +               }
35214 +       }
35215 +
35216 +       return retval;
35217 +}
35218 +
35219 +/**
35220 + * Processes periodic channels for the next frame and queues transactions for
35221 + * these channels to the DWC_otg controller. After queueing transactions, the
35222 + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
35223 + * to queue as Periodic Tx FIFO or request queue space becomes available.
35224 + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
35225 + */
35226 +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
35227 +{
35228 +       hptxsts_data_t tx_status;
35229 +       dwc_list_link_t *qh_ptr;
35230 +       dwc_otg_qh_t *qh;
35231 +       int status;
35232 +       int no_queue_space = 0;
35233 +       int no_fifo_space = 0;
35234 +
35235 +       dwc_otg_host_global_regs_t *host_regs;
35236 +       host_regs = hcd->core_if->host_if->host_global_regs;
35237 +
35238 +       DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
35239 +#ifdef DEBUG
35240 +       tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35241 +       DWC_DEBUGPL(DBG_HCDV,
35242 +                   "  P Tx Req Queue Space Avail (before queue): %d\n",
35243 +                   tx_status.b.ptxqspcavail);
35244 +       DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
35245 +                   tx_status.b.ptxfspcavail);
35246 +#endif
35247 +
35248 +       qh_ptr = hcd->periodic_sched_assigned.next;
35249 +       while (qh_ptr != &hcd->periodic_sched_assigned) {
35250 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35251 +               if (tx_status.b.ptxqspcavail == 0) {
35252 +                       no_queue_space = 1;
35253 +                       break;
35254 +               }
35255 +
35256 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35257 +
35258 +               /*
35259 +                * Set a flag if we're queuing high-bandwidth in slave mode.
35260 +                * The flag prevents any halts to get into the request queue in
35261 +                * the middle of multiple high-bandwidth packets getting queued.
35262 +                */
35263 +               if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
35264 +                       hcd->core_if->queuing_high_bandwidth = 1;
35265 +               }
35266 +               status =
35267 +                   queue_transaction(hcd, qh->channel,
35268 +                                     tx_status.b.ptxfspcavail);
35269 +               if (status < 0) {
35270 +                       no_fifo_space = 1;
35271 +                       break;
35272 +               }
35273 +
35274 +               /*
35275 +                * In Slave mode, stay on the current transfer until there is
35276 +                * nothing more to do or the high-bandwidth request count is
35277 +                * reached. In DMA mode, only need to queue one request. The
35278 +                * controller automatically handles multiple packets for
35279 +                * high-bandwidth transfers.
35280 +                */
35281 +               if (hcd->core_if->dma_enable || status == 0 ||
35282 +                   qh->channel->requests == qh->channel->multi_count) {
35283 +                       qh_ptr = qh_ptr->next;
35284 +                       /*
35285 +                        * Move the QH from the periodic assigned schedule to
35286 +                        * the periodic queued schedule.
35287 +                        */
35288 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
35289 +                                          &qh->qh_list_entry);
35290 +
35291 +                       /* done queuing high bandwidth */
35292 +                       hcd->core_if->queuing_high_bandwidth = 0;
35293 +               }
35294 +       }
35295 +
35296 +       if (!hcd->core_if->dma_enable) {
35297 +               dwc_otg_core_global_regs_t *global_regs;
35298 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35299 +
35300 +               global_regs = hcd->core_if->core_global_regs;
35301 +               intr_mask.b.ptxfempty = 1;
35302 +#ifdef DEBUG
35303 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35304 +               DWC_DEBUGPL(DBG_HCDV,
35305 +                           "  P Tx Req Queue Space Avail (after queue): %d\n",
35306 +                           tx_status.b.ptxqspcavail);
35307 +               DWC_DEBUGPL(DBG_HCDV,
35308 +                           "  P Tx FIFO Space Avail (after queue): %d\n",
35309 +                           tx_status.b.ptxfspcavail);
35310 +#endif
35311 +               if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
35312 +                   no_queue_space || no_fifo_space) {
35313 +                       /*
35314 +                        * May need to queue more transactions as the request
35315 +                        * queue or Tx FIFO empties. Enable the periodic Tx
35316 +                        * FIFO empty interrupt. (Always use the half-empty
35317 +                        * level to ensure that new requests are loaded as
35318 +                        * soon as possible.)
35319 +                        */
35320 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35321 +                                        intr_mask.d32);
35322 +               } else {
35323 +                       /*
35324 +                        * Disable the Tx FIFO empty interrupt since there are
35325 +                        * no more transactions that need to be queued right
35326 +                        * now. This function is called from interrupt
35327 +                        * handlers to queue more transactions as transfer
35328 +                        * states change.
35329 +                        */
35330 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35331 +                                        0);
35332 +               }
35333 +       }
35334 +}
35335 +
35336 +/**
35337 + * Processes active non-periodic channels and queues transactions for these
35338 + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
35339 + * FIFO Empty interrupt is enabled if there are more transactions to queue as
35340 + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
35341 + * FIFO Empty interrupt is disabled.
35342 + */
35343 +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
35344 +{
35345 +       gnptxsts_data_t tx_status;
35346 +       dwc_list_link_t *orig_qh_ptr;
35347 +       dwc_otg_qh_t *qh;
35348 +       int status;
35349 +       int no_queue_space = 0;
35350 +       int no_fifo_space = 0;
35351 +       int more_to_do = 0;
35352 +
35353 +       dwc_otg_core_global_regs_t *global_regs =
35354 +           hcd->core_if->core_global_regs;
35355 +
35356 +       DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
35357 +#ifdef DEBUG
35358 +       tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35359 +       DWC_DEBUGPL(DBG_HCDV,
35360 +                   "  NP Tx Req Queue Space Avail (before queue): %d\n",
35361 +                   tx_status.b.nptxqspcavail);
35362 +       DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
35363 +                   tx_status.b.nptxfspcavail);
35364 +#endif
35365 +       /*
35366 +        * Keep track of the starting point. Skip over the start-of-list
35367 +        * entry.
35368 +        */
35369 +       if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35370 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35371 +       }
35372 +       orig_qh_ptr = hcd->non_periodic_qh_ptr;
35373 +
35374 +       /*
35375 +        * Process once through the active list or until no more space is
35376 +        * available in the request queue or the Tx FIFO.
35377 +        */
35378 +       do {
35379 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35380 +               if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
35381 +                       no_queue_space = 1;
35382 +                       break;
35383 +               }
35384 +
35385 +               qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
35386 +                                   qh_list_entry);
35387 +               status =
35388 +                   queue_transaction(hcd, qh->channel,
35389 +                                     tx_status.b.nptxfspcavail);
35390 +
35391 +               if (status > 0) {
35392 +                       more_to_do = 1;
35393 +               } else if (status < 0) {
35394 +                       no_fifo_space = 1;
35395 +                       break;
35396 +               }
35397 +
35398 +               /* Advance to next QH, skipping start-of-list entry. */
35399 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35400 +               if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35401 +                       hcd->non_periodic_qh_ptr =
35402 +                           hcd->non_periodic_qh_ptr->next;
35403 +               }
35404 +
35405 +       } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
35406 +
35407 +       if (!hcd->core_if->dma_enable) {
35408 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35409 +               intr_mask.b.nptxfempty = 1;
35410 +
35411 +#ifdef DEBUG
35412 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35413 +               DWC_DEBUGPL(DBG_HCDV,
35414 +                           "  NP Tx Req Queue Space Avail (after queue): %d\n",
35415 +                           tx_status.b.nptxqspcavail);
35416 +               DWC_DEBUGPL(DBG_HCDV,
35417 +                           "  NP Tx FIFO Space Avail (after queue): %d\n",
35418 +                           tx_status.b.nptxfspcavail);
35419 +#endif
35420 +               if (more_to_do || no_queue_space || no_fifo_space) {
35421 +                       /*
35422 +                        * May need to queue more transactions as the request
35423 +                        * queue or Tx FIFO empties. Enable the non-periodic
35424 +                        * Tx FIFO empty interrupt. (Always use the half-empty
35425 +                        * level to ensure that new requests are loaded as
35426 +                        * soon as possible.)
35427 +                        */
35428 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35429 +                                        intr_mask.d32);
35430 +               } else {
35431 +                       /*
35432 +                        * Disable the Tx FIFO empty interrupt since there are
35433 +                        * no more transactions that need to be queued right
35434 +                        * now. This function is called from interrupt
35435 +                        * handlers to queue more transactions as transfer
35436 +                        * states change.
35437 +                        */
35438 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35439 +                                        0);
35440 +               }
35441 +       }
35442 +}
35443 +
35444 +/**
35445 + * This function processes the currently active host channels and queues
35446 + * transactions for these channels to the DWC_otg controller. It is called
35447 + * from HCD interrupt handler functions.
35448 + *
35449 + * @param hcd The HCD state structure.
35450 + * @param tr_type The type(s) of transactions to queue (non-periodic,
35451 + * periodic, or both).
35452 + */
35453 +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
35454 +                                   dwc_otg_transaction_type_e tr_type)
35455 +{
35456 +#ifdef DEBUG_SOF
35457 +       DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
35458 +#endif
35459 +       /* Process host channels associated with periodic transfers. */
35460 +       if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
35461 +            tr_type == DWC_OTG_TRANSACTION_ALL) &&
35462 +           !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
35463 +
35464 +               process_periodic_channels(hcd);
35465 +       }
35466 +
35467 +       /* Process host channels associated with non-periodic transfers. */
35468 +       if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
35469 +           tr_type == DWC_OTG_TRANSACTION_ALL) {
35470 +               if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
35471 +                       process_non_periodic_channels(hcd);
35472 +               } else {
35473 +                       /*
35474 +                        * Ensure NP Tx FIFO empty interrupt is disabled when
35475 +                        * there are no non-periodic transfers to process.
35476 +                        */
35477 +                       gintmsk_data_t gintmsk = {.d32 = 0 };
35478 +                       gintmsk.b.nptxfempty = 1;
35479 +                       DWC_MODIFY_REG32(&hcd->core_if->
35480 +                                        core_global_regs->gintmsk, gintmsk.d32,
35481 +                                        0);
35482 +               }
35483 +       }
35484 +}
35485 +
35486 +#ifdef DWC_HS_ELECT_TST
35487 +/*
35488 + * Quick and dirty hack to implement the HS Electrical Test
35489 + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
35490 + *
35491 + * This code was copied from our userspace app "hset". It sends a
35492 + * Get Device Descriptor control sequence in two parts, first the
35493 + * Setup packet by itself, followed some time later by the In and
35494 + * Ack packets. Rather than trying to figure out how to add this
35495 + * functionality to the normal driver code, we just hijack the
35496 + * hardware, using these two function to drive the hardware
35497 + * directly.
35498 + */
35499 +
35500 +static dwc_otg_core_global_regs_t *global_regs;
35501 +static dwc_otg_host_global_regs_t *hc_global_regs;
35502 +static dwc_otg_hc_regs_t *hc_regs;
35503 +static uint32_t *data_fifo;
35504 +
35505 +static void do_setup(void)
35506 +{
35507 +       gintsts_data_t gintsts;
35508 +       hctsiz_data_t hctsiz;
35509 +       hcchar_data_t hcchar;
35510 +       haint_data_t haint;
35511 +       hcint_data_t hcint;
35512 +
35513 +       /* Enable HAINTs */
35514 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35515 +
35516 +       /* Enable HCINTs */
35517 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35518 +
35519 +       /* Read GINTSTS */
35520 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35521 +
35522 +       /* Read HAINT */
35523 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35524 +
35525 +       /* Read HCINT */
35526 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35527 +
35528 +       /* Read HCCHAR */
35529 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35530 +
35531 +       /* Clear HCINT */
35532 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35533 +
35534 +       /* Clear HAINT */
35535 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35536 +
35537 +       /* Clear GINTSTS */
35538 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35539 +
35540 +       /* Read GINTSTS */
35541 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35542 +
35543 +       /*
35544 +        * Send Setup packet (Get Device Descriptor)
35545 +        */
35546 +
35547 +       /* Make sure channel is disabled */
35548 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35549 +       if (hcchar.b.chen) {
35550 +               hcchar.b.chdis = 1;
35551 +//              hcchar.b.chen = 1;
35552 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35553 +               //sleep(1);
35554 +               dwc_mdelay(1000);
35555 +
35556 +               /* Read GINTSTS */
35557 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35558 +
35559 +               /* Read HAINT */
35560 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35561 +
35562 +               /* Read HCINT */
35563 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35564 +
35565 +               /* Read HCCHAR */
35566 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35567 +
35568 +               /* Clear HCINT */
35569 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35570 +
35571 +               /* Clear HAINT */
35572 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35573 +
35574 +               /* Clear GINTSTS */
35575 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35576 +
35577 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35578 +       }
35579 +
35580 +       /* Set HCTSIZ */
35581 +       hctsiz.d32 = 0;
35582 +       hctsiz.b.xfersize = 8;
35583 +       hctsiz.b.pktcnt = 1;
35584 +       hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
35585 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35586 +
35587 +       /* Set HCCHAR */
35588 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35589 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35590 +       hcchar.b.epdir = 0;
35591 +       hcchar.b.epnum = 0;
35592 +       hcchar.b.mps = 8;
35593 +       hcchar.b.chen = 1;
35594 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35595 +
35596 +       /* Fill FIFO with Setup data for Get Device Descriptor */
35597 +       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35598 +       DWC_WRITE_REG32(data_fifo++, 0x01000680);
35599 +       DWC_WRITE_REG32(data_fifo++, 0x00080000);
35600 +
35601 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35602 +
35603 +       /* Wait for host channel interrupt */
35604 +       do {
35605 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35606 +       } while (gintsts.b.hcintr == 0);
35607 +
35608 +       /* Disable HCINTs */
35609 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35610 +
35611 +       /* Disable HAINTs */
35612 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35613 +
35614 +       /* Read HAINT */
35615 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35616 +
35617 +       /* Read HCINT */
35618 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35619 +
35620 +       /* Read HCCHAR */
35621 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35622 +
35623 +       /* Clear HCINT */
35624 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35625 +
35626 +       /* Clear HAINT */
35627 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35628 +
35629 +       /* Clear GINTSTS */
35630 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35631 +
35632 +       /* Read GINTSTS */
35633 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35634 +}
35635 +
35636 +static void do_in_ack(void)
35637 +{
35638 +       gintsts_data_t gintsts;
35639 +       hctsiz_data_t hctsiz;
35640 +       hcchar_data_t hcchar;
35641 +       haint_data_t haint;
35642 +       hcint_data_t hcint;
35643 +       host_grxsts_data_t grxsts;
35644 +
35645 +       /* Enable HAINTs */
35646 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35647 +
35648 +       /* Enable HCINTs */
35649 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35650 +
35651 +       /* Read GINTSTS */
35652 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35653 +
35654 +       /* Read HAINT */
35655 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35656 +
35657 +       /* Read HCINT */
35658 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35659 +
35660 +       /* Read HCCHAR */
35661 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35662 +
35663 +       /* Clear HCINT */
35664 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35665 +
35666 +       /* Clear HAINT */
35667 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35668 +
35669 +       /* Clear GINTSTS */
35670 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35671 +
35672 +       /* Read GINTSTS */
35673 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35674 +
35675 +       /*
35676 +        * Receive Control In packet
35677 +        */
35678 +
35679 +       /* Make sure channel is disabled */
35680 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35681 +       if (hcchar.b.chen) {
35682 +               hcchar.b.chdis = 1;
35683 +               hcchar.b.chen = 1;
35684 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35685 +               //sleep(1);
35686 +               dwc_mdelay(1000);
35687 +
35688 +               /* Read GINTSTS */
35689 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35690 +
35691 +               /* Read HAINT */
35692 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35693 +
35694 +               /* Read HCINT */
35695 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35696 +
35697 +               /* Read HCCHAR */
35698 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35699 +
35700 +               /* Clear HCINT */
35701 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35702 +
35703 +               /* Clear HAINT */
35704 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35705 +
35706 +               /* Clear GINTSTS */
35707 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35708 +
35709 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35710 +       }
35711 +
35712 +       /* Set HCTSIZ */
35713 +       hctsiz.d32 = 0;
35714 +       hctsiz.b.xfersize = 8;
35715 +       hctsiz.b.pktcnt = 1;
35716 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35717 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35718 +
35719 +       /* Set HCCHAR */
35720 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35721 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35722 +       hcchar.b.epdir = 1;
35723 +       hcchar.b.epnum = 0;
35724 +       hcchar.b.mps = 8;
35725 +       hcchar.b.chen = 1;
35726 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35727 +
35728 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35729 +
35730 +       /* Wait for receive status queue interrupt */
35731 +       do {
35732 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35733 +       } while (gintsts.b.rxstsqlvl == 0);
35734 +
35735 +       /* Read RXSTS */
35736 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35737 +
35738 +       /* Clear RXSTSQLVL in GINTSTS */
35739 +       gintsts.d32 = 0;
35740 +       gintsts.b.rxstsqlvl = 1;
35741 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35742 +
35743 +       switch (grxsts.b.pktsts) {
35744 +       case DWC_GRXSTS_PKTSTS_IN:
35745 +               /* Read the data into the host buffer */
35746 +               if (grxsts.b.bcnt > 0) {
35747 +                       int i;
35748 +                       int word_count = (grxsts.b.bcnt + 3) / 4;
35749 +
35750 +                       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35751 +
35752 +                       for (i = 0; i < word_count; i++) {
35753 +                               (void)DWC_READ_REG32(data_fifo++);
35754 +                       }
35755 +               }
35756 +               break;
35757 +
35758 +       default:
35759 +               break;
35760 +       }
35761 +
35762 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35763 +
35764 +       /* Wait for receive status queue interrupt */
35765 +       do {
35766 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35767 +       } while (gintsts.b.rxstsqlvl == 0);
35768 +
35769 +       /* Read RXSTS */
35770 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35771 +
35772 +       /* Clear RXSTSQLVL in GINTSTS */
35773 +       gintsts.d32 = 0;
35774 +       gintsts.b.rxstsqlvl = 1;
35775 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35776 +
35777 +       switch (grxsts.b.pktsts) {
35778 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
35779 +               break;
35780 +
35781 +       default:
35782 +               break;
35783 +       }
35784 +
35785 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35786 +
35787 +       /* Wait for host channel interrupt */
35788 +       do {
35789 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35790 +       } while (gintsts.b.hcintr == 0);
35791 +
35792 +       /* Read HAINT */
35793 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35794 +
35795 +       /* Read HCINT */
35796 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35797 +
35798 +       /* Read HCCHAR */
35799 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35800 +
35801 +       /* Clear HCINT */
35802 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35803 +
35804 +       /* Clear HAINT */
35805 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35806 +
35807 +       /* Clear GINTSTS */
35808 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35809 +
35810 +       /* Read GINTSTS */
35811 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35812 +
35813 +//      usleep(100000);
35814 +//      mdelay(100);
35815 +       dwc_mdelay(1);
35816 +
35817 +       /*
35818 +        * Send handshake packet
35819 +        */
35820 +
35821 +       /* Read HAINT */
35822 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35823 +
35824 +       /* Read HCINT */
35825 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35826 +
35827 +       /* Read HCCHAR */
35828 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35829 +
35830 +       /* Clear HCINT */
35831 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35832 +
35833 +       /* Clear HAINT */
35834 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35835 +
35836 +       /* Clear GINTSTS */
35837 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35838 +
35839 +       /* Read GINTSTS */
35840 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35841 +
35842 +       /* Make sure channel is disabled */
35843 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35844 +       if (hcchar.b.chen) {
35845 +               hcchar.b.chdis = 1;
35846 +               hcchar.b.chen = 1;
35847 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35848 +               //sleep(1);
35849 +               dwc_mdelay(1000);
35850 +
35851 +               /* Read GINTSTS */
35852 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35853 +
35854 +               /* Read HAINT */
35855 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35856 +
35857 +               /* Read HCINT */
35858 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35859 +
35860 +               /* Read HCCHAR */
35861 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35862 +
35863 +               /* Clear HCINT */
35864 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35865 +
35866 +               /* Clear HAINT */
35867 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35868 +
35869 +               /* Clear GINTSTS */
35870 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35871 +
35872 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35873 +       }
35874 +
35875 +       /* Set HCTSIZ */
35876 +       hctsiz.d32 = 0;
35877 +       hctsiz.b.xfersize = 0;
35878 +       hctsiz.b.pktcnt = 1;
35879 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35880 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35881 +
35882 +       /* Set HCCHAR */
35883 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35884 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35885 +       hcchar.b.epdir = 0;
35886 +       hcchar.b.epnum = 0;
35887 +       hcchar.b.mps = 8;
35888 +       hcchar.b.chen = 1;
35889 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35890 +
35891 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35892 +
35893 +       /* Wait for host channel interrupt */
35894 +       do {
35895 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35896 +       } while (gintsts.b.hcintr == 0);
35897 +
35898 +       /* Disable HCINTs */
35899 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35900 +
35901 +       /* Disable HAINTs */
35902 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35903 +
35904 +       /* Read HAINT */
35905 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35906 +
35907 +       /* Read HCINT */
35908 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35909 +
35910 +       /* Read HCCHAR */
35911 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35912 +
35913 +       /* Clear HCINT */
35914 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35915 +
35916 +       /* Clear HAINT */
35917 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35918 +
35919 +       /* Clear GINTSTS */
35920 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35921 +
35922 +       /* Read GINTSTS */
35923 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35924 +}
35925 +#endif
35926 +
35927 +/** Handles hub class-specific requests. */
35928 +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
35929 +                           uint16_t typeReq,
35930 +                           uint16_t wValue,
35931 +                           uint16_t wIndex, uint8_t * buf, uint16_t wLength)
35932 +{
35933 +       int retval = 0;
35934 +
35935 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
35936 +       usb_hub_descriptor_t *hub_desc;
35937 +       hprt0_data_t hprt0 = {.d32 = 0 };
35938 +
35939 +       uint32_t port_status;
35940 +
35941 +       switch (typeReq) {
35942 +       case UCR_CLEAR_HUB_FEATURE:
35943 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35944 +                           "ClearHubFeature 0x%x\n", wValue);
35945 +               switch (wValue) {
35946 +               case UHF_C_HUB_LOCAL_POWER:
35947 +               case UHF_C_HUB_OVER_CURRENT:
35948 +                       /* Nothing required here */
35949 +                       break;
35950 +               default:
35951 +                       retval = -DWC_E_INVALID;
35952 +                       DWC_ERROR("DWC OTG HCD - "
35953 +                                 "ClearHubFeature request %xh unknown\n",
35954 +                                 wValue);
35955 +               }
35956 +               break;
35957 +       case UCR_CLEAR_PORT_FEATURE:
35958 +#ifdef CONFIG_USB_DWC_OTG_LPM
35959 +               if (wValue != UHF_PORT_L1)
35960 +#endif
35961 +                       if (!wIndex || wIndex > 1)
35962 +                               goto error;
35963 +
35964 +               switch (wValue) {
35965 +               case UHF_PORT_ENABLE:
35966 +                       DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
35967 +                                   "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
35968 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
35969 +                       hprt0.b.prtena = 1;
35970 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35971 +                       break;
35972 +               case UHF_PORT_SUSPEND:
35973 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35974 +                                   "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
35975 +
35976 +                       if (core_if->power_down == 2) {
35977 +                               dwc_otg_host_hibernation_restore(core_if, 0, 0);
35978 +                       } else {
35979 +                               DWC_WRITE_REG32(core_if->pcgcctl, 0);
35980 +                               dwc_mdelay(5);
35981 +
35982 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
35983 +                               hprt0.b.prtres = 1;
35984 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35985 +                               hprt0.b.prtsusp = 0;
35986 +                               /* Clear Resume bit */
35987 +                               dwc_mdelay(100);
35988 +                               hprt0.b.prtres = 0;
35989 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35990 +                       }
35991 +                       break;
35992 +#ifdef CONFIG_USB_DWC_OTG_LPM
35993 +               case UHF_PORT_L1:
35994 +                       {
35995 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
35996 +                               glpmcfg_data_t lpmcfg = {.d32 = 0 };
35997 +
35998 +                               lpmcfg.d32 =
35999 +                                   DWC_READ_REG32(&core_if->
36000 +                                                  core_global_regs->glpmcfg);
36001 +                               lpmcfg.b.en_utmi_sleep = 0;
36002 +                               lpmcfg.b.hird_thres &= (~(1 << 4));
36003 +                               lpmcfg.b.prt_sleep_sts = 1;
36004 +                               DWC_WRITE_REG32(&core_if->
36005 +                                               core_global_regs->glpmcfg,
36006 +                                               lpmcfg.d32);
36007 +
36008 +                               /* Clear Enbl_L1Gating bit. */
36009 +                               pcgcctl.b.enbl_sleep_gating = 1;
36010 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
36011 +                                                0);
36012 +
36013 +                               dwc_mdelay(5);
36014 +
36015 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36016 +                               hprt0.b.prtres = 1;
36017 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36018 +                                               hprt0.d32);
36019 +                               /* This bit will be cleared in wakeup interrupt handle */
36020 +                               break;
36021 +                       }
36022 +#endif
36023 +               case UHF_PORT_POWER:
36024 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36025 +                                   "ClearPortFeature USB_PORT_FEAT_POWER\n");
36026 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36027 +                       hprt0.b.prtpwr = 0;
36028 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36029 +                       break;
36030 +               case UHF_PORT_INDICATOR:
36031 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36032 +                                   "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
36033 +                       /* Port inidicator not supported */
36034 +                       break;
36035 +               case UHF_C_PORT_CONNECTION:
36036 +                       /* Clears drivers internal connect status change
36037 +                        * flag */
36038 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36039 +                                   "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
36040 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 0;
36041 +                       break;
36042 +               case UHF_C_PORT_RESET:
36043 +                       /* Clears the driver's internal Port Reset Change
36044 +                        * flag */
36045 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36046 +                                   "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
36047 +                       dwc_otg_hcd->flags.b.port_reset_change = 0;
36048 +                       break;
36049 +               case UHF_C_PORT_ENABLE:
36050 +                       /* Clears the driver's internal Port
36051 +                        * Enable/Disable Change flag */
36052 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36053 +                                   "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
36054 +                       dwc_otg_hcd->flags.b.port_enable_change = 0;
36055 +                       break;
36056 +               case UHF_C_PORT_SUSPEND:
36057 +                       /* Clears the driver's internal Port Suspend
36058 +                        * Change flag, which is set when resume signaling on
36059 +                        * the host port is complete */
36060 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36061 +                                   "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
36062 +                       dwc_otg_hcd->flags.b.port_suspend_change = 0;
36063 +                       break;
36064 +#ifdef CONFIG_USB_DWC_OTG_LPM
36065 +               case UHF_C_PORT_L1:
36066 +                       dwc_otg_hcd->flags.b.port_l1_change = 0;
36067 +                       break;
36068 +#endif
36069 +               case UHF_C_PORT_OVER_CURRENT:
36070 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36071 +                                   "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
36072 +                       dwc_otg_hcd->flags.b.port_over_current_change = 0;
36073 +                       break;
36074 +               default:
36075 +                       retval = -DWC_E_INVALID;
36076 +                       DWC_ERROR("DWC OTG HCD - "
36077 +                                 "ClearPortFeature request %xh "
36078 +                                 "unknown or unsupported\n", wValue);
36079 +               }
36080 +               break;
36081 +       case UCR_GET_HUB_DESCRIPTOR:
36082 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36083 +                           "GetHubDescriptor\n");
36084 +               hub_desc = (usb_hub_descriptor_t *) buf;
36085 +               hub_desc->bDescLength = 9;
36086 +               hub_desc->bDescriptorType = 0x29;
36087 +               hub_desc->bNbrPorts = 1;
36088 +               USETW(hub_desc->wHubCharacteristics, 0x08);
36089 +               hub_desc->bPwrOn2PwrGood = 1;
36090 +               hub_desc->bHubContrCurrent = 0;
36091 +               hub_desc->DeviceRemovable[0] = 0;
36092 +               hub_desc->DeviceRemovable[1] = 0xff;
36093 +               break;
36094 +       case UCR_GET_HUB_STATUS:
36095 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36096 +                           "GetHubStatus\n");
36097 +               DWC_MEMSET(buf, 0, 4);
36098 +               break;
36099 +       case UCR_GET_PORT_STATUS:
36100 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36101 +                           "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
36102 +                           wIndex, dwc_otg_hcd->flags.d32);
36103 +               if (!wIndex || wIndex > 1)
36104 +                       goto error;
36105 +
36106 +               port_status = 0;
36107 +
36108 +               if (dwc_otg_hcd->flags.b.port_connect_status_change)
36109 +                       port_status |= (1 << UHF_C_PORT_CONNECTION);
36110 +
36111 +               if (dwc_otg_hcd->flags.b.port_enable_change)
36112 +                       port_status |= (1 << UHF_C_PORT_ENABLE);
36113 +
36114 +               if (dwc_otg_hcd->flags.b.port_suspend_change)
36115 +                       port_status |= (1 << UHF_C_PORT_SUSPEND);
36116 +
36117 +               if (dwc_otg_hcd->flags.b.port_l1_change)
36118 +                       port_status |= (1 << UHF_C_PORT_L1);
36119 +
36120 +               if (dwc_otg_hcd->flags.b.port_reset_change) {
36121 +                       port_status |= (1 << UHF_C_PORT_RESET);
36122 +               }
36123 +
36124 +               if (dwc_otg_hcd->flags.b.port_over_current_change) {
36125 +                       DWC_WARN("Overcurrent change detected\n");
36126 +                       port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
36127 +               }
36128 +
36129 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36130 +                       /*
36131 +                        * The port is disconnected, which means the core is
36132 +                        * either in device mode or it soon will be. Just
36133 +                        * return 0's for the remainder of the port status
36134 +                        * since the port register can't be read if the core
36135 +                        * is in device mode.
36136 +                        */
36137 +                       *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36138 +                       break;
36139 +               }
36140 +
36141 +               hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
36142 +               DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
36143 +
36144 +               if (hprt0.b.prtconnsts)
36145 +                       port_status |= (1 << UHF_PORT_CONNECTION);
36146 +
36147 +               if (hprt0.b.prtena)
36148 +                       port_status |= (1 << UHF_PORT_ENABLE);
36149 +
36150 +               if (hprt0.b.prtsusp)
36151 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36152 +
36153 +               if (hprt0.b.prtovrcurract)
36154 +                       port_status |= (1 << UHF_PORT_OVER_CURRENT);
36155 +
36156 +               if (hprt0.b.prtrst)
36157 +                       port_status |= (1 << UHF_PORT_RESET);
36158 +
36159 +               if (hprt0.b.prtpwr)
36160 +                       port_status |= (1 << UHF_PORT_POWER);
36161 +
36162 +               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
36163 +                       port_status |= (1 << UHF_PORT_HIGH_SPEED);
36164 +               else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
36165 +                       port_status |= (1 << UHF_PORT_LOW_SPEED);
36166 +
36167 +               if (hprt0.b.prttstctl)
36168 +                       port_status |= (1 << UHF_PORT_TEST);
36169 +               if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
36170 +                       port_status |= (1 << UHF_PORT_L1);
36171 +               }
36172 +               /*
36173 +                  For Synopsys HW emulation of Power down wkup_control asserts the
36174 +                  hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
36175 +                  We intentionally tell the software that port is in L2Suspend state.
36176 +                  Only for STE.
36177 +               */
36178 +               if ((core_if->power_down == 2)
36179 +                   && (core_if->hibernation_suspend == 1)) {
36180 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36181 +               }
36182 +               /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
36183 +
36184 +               *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36185 +
36186 +               break;
36187 +       case UCR_SET_HUB_FEATURE:
36188 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36189 +                           "SetHubFeature\n");
36190 +               /* No HUB features supported */
36191 +               break;
36192 +       case UCR_SET_PORT_FEATURE:
36193 +               if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
36194 +                       goto error;
36195 +
36196 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36197 +                       /*
36198 +                        * The port is disconnected, which means the core is
36199 +                        * either in device mode or it soon will be. Just
36200 +                        * return without doing anything since the port
36201 +                        * register can't be written if the core is in device
36202 +                        * mode.
36203 +                        */
36204 +                       break;
36205 +               }
36206 +
36207 +               switch (wValue) {
36208 +               case UHF_PORT_SUSPEND:
36209 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36210 +                                   "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
36211 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
36212 +                               goto error;
36213 +                       }
36214 +                       if (core_if->power_down == 2) {
36215 +                               int timeout = 300;
36216 +                               dwc_irqflags_t flags;
36217 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36218 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
36219 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
36220 +#ifdef DWC_DEV_SRPCAP
36221 +                               int32_t otg_cap_param = core_if->core_params->otg_cap;
36222 +#endif
36223 +                               DWC_PRINTF("Preparing for complete power-off\n");
36224 +
36225 +                               /* Save registers before hibernation */
36226 +                               dwc_otg_save_global_regs(core_if);
36227 +                               dwc_otg_save_host_regs(core_if);
36228 +
36229 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36230 +                               hprt0.b.prtsusp = 1;
36231 +                               hprt0.b.prtena = 0;
36232 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36233 +                               /* Spin hprt0.b.prtsusp to became 1 */
36234 +                               do {
36235 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36236 +                                       if (hprt0.b.prtsusp) {
36237 +                                               break;
36238 +                                       }
36239 +                                       dwc_mdelay(1);
36240 +                               } while (--timeout);
36241 +                               if (!timeout) {
36242 +                                       DWC_WARN("Suspend wasn't genereted\n");
36243 +                               }
36244 +                               dwc_udelay(10);
36245 +
36246 +                               /*
36247 +                                * We need to disable interrupts to prevent servicing of any IRQ
36248 +                                * during going to hibernation
36249 +                                */
36250 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36251 +                               core_if->lx_state = DWC_OTG_L2;
36252 +#ifdef DWC_DEV_SRPCAP
36253 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36254 +                               hprt0.b.prtpwr = 0;
36255 +                               hprt0.b.prtena = 0;
36256 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36257 +                                               hprt0.d32);
36258 +#endif
36259 +                               gusbcfg.d32 =
36260 +                                   DWC_READ_REG32(&core_if->core_global_regs->
36261 +                                                  gusbcfg);
36262 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
36263 +                                       /* ULPI interface */
36264 +                                       /* Suspend the Phy Clock */
36265 +                                       pcgcctl.d32 = 0;
36266 +                                       pcgcctl.b.stoppclk = 1;
36267 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36268 +                                                        pcgcctl.d32);
36269 +                                       dwc_udelay(10);
36270 +                                       gpwrdn.b.pmuactv = 1;
36271 +                                       DWC_MODIFY_REG32(&core_if->
36272 +                                                        core_global_regs->
36273 +                                                        gpwrdn, 0, gpwrdn.d32);
36274 +                               } else {
36275 +                                       /* UTMI+ Interface */
36276 +                                       gpwrdn.b.pmuactv = 1;
36277 +                                       DWC_MODIFY_REG32(&core_if->
36278 +                                                        core_global_regs->
36279 +                                                        gpwrdn, 0, gpwrdn.d32);
36280 +                                       dwc_udelay(10);
36281 +                                       pcgcctl.b.stoppclk = 1;
36282 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
36283 +                                       dwc_udelay(10);
36284 +                               }
36285 +#ifdef DWC_DEV_SRPCAP
36286 +                               gpwrdn.d32 = 0;
36287 +                               gpwrdn.b.dis_vbus = 1;
36288 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36289 +                                                gpwrdn, 0, gpwrdn.d32);
36290 +#endif
36291 +                               gpwrdn.d32 = 0;
36292 +                               gpwrdn.b.pmuintsel = 1;
36293 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36294 +                                                gpwrdn, 0, gpwrdn.d32);
36295 +                               dwc_udelay(10);
36296 +
36297 +                               gpwrdn.d32 = 0;
36298 +#ifdef DWC_DEV_SRPCAP
36299 +                               gpwrdn.b.srp_det_msk = 1;
36300 +#endif
36301 +                               gpwrdn.b.disconn_det_msk = 1;
36302 +                               gpwrdn.b.lnstchng_msk = 1;
36303 +                               gpwrdn.b.sts_chngint_msk = 1;
36304 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36305 +                                                gpwrdn, 0, gpwrdn.d32);
36306 +                               dwc_udelay(10);
36307 +
36308 +                               /* Enable Power Down Clamp and all interrupts in GPWRDN */
36309 +                               gpwrdn.d32 = 0;
36310 +                               gpwrdn.b.pwrdnclmp = 1;
36311 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36312 +                                                gpwrdn, 0, gpwrdn.d32);
36313 +                               dwc_udelay(10);
36314 +
36315 +                               /* Switch off VDD */
36316 +                               gpwrdn.d32 = 0;
36317 +                               gpwrdn.b.pwrdnswtch = 1;
36318 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36319 +                                                gpwrdn, 0, gpwrdn.d32);
36320 +
36321 +#ifdef DWC_DEV_SRPCAP
36322 +                               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
36323 +                               {
36324 +                                       core_if->pwron_timer_started = 1;
36325 +                                       DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
36326 +                               }
36327 +#endif
36328 +                               /* Save gpwrdn register for further usage if stschng interrupt */
36329 +                               core_if->gr_backup->gpwrdn_local =
36330 +                                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
36331 +
36332 +                               /* Set flag to indicate that we are in hibernation */
36333 +                               core_if->hibernation_suspend = 1;
36334 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
36335 +
36336 +                               DWC_PRINTF("Host hibernation completed\n");
36337 +                               // Exit from case statement
36338 +                               break;
36339 +
36340 +                       }
36341 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
36342 +                           dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36343 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36344 +                               gotgctl.b.hstsethnpen = 1;
36345 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36346 +                                                gotgctl, 0, gotgctl.d32);
36347 +                               core_if->op_state = A_SUSPEND;
36348 +                       }
36349 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36350 +                       hprt0.b.prtsusp = 1;
36351 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36352 +                       {
36353 +                               dwc_irqflags_t flags;
36354 +                               /* Update lx_state */
36355 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36356 +                               core_if->lx_state = DWC_OTG_L2;
36357 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
36358 +                       }
36359 +                       /* Suspend the Phy Clock */
36360 +                       {
36361 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36362 +                               pcgcctl.b.stoppclk = 1;
36363 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36364 +                                                pcgcctl.d32);
36365 +                               dwc_udelay(10);
36366 +                       }
36367 +
36368 +                       /* For HNP the bus must be suspended for at least 200ms. */
36369 +                       if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36370 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36371 +                               pcgcctl.b.stoppclk = 1;
36372 +                DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36373 +                               dwc_mdelay(200);
36374 +                       }
36375 +
36376 +                       /** @todo - check how sw can wait for 1 sec to check asesvld??? */
36377 +#if 0 //vahrama !!!!!!!!!!!!!!!!!!
36378 +                       if (core_if->adp_enable) {
36379 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36380 +                               gpwrdn_data_t gpwrdn;
36381 +
36382 +                               while (gotgctl.b.asesvld == 1) {
36383 +                                       gotgctl.d32 =
36384 +                                           DWC_READ_REG32(&core_if->
36385 +                                                          core_global_regs->
36386 +                                                          gotgctl);
36387 +                                       dwc_mdelay(100);
36388 +                               }
36389 +
36390 +                               /* Enable Power Down Logic */
36391 +                               gpwrdn.d32 = 0;
36392 +                               gpwrdn.b.pmuactv = 1;
36393 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36394 +                                                gpwrdn, 0, gpwrdn.d32);
36395 +
36396 +                               /* Unmask SRP detected interrupt from Power Down Logic */
36397 +                               gpwrdn.d32 = 0;
36398 +                               gpwrdn.b.srp_det_msk = 1;
36399 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36400 +                                                gpwrdn, 0, gpwrdn.d32);
36401 +
36402 +                               dwc_otg_adp_probe_start(core_if);
36403 +                       }
36404 +#endif
36405 +                       break;
36406 +               case UHF_PORT_POWER:
36407 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36408 +                                   "SetPortFeature - USB_PORT_FEAT_POWER\n");
36409 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36410 +                       hprt0.b.prtpwr = 1;
36411 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36412 +                       break;
36413 +               case UHF_PORT_RESET:
36414 +                       if ((core_if->power_down == 2)
36415 +                           && (core_if->hibernation_suspend == 1)) {
36416 +                               /* If we are going to exit from Hibernated
36417 +                                * state via USB RESET.
36418 +                                */
36419 +                               dwc_otg_host_hibernation_restore(core_if, 0, 1);
36420 +                       } else {
36421 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36422 +
36423 +                               DWC_DEBUGPL(DBG_HCD,
36424 +                                           "DWC OTG HCD HUB CONTROL - "
36425 +                                           "SetPortFeature - USB_PORT_FEAT_RESET\n");
36426 +                               {
36427 +                                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36428 +                                       pcgcctl.b.enbl_sleep_gating = 1;
36429 +                                       pcgcctl.b.stoppclk = 1;
36430 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36431 +                                       DWC_WRITE_REG32(core_if->pcgcctl, 0);
36432 +                               }
36433 +#ifdef CONFIG_USB_DWC_OTG_LPM
36434 +                               {
36435 +                                       glpmcfg_data_t lpmcfg;
36436 +                                       lpmcfg.d32 =
36437 +                                               DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36438 +                                       if (lpmcfg.b.prt_sleep_sts) {
36439 +                                               lpmcfg.b.en_utmi_sleep = 0;
36440 +                                               lpmcfg.b.hird_thres &= (~(1 << 4));
36441 +                                               DWC_WRITE_REG32
36442 +                                                   (&core_if->core_global_regs->glpmcfg,
36443 +                                                    lpmcfg.d32);
36444 +                                               dwc_mdelay(1);
36445 +                                       }
36446 +                               }
36447 +#endif
36448 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36449 +                               /* Clear suspend bit if resetting from suspended state. */
36450 +                               hprt0.b.prtsusp = 0;
36451 +                               /* When B-Host the Port reset bit is set in
36452 +                                * the Start HCD Callback function, so that
36453 +                                * the reset is started within 1ms of the HNP
36454 +                                * success interrupt. */
36455 +                               if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
36456 +                                       hprt0.b.prtpwr = 1;
36457 +                                       hprt0.b.prtrst = 1;
36458 +                                       DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
36459 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36460 +                                                       hprt0.d32);
36461 +                               }
36462 +                               /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
36463 +                               dwc_mdelay(60);
36464 +                               hprt0.b.prtrst = 0;
36465 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36466 +                               core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
36467 +                       }
36468 +                       break;
36469 +#ifdef DWC_HS_ELECT_TST
36470 +               case UHF_PORT_TEST:
36471 +                       {
36472 +                               uint32_t t;
36473 +                               gintmsk_data_t gintmsk;
36474 +
36475 +                               t = (wIndex >> 8);      /* MSB wIndex USB */
36476 +                               DWC_DEBUGPL(DBG_HCD,
36477 +                                           "DWC OTG HCD HUB CONTROL - "
36478 +                                           "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
36479 +                                           t);
36480 +                               DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
36481 +                               if (t < 6) {
36482 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36483 +                                       hprt0.b.prttstctl = t;
36484 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36485 +                                                       hprt0.d32);
36486 +                               } else {
36487 +                                       /* Setup global vars with reg addresses (quick and
36488 +                                        * dirty hack, should be cleaned up)
36489 +                                        */
36490 +                                       global_regs = core_if->core_global_regs;
36491 +                                       hc_global_regs =
36492 +                                           core_if->host_if->host_global_regs;
36493 +                                       hc_regs =
36494 +                                           (dwc_otg_hc_regs_t *) ((char *)
36495 +                                                                  global_regs +
36496 +                                                                  0x500);
36497 +                                       data_fifo =
36498 +                                           (uint32_t *) ((char *)global_regs +
36499 +                                                         0x1000);
36500 +
36501 +                                       if (t == 6) {   /* HS_HOST_PORT_SUSPEND_RESUME */
36502 +                                               /* Save current interrupt mask */
36503 +                                               gintmsk.d32 =
36504 +                                                   DWC_READ_REG32
36505 +                                                   (&global_regs->gintmsk);
36506 +
36507 +                                               /* Disable all interrupts while we muck with
36508 +                                                * the hardware directly
36509 +                                                */
36510 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36511 +
36512 +                                               /* 15 second delay per the test spec */
36513 +                                               dwc_mdelay(15000);
36514 +
36515 +                                               /* Drive suspend on the root port */
36516 +                                               hprt0.d32 =
36517 +                                                   dwc_otg_read_hprt0(core_if);
36518 +                                               hprt0.b.prtsusp = 1;
36519 +                                               hprt0.b.prtres = 0;
36520 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36521 +
36522 +                                               /* 15 second delay per the test spec */
36523 +                                               dwc_mdelay(15000);
36524 +
36525 +                                               /* Drive resume on the root port */
36526 +                                               hprt0.d32 =
36527 +                                                   dwc_otg_read_hprt0(core_if);
36528 +                                               hprt0.b.prtsusp = 0;
36529 +                                               hprt0.b.prtres = 1;
36530 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36531 +                                               dwc_mdelay(100);
36532 +
36533 +                                               /* Clear the resume bit */
36534 +                                               hprt0.b.prtres = 0;
36535 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36536 +
36537 +                                               /* Restore interrupts */
36538 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36539 +                                       } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
36540 +                                               /* Save current interrupt mask */
36541 +                                               gintmsk.d32 =
36542 +                                                   DWC_READ_REG32
36543 +                                                   (&global_regs->gintmsk);
36544 +
36545 +                                               /* Disable all interrupts while we muck with
36546 +                                                * the hardware directly
36547 +                                                */
36548 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36549 +
36550 +                                               /* 15 second delay per the test spec */
36551 +                                               dwc_mdelay(15000);
36552 +
36553 +                                               /* Send the Setup packet */
36554 +                                               do_setup();
36555 +
36556 +                                               /* 15 second delay so nothing else happens for awhile */
36557 +                                               dwc_mdelay(15000);
36558 +
36559 +                                               /* Restore interrupts */
36560 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36561 +                                       } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
36562 +                                               /* Save current interrupt mask */
36563 +                                               gintmsk.d32 =
36564 +                                                   DWC_READ_REG32
36565 +                                                   (&global_regs->gintmsk);
36566 +
36567 +                                               /* Disable all interrupts while we muck with
36568 +                                                * the hardware directly
36569 +                                                */
36570 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36571 +
36572 +                                               /* Send the Setup packet */
36573 +                                               do_setup();
36574 +
36575 +                                               /* 15 second delay so nothing else happens for awhile */
36576 +                                               dwc_mdelay(15000);
36577 +
36578 +                                               /* Send the In and Ack packets */
36579 +                                               do_in_ack();
36580 +
36581 +                                               /* 15 second delay so nothing else happens for awhile */
36582 +                                               dwc_mdelay(15000);
36583 +
36584 +                                               /* Restore interrupts */
36585 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36586 +                                       }
36587 +                               }
36588 +                               break;
36589 +                       }
36590 +#endif /* DWC_HS_ELECT_TST */
36591 +
36592 +               case UHF_PORT_INDICATOR:
36593 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36594 +                                   "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
36595 +                       /* Not supported */
36596 +                       break;
36597 +               default:
36598 +                       retval = -DWC_E_INVALID;
36599 +                       DWC_ERROR("DWC OTG HCD - "
36600 +                                 "SetPortFeature request %xh "
36601 +                                 "unknown or unsupported\n", wValue);
36602 +                       break;
36603 +               }
36604 +               break;
36605 +#ifdef CONFIG_USB_DWC_OTG_LPM
36606 +       case UCR_SET_AND_TEST_PORT_FEATURE:
36607 +               if (wValue != UHF_PORT_L1) {
36608 +                       goto error;
36609 +               }
36610 +               {
36611 +                       int portnum, hird, devaddr, remwake;
36612 +                       glpmcfg_data_t lpmcfg;
36613 +                       uint32_t time_usecs;
36614 +                       gintsts_data_t gintsts;
36615 +                       gintmsk_data_t gintmsk;
36616 +
36617 +                       if (!dwc_otg_get_param_lpm_enable(core_if)) {
36618 +                               goto error;
36619 +                       }
36620 +                       if (wValue != UHF_PORT_L1 || wLength != 1) {
36621 +                               goto error;
36622 +                       }
36623 +                       /* Check if the port currently is in SLEEP state */
36624 +                       lpmcfg.d32 =
36625 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36626 +                       if (lpmcfg.b.prt_sleep_sts) {
36627 +                               DWC_INFO("Port is already in sleep mode\n");
36628 +                               buf[0] = 0;     /* Return success */
36629 +                               break;
36630 +                       }
36631 +
36632 +                       portnum = wIndex & 0xf;
36633 +                       hird = (wIndex >> 4) & 0xf;
36634 +                       devaddr = (wIndex >> 8) & 0x7f;
36635 +                       remwake = (wIndex >> 15);
36636 +
36637 +                       if (portnum != 1) {
36638 +                               retval = -DWC_E_INVALID;
36639 +                               DWC_WARN
36640 +                                   ("Wrong port number(%d) in SetandTestPortFeature request\n",
36641 +                                    portnum);
36642 +                               break;
36643 +                       }
36644 +
36645 +                       DWC_PRINTF
36646 +                           ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
36647 +                            portnum, hird, devaddr, remwake);
36648 +                       /* Disable LPM interrupt */
36649 +                       gintmsk.d32 = 0;
36650 +                       gintmsk.b.lpmtranrcvd = 1;
36651 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
36652 +                                        gintmsk.d32, 0);
36653 +
36654 +                       if (dwc_otg_hcd_send_lpm
36655 +                           (dwc_otg_hcd, devaddr, hird, remwake)) {
36656 +                               retval = -DWC_E_INVALID;
36657 +                               break;
36658 +                       }
36659 +
36660 +                       time_usecs = 10 * (lpmcfg.b.retry_count + 1);
36661 +                       /* We will consider timeout if time_usecs microseconds pass,
36662 +                        * and we don't receive LPM transaction status.
36663 +                        * After receiving non-error responce(ACK/NYET/STALL) from device,
36664 +                        *  core will set lpmtranrcvd bit.
36665 +                        */
36666 +                       do {
36667 +                               gintsts.d32 =
36668 +                                   DWC_READ_REG32(&core_if->core_global_regs->gintsts);
36669 +                               if (gintsts.b.lpmtranrcvd) {
36670 +                                       break;
36671 +                               }
36672 +                               dwc_udelay(1);
36673 +                       } while (--time_usecs);
36674 +                       /* lpm_int bit will be cleared in LPM interrupt handler */
36675 +
36676 +                       /* Now fill status
36677 +                        * 0x00 - Success
36678 +                        * 0x10 - NYET
36679 +                        * 0x11 - Timeout
36680 +                        */
36681 +                       if (!gintsts.b.lpmtranrcvd) {
36682 +                               buf[0] = 0x3;   /* Completion code is Timeout */
36683 +                               dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
36684 +                       } else {
36685 +                               lpmcfg.d32 =
36686 +                                   DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36687 +                               if (lpmcfg.b.lpm_resp == 0x3) {
36688 +                                       /* ACK responce from the device */
36689 +                                       buf[0] = 0x00;  /* Success */
36690 +                               } else if (lpmcfg.b.lpm_resp == 0x2) {
36691 +                                       /* NYET responce from the device */
36692 +                                       buf[0] = 0x2;
36693 +                               } else {
36694 +                                       /* Otherwise responce with Timeout */
36695 +                                       buf[0] = 0x3;
36696 +                               }
36697 +                       }
36698 +                       DWC_PRINTF("Device responce to LPM trans is %x\n",
36699 +                                  lpmcfg.b.lpm_resp);
36700 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
36701 +                                        gintmsk.d32);
36702 +
36703 +                       break;
36704 +               }
36705 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36706 +       default:
36707 +error:
36708 +               retval = -DWC_E_INVALID;
36709 +               DWC_WARN("DWC OTG HCD - "
36710 +                        "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
36711 +                        typeReq, wIndex, wValue);
36712 +               break;
36713 +       }
36714 +
36715 +       return retval;
36716 +}
36717 +
36718 +#ifdef CONFIG_USB_DWC_OTG_LPM
36719 +/** Returns index of host channel to perform LPM transaction. */
36720 +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
36721 +{
36722 +       dwc_otg_core_if_t *core_if = hcd->core_if;
36723 +       dwc_hc_t *hc;
36724 +       hcchar_data_t hcchar;
36725 +       gintmsk_data_t gintmsk = {.d32 = 0 };
36726 +
36727 +       if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
36728 +               DWC_PRINTF("No free channel to select for LPM transaction\n");
36729 +               return -1;
36730 +       }
36731 +
36732 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
36733 +
36734 +       /* Mask host channel interrupts. */
36735 +       gintmsk.b.hcintr = 1;
36736 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
36737 +
36738 +       /* Fill fields that core needs for LPM transaction */
36739 +       hcchar.b.devaddr = devaddr;
36740 +       hcchar.b.epnum = 0;
36741 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36742 +       hcchar.b.mps = 64;
36743 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
36744 +       hcchar.b.epdir = 0;     /* OUT */
36745 +       DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
36746 +                       hcchar.d32);
36747 +
36748 +       /* Remove the host channel from the free list. */
36749 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
36750 +
36751 +       DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
36752 +
36753 +       return hc->hc_num;
36754 +}
36755 +
36756 +/** Release hc after performing LPM transaction */
36757 +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
36758 +{
36759 +       dwc_hc_t *hc;
36760 +       glpmcfg_data_t lpmcfg;
36761 +       uint8_t hc_num;
36762 +
36763 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36764 +       hc_num = lpmcfg.b.lpm_chan_index;
36765 +
36766 +       hc = hcd->hc_ptr_array[hc_num];
36767 +
36768 +       DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
36769 +       /* Return host channel to free list */
36770 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
36771 +}
36772 +
36773 +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
36774 +                        uint8_t bRemoteWake)
36775 +{
36776 +       glpmcfg_data_t lpmcfg;
36777 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36778 +       int channel;
36779 +
36780 +       channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
36781 +       if (channel < 0) {
36782 +               return channel;
36783 +       }
36784 +
36785 +       pcgcctl.b.enbl_sleep_gating = 1;
36786 +       DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
36787 +
36788 +       /* Read LPM config register */
36789 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36790 +
36791 +       /* Program LPM transaction fields */
36792 +       lpmcfg.b.rem_wkup_en = bRemoteWake;
36793 +       lpmcfg.b.hird = hird;
36794 +       lpmcfg.b.hird_thres = 0x1c;
36795 +       lpmcfg.b.lpm_chan_index = channel;
36796 +       lpmcfg.b.en_utmi_sleep = 1;
36797 +       /* Program LPM config register */
36798 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36799 +
36800 +       /* Send LPM transaction */
36801 +       lpmcfg.b.send_lpm = 1;
36802 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36803 +
36804 +       return 0;
36805 +}
36806 +
36807 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36808 +
36809 +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
36810 +{
36811 +       int retval;
36812 +
36813 +       if (port != 1) {
36814 +               return -DWC_E_INVALID;
36815 +       }
36816 +
36817 +       retval = (hcd->flags.b.port_connect_status_change ||
36818 +                 hcd->flags.b.port_reset_change ||
36819 +                 hcd->flags.b.port_enable_change ||
36820 +                 hcd->flags.b.port_suspend_change ||
36821 +                 hcd->flags.b.port_over_current_change);
36822 +#ifdef DEBUG
36823 +       if (retval) {
36824 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
36825 +                           " Root port status changed\n");
36826 +               DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
36827 +                           hcd->flags.b.port_connect_status_change);
36828 +               DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
36829 +                           hcd->flags.b.port_reset_change);
36830 +               DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
36831 +                           hcd->flags.b.port_enable_change);
36832 +               DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
36833 +                           hcd->flags.b.port_suspend_change);
36834 +               DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
36835 +                           hcd->flags.b.port_over_current_change);
36836 +       }
36837 +#endif
36838 +       return retval;
36839 +}
36840 +
36841 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
36842 +{
36843 +       hfnum_data_t hfnum;
36844 +       hfnum.d32 =
36845 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
36846 +                          hfnum);
36847 +
36848 +#ifdef DEBUG_SOF
36849 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
36850 +                   hfnum.b.frnum);
36851 +#endif
36852 +       return hfnum.b.frnum;
36853 +}
36854 +
36855 +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
36856 +                     struct dwc_otg_hcd_function_ops *fops)
36857 +{
36858 +       int retval = 0;
36859 +
36860 +       hcd->fops = fops;
36861 +       if (!dwc_otg_is_device_mode(hcd->core_if) &&
36862 +               (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
36863 +               dwc_otg_hcd_reinit(hcd);
36864 +       } else {
36865 +               retval = -DWC_E_NO_DEVICE;
36866 +       }
36867 +
36868 +       return retval;
36869 +}
36870 +
36871 +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
36872 +{
36873 +       return hcd->priv;
36874 +}
36875 +
36876 +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
36877 +{
36878 +       hcd->priv = priv_data;
36879 +}
36880 +
36881 +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
36882 +{
36883 +       return hcd->otg_port;
36884 +}
36885 +
36886 +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
36887 +{
36888 +       uint32_t is_b_host;
36889 +       if (hcd->core_if->op_state == B_HOST) {
36890 +               is_b_host = 1;
36891 +       } else {
36892 +               is_b_host = 0;
36893 +       }
36894 +
36895 +       return is_b_host;
36896 +}
36897 +
36898 +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
36899 +                                        int iso_desc_count, int atomic_alloc)
36900 +{
36901 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
36902 +       uint32_t size;
36903 +
36904 +       size =
36905 +           sizeof(*dwc_otg_urb) +
36906 +           iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
36907 +       if (atomic_alloc)
36908 +               dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
36909 +       else
36910 +               dwc_otg_urb = DWC_ALLOC(size);
36911 +
36912 +        if (NULL != dwc_otg_urb)
36913 +                dwc_otg_urb->packet_count = iso_desc_count;
36914 +        else {
36915 +                dwc_otg_urb->packet_count = 0;
36916 +                if (size != 0) {
36917 +                        DWC_ERROR("**** DWC OTG HCD URB alloc - "
36918 +                                  "%salloc of %db failed\n",
36919 +                                  atomic_alloc?"atomic ":"", size);
36920 +                }
36921 +        }
36922 +
36923 +       return dwc_otg_urb;
36924 +}
36925 +
36926 +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
36927 +                                 uint8_t dev_addr, uint8_t ep_num,
36928 +                                 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
36929 +{
36930 +       dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
36931 +                             ep_type, ep_dir, mps);
36932 +#if 0
36933 +       DWC_PRINTF
36934 +           ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
36935 +            dev_addr, ep_num, ep_dir, ep_type, mps);
36936 +#endif
36937 +}
36938 +
36939 +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
36940 +                               void *urb_handle, void *buf, dwc_dma_t dma,
36941 +                               uint32_t buflen, void *setup_packet,
36942 +                               dwc_dma_t setup_dma, uint32_t flags,
36943 +                               uint16_t interval)
36944 +{
36945 +       dwc_otg_urb->priv = urb_handle;
36946 +       dwc_otg_urb->buf = buf;
36947 +       dwc_otg_urb->dma = dma;
36948 +       dwc_otg_urb->length = buflen;
36949 +       dwc_otg_urb->setup_packet = setup_packet;
36950 +       dwc_otg_urb->setup_dma = setup_dma;
36951 +       dwc_otg_urb->flags = flags;
36952 +       dwc_otg_urb->interval = interval;
36953 +       dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
36954 +}
36955 +
36956 +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
36957 +{
36958 +       return dwc_otg_urb->status;
36959 +}
36960 +
36961 +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
36962 +{
36963 +       return dwc_otg_urb->actual_length;
36964 +}
36965 +
36966 +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
36967 +{
36968 +       return dwc_otg_urb->error_count;
36969 +}
36970 +
36971 +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
36972 +                                        int desc_num, uint32_t offset,
36973 +                                        uint32_t length)
36974 +{
36975 +       dwc_otg_urb->iso_descs[desc_num].offset = offset;
36976 +       dwc_otg_urb->iso_descs[desc_num].length = length;
36977 +}
36978 +
36979 +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
36980 +                                            int desc_num)
36981 +{
36982 +       return dwc_otg_urb->iso_descs[desc_num].status;
36983 +}
36984 +
36985 +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
36986 +                                                   dwc_otg_urb, int desc_num)
36987 +{
36988 +       return dwc_otg_urb->iso_descs[desc_num].actual_length;
36989 +}
36990 +
36991 +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
36992 +{
36993 +       int allocated = 0;
36994 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
36995 +
36996 +       if (qh) {
36997 +               if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
36998 +                       allocated = 1;
36999 +               }
37000 +       }
37001 +       return allocated;
37002 +}
37003 +
37004 +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
37005 +{
37006 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37007 +       int freed = 0;
37008 +       DWC_ASSERT(qh, "qh is not allocated\n");
37009 +
37010 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37011 +               freed = 1;
37012 +       }
37013 +
37014 +       return freed;
37015 +}
37016 +
37017 +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
37018 +{
37019 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37020 +       DWC_ASSERT(qh, "qh is not allocated\n");
37021 +       return qh->usecs;
37022 +}
37023 +
37024 +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
37025 +{
37026 +#ifdef DEBUG
37027 +       int num_channels;
37028 +       int i;
37029 +       gnptxsts_data_t np_tx_status;
37030 +       hptxsts_data_t p_tx_status;
37031 +
37032 +       num_channels = hcd->core_if->core_params->host_channels;
37033 +       DWC_PRINTF("\n");
37034 +       DWC_PRINTF
37035 +           ("************************************************************\n");
37036 +       DWC_PRINTF("HCD State:\n");
37037 +       DWC_PRINTF("  Num channels: %d\n", num_channels);
37038 +       for (i = 0; i < num_channels; i++) {
37039 +               dwc_hc_t *hc = hcd->hc_ptr_array[i];
37040 +               DWC_PRINTF("  Channel %d:\n", i);
37041 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
37042 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
37043 +               DWC_PRINTF("    speed: %d\n", hc->speed);
37044 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
37045 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
37046 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
37047 +               DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
37048 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
37049 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
37050 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
37051 +               DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
37052 +               DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
37053 +               DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
37054 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
37055 +               DWC_PRINTF("    do_split: %d\n", hc->do_split);
37056 +               DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
37057 +               DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
37058 +               DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
37059 +               DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
37060 +               DWC_PRINTF("    requests: %d\n", hc->requests);
37061 +               DWC_PRINTF("    qh: %p\n", hc->qh);
37062 +               if (hc->xfer_started) {
37063 +                       hfnum_data_t hfnum;
37064 +                       hcchar_data_t hcchar;
37065 +                       hctsiz_data_t hctsiz;
37066 +                       hcint_data_t hcint;
37067 +                       hcintmsk_data_t hcintmsk;
37068 +                       hfnum.d32 =
37069 +                           DWC_READ_REG32(&hcd->core_if->
37070 +                                          host_if->host_global_regs->hfnum);
37071 +                       hcchar.d32 =
37072 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37073 +                                          hc_regs[i]->hcchar);
37074 +                       hctsiz.d32 =
37075 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37076 +                                          hc_regs[i]->hctsiz);
37077 +                       hcint.d32 =
37078 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37079 +                                          hc_regs[i]->hcint);
37080 +                       hcintmsk.d32 =
37081 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37082 +                                          hc_regs[i]->hcintmsk);
37083 +                       DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
37084 +                       DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
37085 +                       DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
37086 +                       DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
37087 +                       DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
37088 +               }
37089 +               if (hc->xfer_started && hc->qh) {
37090 +                       dwc_otg_qtd_t *qtd;
37091 +                       dwc_otg_hcd_urb_t *urb;
37092 +
37093 +                       DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
37094 +                               if (!qtd->in_process)
37095 +                                       break;
37096 +
37097 +                               urb = qtd->urb;
37098 +                       DWC_PRINTF("    URB Info:\n");
37099 +                       DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
37100 +                       if (urb) {
37101 +                               DWC_PRINTF("      Dev: %d, EP: %d %s\n",
37102 +                                          dwc_otg_hcd_get_dev_addr(&urb->
37103 +                                                                   pipe_info),
37104 +                                          dwc_otg_hcd_get_ep_num(&urb->
37105 +                                                                 pipe_info),
37106 +                                          dwc_otg_hcd_is_pipe_in(&urb->
37107 +                                                                 pipe_info) ?
37108 +                                          "IN" : "OUT");
37109 +                               DWC_PRINTF("      Max packet size: %d\n",
37110 +                                          dwc_otg_hcd_get_mps(&urb->
37111 +                                                              pipe_info));
37112 +                               DWC_PRINTF("      transfer_buffer: %p\n",
37113 +                                          urb->buf);
37114 +                               DWC_PRINTF("      transfer_dma: %p\n",
37115 +                                          (void *)urb->dma);
37116 +                               DWC_PRINTF("      transfer_buffer_length: %d\n",
37117 +                                          urb->length);
37118 +                                       DWC_PRINTF("      actual_length: %d\n",
37119 +                                                  urb->actual_length);
37120 +                               }
37121 +                       }
37122 +               }
37123 +       }
37124 +       DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
37125 +       DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
37126 +       DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
37127 +       np_tx_status.d32 =
37128 +           DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
37129 +       DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
37130 +                  np_tx_status.b.nptxqspcavail);
37131 +       DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
37132 +                  np_tx_status.b.nptxfspcavail);
37133 +       p_tx_status.d32 =
37134 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
37135 +       DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
37136 +                  p_tx_status.b.ptxqspcavail);
37137 +       DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
37138 +       dwc_otg_hcd_dump_frrem(hcd);
37139 +       dwc_otg_dump_global_registers(hcd->core_if);
37140 +       dwc_otg_dump_host_registers(hcd->core_if);
37141 +       DWC_PRINTF
37142 +           ("************************************************************\n");
37143 +       DWC_PRINTF("\n");
37144 +#endif
37145 +}
37146 +
37147 +#ifdef DEBUG
37148 +void dwc_print_setup_data(uint8_t * setup)
37149 +{
37150 +       int i;
37151 +       if (CHK_DEBUG_LEVEL(DBG_HCD)) {
37152 +               DWC_PRINTF("Setup Data = MSB ");
37153 +               for (i = 7; i >= 0; i--)
37154 +                       DWC_PRINTF("%02x ", setup[i]);
37155 +               DWC_PRINTF("\n");
37156 +               DWC_PRINTF("  bmRequestType Tranfer = %s\n",
37157 +                          (setup[0] & 0x80) ? "Device-to-Host" :
37158 +                          "Host-to-Device");
37159 +               DWC_PRINTF("  bmRequestType Type = ");
37160 +               switch ((setup[0] & 0x60) >> 5) {
37161 +               case 0:
37162 +                       DWC_PRINTF("Standard\n");
37163 +                       break;
37164 +               case 1:
37165 +                       DWC_PRINTF("Class\n");
37166 +                       break;
37167 +               case 2:
37168 +                       DWC_PRINTF("Vendor\n");
37169 +                       break;
37170 +               case 3:
37171 +                       DWC_PRINTF("Reserved\n");
37172 +                       break;
37173 +               }
37174 +               DWC_PRINTF("  bmRequestType Recipient = ");
37175 +               switch (setup[0] & 0x1f) {
37176 +               case 0:
37177 +                       DWC_PRINTF("Device\n");
37178 +                       break;
37179 +               case 1:
37180 +                       DWC_PRINTF("Interface\n");
37181 +                       break;
37182 +               case 2:
37183 +                       DWC_PRINTF("Endpoint\n");
37184 +                       break;
37185 +               case 3:
37186 +                       DWC_PRINTF("Other\n");
37187 +                       break;
37188 +               default:
37189 +                       DWC_PRINTF("Reserved\n");
37190 +                       break;
37191 +               }
37192 +               DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
37193 +               DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
37194 +               DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
37195 +               DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
37196 +       }
37197 +}
37198 +#endif
37199 +
37200 +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
37201 +{
37202 +#if 0
37203 +       DWC_PRINTF("Frame remaining at SOF:\n");
37204 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37205 +                  hcd->frrem_samples, hcd->frrem_accum,
37206 +                  (hcd->frrem_samples > 0) ?
37207 +                  hcd->frrem_accum / hcd->frrem_samples : 0);
37208 +
37209 +       DWC_PRINTF("\n");
37210 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
37211 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37212 +                  hcd->core_if->hfnum_7_samples,
37213 +                  hcd->core_if->hfnum_7_frrem_accum,
37214 +                  (hcd->core_if->hfnum_7_samples >
37215 +                   0) ? hcd->core_if->hfnum_7_frrem_accum /
37216 +                  hcd->core_if->hfnum_7_samples : 0);
37217 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
37218 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37219 +                  hcd->core_if->hfnum_0_samples,
37220 +                  hcd->core_if->hfnum_0_frrem_accum,
37221 +                  (hcd->core_if->hfnum_0_samples >
37222 +                   0) ? hcd->core_if->hfnum_0_frrem_accum /
37223 +                  hcd->core_if->hfnum_0_samples : 0);
37224 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
37225 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37226 +                  hcd->core_if->hfnum_other_samples,
37227 +                  hcd->core_if->hfnum_other_frrem_accum,
37228 +                  (hcd->core_if->hfnum_other_samples >
37229 +                   0) ? hcd->core_if->hfnum_other_frrem_accum /
37230 +                  hcd->core_if->hfnum_other_samples : 0);
37231 +
37232 +       DWC_PRINTF("\n");
37233 +       DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
37234 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37235 +                  hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
37236 +                  (hcd->hfnum_7_samples_a > 0) ?
37237 +                  hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
37238 +       DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
37239 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37240 +                  hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
37241 +                  (hcd->hfnum_0_samples_a > 0) ?
37242 +                  hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
37243 +       DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
37244 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37245 +                  hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
37246 +                  (hcd->hfnum_other_samples_a > 0) ?
37247 +                  hcd->hfnum_other_frrem_accum_a /
37248 +                  hcd->hfnum_other_samples_a : 0);
37249 +
37250 +       DWC_PRINTF("\n");
37251 +       DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
37252 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37253 +                  hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
37254 +                  (hcd->hfnum_7_samples_b > 0) ?
37255 +                  hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
37256 +       DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
37257 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37258 +                  hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
37259 +                  (hcd->hfnum_0_samples_b > 0) ?
37260 +                  hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
37261 +       DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
37262 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37263 +                  hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
37264 +                  (hcd->hfnum_other_samples_b > 0) ?
37265 +                  hcd->hfnum_other_frrem_accum_b /
37266 +                  hcd->hfnum_other_samples_b : 0);
37267 +#endif
37268 +}
37269 +
37270 +#endif /* DWC_DEVICE_ONLY */
37271 --- /dev/null
37272 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
37273 @@ -0,0 +1,824 @@
37274 +/* ==========================================================================
37275 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
37276 + * $Revision: #58 $
37277 + * $Date: 2011/09/15 $
37278 + * $Change: 1846647 $
37279 + *
37280 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
37281 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
37282 + * otherwise expressly agreed to in writing between Synopsys and you.
37283 + *
37284 + * The Software IS NOT an item of Licensed Software or Licensed Product under
37285 + * any End User Software License Agreement or Agreement for Licensed Product
37286 + * with Synopsys or any supplement thereto. You are permitted to use and
37287 + * redistribute this Software in source and binary forms, with or without
37288 + * modification, provided that redistributions of source code must retain this
37289 + * notice. You may not view, use, disclose, copy or distribute this file or
37290 + * any information contained herein except pursuant to this license grant from
37291 + * Synopsys. If you do not agree with this notice, including the disclaimer
37292 + * below, then you are not authorized to use the Software.
37293 + *
37294 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
37295 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37296 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37297 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
37298 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37299 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37300 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37301 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37302 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37303 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
37304 + * DAMAGE.
37305 + * ========================================================================== */
37306 +#ifndef DWC_DEVICE_ONLY
37307 +#ifndef __DWC_HCD_H__
37308 +#define __DWC_HCD_H__
37309 +
37310 +#include "dwc_otg_os_dep.h"
37311 +#include "usb.h"
37312 +#include "dwc_otg_hcd_if.h"
37313 +#include "dwc_otg_core_if.h"
37314 +#include "dwc_list.h"
37315 +#include "dwc_otg_cil.h"
37316 +
37317 +/**
37318 + * @file
37319 + *
37320 + * This file contains the structures, constants, and interfaces for
37321 + * the Host Contoller Driver (HCD).
37322 + *
37323 + * The Host Controller Driver (HCD) is responsible for translating requests
37324 + * from the USB Driver into the appropriate actions on the DWC_otg controller.
37325 + * It isolates the USBD from the specifics of the controller by providing an
37326 + * API to the USBD.
37327 + */
37328 +
37329 +struct dwc_otg_hcd_pipe_info {
37330 +       uint8_t dev_addr;
37331 +       uint8_t ep_num;
37332 +       uint8_t pipe_type;
37333 +       uint8_t pipe_dir;
37334 +       uint16_t mps;
37335 +};
37336 +
37337 +struct dwc_otg_hcd_iso_packet_desc {
37338 +       uint32_t offset;
37339 +       uint32_t length;
37340 +       uint32_t actual_length;
37341 +       uint32_t status;
37342 +};
37343 +
37344 +struct dwc_otg_qtd;
37345 +
37346 +struct dwc_otg_hcd_urb {
37347 +       void *priv;
37348 +       struct dwc_otg_qtd *qtd;
37349 +       void *buf;
37350 +       dwc_dma_t dma;
37351 +       void *setup_packet;
37352 +       dwc_dma_t setup_dma;
37353 +       uint32_t length;
37354 +       uint32_t actual_length;
37355 +       uint32_t status;
37356 +       uint32_t error_count;
37357 +       uint32_t packet_count;
37358 +       uint32_t flags;
37359 +       uint16_t interval;
37360 +       struct dwc_otg_hcd_pipe_info pipe_info;
37361 +       struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
37362 +};
37363 +
37364 +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
37365 +{
37366 +       return pipe->ep_num;
37367 +}
37368 +
37369 +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
37370 +                                               *pipe)
37371 +{
37372 +       return pipe->pipe_type;
37373 +}
37374 +
37375 +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
37376 +{
37377 +       return pipe->mps;
37378 +}
37379 +
37380 +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
37381 +                                              *pipe)
37382 +{
37383 +       return pipe->dev_addr;
37384 +}
37385 +
37386 +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
37387 +                                              *pipe)
37388 +{
37389 +       return (pipe->pipe_type == UE_ISOCHRONOUS);
37390 +}
37391 +
37392 +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
37393 +                                             *pipe)
37394 +{
37395 +       return (pipe->pipe_type == UE_INTERRUPT);
37396 +}
37397 +
37398 +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
37399 +                                              *pipe)
37400 +{
37401 +       return (pipe->pipe_type == UE_BULK);
37402 +}
37403 +
37404 +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
37405 +                                                 *pipe)
37406 +{
37407 +       return (pipe->pipe_type == UE_CONTROL);
37408 +}
37409 +
37410 +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
37411 +{
37412 +       return (pipe->pipe_dir == UE_DIR_IN);
37413 +}
37414 +
37415 +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
37416 +                                             *pipe)
37417 +{
37418 +       return (!dwc_otg_hcd_is_pipe_in(pipe));
37419 +}
37420 +
37421 +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
37422 +                                        uint8_t devaddr, uint8_t ep_num,
37423 +                                        uint8_t pipe_type, uint8_t pipe_dir,
37424 +                                        uint16_t mps)
37425 +{
37426 +       pipe->dev_addr = devaddr;
37427 +       pipe->ep_num = ep_num;
37428 +       pipe->pipe_type = pipe_type;
37429 +       pipe->pipe_dir = pipe_dir;
37430 +       pipe->mps = mps;
37431 +}
37432 +
37433 +/**
37434 + * Phases for control transfers.
37435 + */
37436 +typedef enum dwc_otg_control_phase {
37437 +       DWC_OTG_CONTROL_SETUP,
37438 +       DWC_OTG_CONTROL_DATA,
37439 +       DWC_OTG_CONTROL_STATUS
37440 +} dwc_otg_control_phase_e;
37441 +
37442 +/** Transaction types. */
37443 +typedef enum dwc_otg_transaction_type {
37444 +       DWC_OTG_TRANSACTION_NONE,
37445 +       DWC_OTG_TRANSACTION_PERIODIC,
37446 +       DWC_OTG_TRANSACTION_NON_PERIODIC,
37447 +       DWC_OTG_TRANSACTION_ALL
37448 +} dwc_otg_transaction_type_e;
37449 +
37450 +struct dwc_otg_qh;
37451 +
37452 +/**
37453 + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
37454 + * interrupt, or isochronous transfer. A single QTD is created for each URB
37455 + * (of one of these types) submitted to the HCD. The transfer associated with
37456 + * a QTD may require one or multiple transactions.
37457 + *
37458 + * A QTD is linked to a Queue Head, which is entered in either the
37459 + * non-periodic or periodic schedule for execution. When a QTD is chosen for
37460 + * execution, some or all of its transactions may be executed. After
37461 + * execution, the state of the QTD is updated. The QTD may be retired if all
37462 + * its transactions are complete or if an error occurred. Otherwise, it
37463 + * remains in the schedule so more transactions can be executed later.
37464 + */
37465 +typedef struct dwc_otg_qtd {
37466 +       /**
37467 +        * Determines the PID of the next data packet for the data phase of
37468 +        * control transfers. Ignored for other transfer types.<br>
37469 +        * One of the following values:
37470 +        *      - DWC_OTG_HC_PID_DATA0
37471 +        *      - DWC_OTG_HC_PID_DATA1
37472 +        */
37473 +       uint8_t data_toggle;
37474 +
37475 +       /** Current phase for control transfers (Setup, Data, or Status). */
37476 +       dwc_otg_control_phase_e control_phase;
37477 +
37478 +       /** Keep track of the current split type
37479 +        * for FS/LS endpoints on a HS Hub */
37480 +       uint8_t complete_split;
37481 +
37482 +       /** How many bytes transferred during SSPLIT OUT */
37483 +       uint32_t ssplit_out_xfer_count;
37484 +
37485 +       /**
37486 +        * Holds the number of bus errors that have occurred for a transaction
37487 +        * within this transfer.
37488 +        */
37489 +       uint8_t error_count;
37490 +
37491 +       /**
37492 +        * Index of the next frame descriptor for an isochronous transfer. A
37493 +        * frame descriptor describes the buffer position and length of the
37494 +        * data to be transferred in the next scheduled (micro)frame of an
37495 +        * isochronous transfer. It also holds status for that transaction.
37496 +        * The frame index starts at 0.
37497 +        */
37498 +       uint16_t isoc_frame_index;
37499 +
37500 +       /** Position of the ISOC split on full/low speed */
37501 +       uint8_t isoc_split_pos;
37502 +
37503 +       /** Position of the ISOC split in the buffer for the current frame */
37504 +       uint16_t isoc_split_offset;
37505 +
37506 +       /** URB for this transfer */
37507 +       struct dwc_otg_hcd_urb *urb;
37508 +
37509 +       struct dwc_otg_qh *qh;
37510 +
37511 +       /** This list of QTDs */
37512 +        DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
37513 +
37514 +       /** Indicates if this QTD is currently processed by HW. */
37515 +       uint8_t in_process;
37516 +
37517 +       /** Number of DMA descriptors for this QTD */
37518 +       uint8_t n_desc;
37519 +
37520 +       /**
37521 +        * Last activated frame(packet) index.
37522 +        * Used in Descriptor DMA mode only.
37523 +        */
37524 +       uint16_t isoc_frame_index_last;
37525 +
37526 +} dwc_otg_qtd_t;
37527 +
37528 +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
37529 +
37530 +/**
37531 + * A Queue Head (QH) holds the static characteristics of an endpoint and
37532 + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
37533 + * be entered in either the non-periodic or periodic schedule.
37534 + */
37535 +typedef struct dwc_otg_qh {
37536 +       /**
37537 +        * Endpoint type.
37538 +        * One of the following values:
37539 +        *      - UE_CONTROL
37540 +        *      - UE_BULK
37541 +        *      - UE_INTERRUPT
37542 +        *      - UE_ISOCHRONOUS
37543 +        */
37544 +       uint8_t ep_type;
37545 +       uint8_t ep_is_in;
37546 +
37547 +       /** wMaxPacketSize Field of Endpoint Descriptor. */
37548 +       uint16_t maxp;
37549 +
37550 +       /**
37551 +        * Device speed.
37552 +        * One of the following values:
37553 +        *      - DWC_OTG_EP_SPEED_LOW
37554 +        *      - DWC_OTG_EP_SPEED_FULL
37555 +        *      - DWC_OTG_EP_SPEED_HIGH
37556 +        */
37557 +       uint8_t dev_speed;
37558 +
37559 +       /**
37560 +        * Determines the PID of the next data packet for non-control
37561 +        * transfers. Ignored for control transfers.<br>
37562 +        * One of the following values:
37563 +        *      - DWC_OTG_HC_PID_DATA0
37564 +        *      - DWC_OTG_HC_PID_DATA1
37565 +        */
37566 +       uint8_t data_toggle;
37567 +
37568 +       /** Ping state if 1. */
37569 +       uint8_t ping_state;
37570 +
37571 +       /**
37572 +        * List of QTDs for this QH.
37573 +        */
37574 +       struct dwc_otg_qtd_list qtd_list;
37575 +
37576 +       /** Host channel currently processing transfers for this QH. */
37577 +       struct dwc_hc *channel;
37578 +
37579 +       /** Full/low speed endpoint on high-speed hub requires split. */
37580 +       uint8_t do_split;
37581 +
37582 +       /** @name Periodic schedule information */
37583 +       /** @{ */
37584 +
37585 +       /** Bandwidth in microseconds per (micro)frame. */
37586 +       uint16_t usecs;
37587 +
37588 +       /** Interval between transfers in (micro)frames. */
37589 +       uint16_t interval;
37590 +
37591 +       /**
37592 +        * (micro)frame to initialize a periodic transfer. The transfer
37593 +        * executes in the following (micro)frame.
37594 +        */
37595 +       uint16_t sched_frame;
37596 +
37597 +       /** (micro)frame at which last start split was initialized. */
37598 +       uint16_t start_split_frame;
37599 +
37600 +       /** @} */
37601 +
37602 +       /**
37603 +        * Used instead of original buffer if
37604 +        * it(physical address) is not dword-aligned.
37605 +        */
37606 +       uint8_t *dw_align_buf;
37607 +       dwc_dma_t dw_align_buf_dma;
37608 +
37609 +       /** Entry for QH in either the periodic or non-periodic schedule. */
37610 +       dwc_list_link_t qh_list_entry;
37611 +
37612 +       /** @name Descriptor DMA support */
37613 +       /** @{ */
37614 +
37615 +       /** Descriptor List. */
37616 +       dwc_otg_host_dma_desc_t *desc_list;
37617 +
37618 +       /** Descriptor List physical address. */
37619 +       dwc_dma_t desc_list_dma;
37620 +
37621 +       /**
37622 +        * Xfer Bytes array.
37623 +        * Each element corresponds to a descriptor and indicates
37624 +        * original XferSize size value for the descriptor.
37625 +        */
37626 +       uint32_t *n_bytes;
37627 +
37628 +       /** Actual number of transfer descriptors in a list. */
37629 +       uint16_t ntd;
37630 +
37631 +       /** First activated isochronous transfer descriptor index. */
37632 +       uint8_t td_first;
37633 +       /** Last activated isochronous transfer descriptor index. */
37634 +       uint8_t td_last;
37635 +
37636 +       /** @} */
37637 +
37638 +
37639 +       uint16_t speed;
37640 +       uint16_t frame_usecs[8];
37641 +} dwc_otg_qh_t;
37642 +
37643 +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
37644 +
37645 +/**
37646 + * This structure holds the state of the HCD, including the non-periodic and
37647 + * periodic schedules.
37648 + */
37649 +struct dwc_otg_hcd {
37650 +       /** The DWC otg device pointer */
37651 +       struct dwc_otg_device *otg_dev;
37652 +       /** DWC OTG Core Interface Layer */
37653 +       dwc_otg_core_if_t *core_if;
37654 +
37655 +       /** Function HCD driver callbacks */
37656 +       struct dwc_otg_hcd_function_ops *fops;
37657 +
37658 +       /** Internal DWC HCD Flags */
37659 +       volatile union dwc_otg_hcd_internal_flags {
37660 +               uint32_t d32;
37661 +               struct {
37662 +                       unsigned port_connect_status_change:1;
37663 +                       unsigned port_connect_status:1;
37664 +                       unsigned port_reset_change:1;
37665 +                       unsigned port_enable_change:1;
37666 +                       unsigned port_suspend_change:1;
37667 +                       unsigned port_over_current_change:1;
37668 +                       unsigned port_l1_change:1;
37669 +                       unsigned reserved:26;
37670 +               } b;
37671 +       } flags;
37672 +
37673 +       /**
37674 +        * Inactive items in the non-periodic schedule. This is a list of
37675 +        * Queue Heads. Transfers associated with these Queue Heads are not
37676 +        * currently assigned to a host channel.
37677 +        */
37678 +       dwc_list_link_t non_periodic_sched_inactive;
37679 +
37680 +       /**
37681 +        * Active items in the non-periodic schedule. This is a list of
37682 +        * Queue Heads. Transfers associated with these Queue Heads are
37683 +        * currently assigned to a host channel.
37684 +        */
37685 +       dwc_list_link_t non_periodic_sched_active;
37686 +
37687 +       /**
37688 +        * Pointer to the next Queue Head to process in the active
37689 +        * non-periodic schedule.
37690 +        */
37691 +       dwc_list_link_t *non_periodic_qh_ptr;
37692 +
37693 +       /**
37694 +        * Inactive items in the periodic schedule. This is a list of QHs for
37695 +        * periodic transfers that are _not_ scheduled for the next frame.
37696 +        * Each QH in the list has an interval counter that determines when it
37697 +        * needs to be scheduled for execution. This scheduling mechanism
37698 +        * allows only a simple calculation for periodic bandwidth used (i.e.
37699 +        * must assume that all periodic transfers may need to execute in the
37700 +        * same frame). However, it greatly simplifies scheduling and should
37701 +        * be sufficient for the vast majority of OTG hosts, which need to
37702 +        * connect to a small number of peripherals at one time.
37703 +        *
37704 +        * Items move from this list to periodic_sched_ready when the QH
37705 +        * interval counter is 0 at SOF.
37706 +        */
37707 +       dwc_list_link_t periodic_sched_inactive;
37708 +
37709 +       /**
37710 +        * List of periodic QHs that are ready for execution in the next
37711 +        * frame, but have not yet been assigned to host channels.
37712 +        *
37713 +        * Items move from this list to periodic_sched_assigned as host
37714 +        * channels become available during the current frame.
37715 +        */
37716 +       dwc_list_link_t periodic_sched_ready;
37717 +
37718 +       /**
37719 +        * List of periodic QHs to be executed in the next frame that are
37720 +        * assigned to host channels.
37721 +        *
37722 +        * Items move from this list to periodic_sched_queued as the
37723 +        * transactions for the QH are queued to the DWC_otg controller.
37724 +        */
37725 +       dwc_list_link_t periodic_sched_assigned;
37726 +
37727 +       /**
37728 +        * List of periodic QHs that have been queued for execution.
37729 +        *
37730 +        * Items move from this list to either periodic_sched_inactive or
37731 +        * periodic_sched_ready when the channel associated with the transfer
37732 +        * is released. If the interval for the QH is 1, the item moves to
37733 +        * periodic_sched_ready because it must be rescheduled for the next
37734 +        * frame. Otherwise, the item moves to periodic_sched_inactive.
37735 +        */
37736 +       dwc_list_link_t periodic_sched_queued;
37737 +
37738 +       /**
37739 +        * Total bandwidth claimed so far for periodic transfers. This value
37740 +        * is in microseconds per (micro)frame. The assumption is that all
37741 +        * periodic transfers may occur in the same (micro)frame.
37742 +        */
37743 +       uint16_t periodic_usecs;
37744 +
37745 +       /**
37746 +        * Total bandwidth claimed so far for all periodic transfers
37747 +        * in a frame.
37748 +        * This will include a mixture of HS and FS transfers.
37749 +        * Units are microseconds per (micro)frame.
37750 +        * We have a budget per frame and have to schedule
37751 +        * transactions accordingly.
37752 +        * Watch out for the fact that things are actually scheduled for the
37753 +        * "next frame".
37754 +        */
37755 +       uint16_t                frame_usecs[8];
37756 +
37757 +
37758 +       /**
37759 +        * Frame number read from the core at SOF. The value ranges from 0 to
37760 +        * DWC_HFNUM_MAX_FRNUM.
37761 +        */
37762 +       uint16_t frame_number;
37763 +
37764 +       /**
37765 +        * Count of periodic QHs, if using several eps. For SOF enable/disable.
37766 +        */
37767 +       uint16_t periodic_qh_count;
37768 +
37769 +       /**
37770 +        * Free host channels in the controller. This is a list of
37771 +        * dwc_hc_t items.
37772 +        */
37773 +       struct hc_list free_hc_list;
37774 +       /**
37775 +        * Number of host channels assigned to periodic transfers. Currently
37776 +        * assuming that there is a dedicated host channel for each periodic
37777 +        * transaction and at least one host channel available for
37778 +        * non-periodic transactions.
37779 +        */
37780 +       int periodic_channels; /* microframe_schedule==0 */
37781 +
37782 +       /**
37783 +        * Number of host channels assigned to non-periodic transfers.
37784 +        */
37785 +       int non_periodic_channels; /* microframe_schedule==0 */
37786 +
37787 +       /**
37788 +        * Number of host channels assigned to non-periodic transfers.
37789 +        */
37790 +       int available_host_channels;
37791 +
37792 +       /**
37793 +        * Array of pointers to the host channel descriptors. Allows accessing
37794 +        * a host channel descriptor given the host channel number. This is
37795 +        * useful in interrupt handlers.
37796 +        */
37797 +       struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
37798 +
37799 +       /**
37800 +        * Buffer to use for any data received during the status phase of a
37801 +        * control transfer. Normally no data is transferred during the status
37802 +        * phase. This buffer is used as a bit bucket.
37803 +        */
37804 +       uint8_t *status_buf;
37805 +
37806 +       /**
37807 +        * DMA address for status_buf.
37808 +        */
37809 +       dma_addr_t status_buf_dma;
37810 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
37811 +
37812 +       /**
37813 +        * Connection timer. An OTG host must display a message if the device
37814 +        * does not connect. Started when the VBus power is turned on via
37815 +        * sysfs attribute "buspower".
37816 +        */
37817 +       dwc_timer_t *conn_timer;
37818 +
37819 +       /* Tasket to do a reset */
37820 +       dwc_tasklet_t *reset_tasklet;
37821 +
37822 +       /*  */
37823 +       dwc_spinlock_t *lock;
37824 +
37825 +       /**
37826 +        * Private data that could be used by OS wrapper.
37827 +        */
37828 +       void *priv;
37829 +
37830 +       uint8_t otg_port;
37831 +
37832 +       /** Frame List */
37833 +       uint32_t *frame_list;
37834 +
37835 +       /** Frame List DMA address */
37836 +       dma_addr_t frame_list_dma;
37837 +
37838 +#ifdef DEBUG
37839 +       uint32_t frrem_samples;
37840 +       uint64_t frrem_accum;
37841 +
37842 +       uint32_t hfnum_7_samples_a;
37843 +       uint64_t hfnum_7_frrem_accum_a;
37844 +       uint32_t hfnum_0_samples_a;
37845 +       uint64_t hfnum_0_frrem_accum_a;
37846 +       uint32_t hfnum_other_samples_a;
37847 +       uint64_t hfnum_other_frrem_accum_a;
37848 +
37849 +       uint32_t hfnum_7_samples_b;
37850 +       uint64_t hfnum_7_frrem_accum_b;
37851 +       uint32_t hfnum_0_samples_b;
37852 +       uint64_t hfnum_0_frrem_accum_b;
37853 +       uint32_t hfnum_other_samples_b;
37854 +       uint64_t hfnum_other_frrem_accum_b;
37855 +#endif
37856 +};
37857 +
37858 +/** @name Transaction Execution Functions */
37859 +/** @{ */
37860 +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
37861 +                                                                 * hcd);
37862 +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
37863 +                                          dwc_otg_transaction_type_e tr_type);
37864 +
37865 +/** @} */
37866 +
37867 +/** @name Interrupt Handler Functions */
37868 +/** @{ */
37869 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37870 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37871 +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
37872 +                                                        dwc_otg_hcd);
37873 +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
37874 +                                                       dwc_otg_hcd);
37875 +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
37876 +                                                          dwc_otg_hcd);
37877 +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
37878 +                                                          dwc_otg_hcd);
37879 +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37880 +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
37881 +                                                            dwc_otg_hcd);
37882 +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37883 +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37884 +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
37885 +                                           uint32_t num);
37886 +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37887 +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
37888 +                                                      dwc_otg_hcd);
37889 +/** @} */
37890 +
37891 +/** @name Schedule Queue Functions */
37892 +/** @{ */
37893 +
37894 +/* Implemented in dwc_otg_hcd_queue.c */
37895 +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
37896 +                                          dwc_otg_hcd_urb_t * urb, int atomic_alloc);
37897 +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37898 +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37899 +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37900 +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
37901 +                                     int sched_csplit);
37902 +
37903 +/** Remove and free a QH */
37904 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
37905 +                                                 dwc_otg_qh_t * qh)
37906 +{
37907 +       dwc_irqflags_t flags;
37908 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
37909 +       dwc_otg_hcd_qh_remove(hcd, qh);
37910 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
37911 +       dwc_otg_hcd_qh_free(hcd, qh);
37912 +}
37913 +
37914 +/** Allocates memory for a QH structure.
37915 + * @return Returns the memory allocate or NULL on error. */
37916 +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
37917 +{
37918 +       if (atomic_alloc)
37919 +               return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
37920 +       else
37921 +               return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
37922 +}
37923 +
37924 +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
37925 +                                            int atomic_alloc);
37926 +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
37927 +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
37928 +                              dwc_otg_qh_t ** qh, int atomic_alloc);
37929 +
37930 +/** Allocates memory for a QTD structure.
37931 + * @return Returns the memory allocate or NULL on error. */
37932 +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
37933 +{
37934 +       if (atomic_alloc)
37935 +               return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
37936 +       else
37937 +               return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
37938 +}
37939 +
37940 +/** Frees the memory for a QTD structure.  QTD should already be removed from
37941 + * list.
37942 + * @param qtd QTD to free.*/
37943 +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
37944 +{
37945 +       DWC_FREE(qtd);
37946 +}
37947 +
37948 +/** Removes a QTD from list.
37949 + * @param hcd HCD instance.
37950 + * @param qtd QTD to remove from list.
37951 + * @param qh QTD belongs to.
37952 + */
37953 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
37954 +                                         dwc_otg_qtd_t * qtd,
37955 +                                         dwc_otg_qh_t * qh)
37956 +{
37957 +       DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
37958 +}
37959 +
37960 +/** Remove and free a QTD
37961 +  * Need to disable IRQ and hold hcd lock while calling this function out of
37962 +  * interrupt servicing chain */
37963 +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
37964 +                                                  dwc_otg_qtd_t * qtd,
37965 +                                                  dwc_otg_qh_t * qh)
37966 +{
37967 +       dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
37968 +       dwc_otg_hcd_qtd_free(qtd);
37969 +}
37970 +
37971 +/** @} */
37972 +
37973 +/** @name Descriptor DMA Supporting Functions */
37974 +/** @{ */
37975 +
37976 +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37977 +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
37978 +                                          dwc_hc_t * hc,
37979 +                                          dwc_otg_hc_regs_t * hc_regs,
37980 +                                          dwc_otg_halt_status_e halt_status);
37981 +
37982 +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37983 +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37984 +
37985 +/** @} */
37986 +
37987 +/** @name Internal Functions */
37988 +/** @{ */
37989 +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
37990 +/** @} */
37991 +
37992 +#ifdef CONFIG_USB_DWC_OTG_LPM
37993 +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
37994 +                                          uint8_t devaddr);
37995 +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
37996 +#endif
37997 +
37998 +/** Gets the QH that contains the list_head */
37999 +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
38000 +
38001 +/** Gets the QTD that contains the list_head */
38002 +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
38003 +
38004 +/** Check if QH is non-periodic  */
38005 +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
38006 +                                    (_qh_ptr_->ep_type == UE_CONTROL))
38007 +
38008 +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
38009 +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
38010 +
38011 +/** Packet size for any kind of endpoint descriptor */
38012 +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
38013 +
38014 +/**
38015 + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
38016 + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
38017 + * frame number when the max frame number is reached.
38018 + */
38019 +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
38020 +{
38021 +       return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
38022 +           (DWC_HFNUM_MAX_FRNUM >> 1);
38023 +}
38024 +
38025 +/**
38026 + * Returns true if _frame1 is greater than _frame2. The comparison is done
38027 + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
38028 + * number when the max frame number is reached.
38029 + */
38030 +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
38031 +{
38032 +       return (frame1 != frame2) &&
38033 +           (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
38034 +            (DWC_HFNUM_MAX_FRNUM >> 1));
38035 +}
38036 +
38037 +/**
38038 + * Increments _frame by the amount specified by _inc. The addition is done
38039 + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
38040 + */
38041 +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
38042 +{
38043 +       return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
38044 +}
38045 +
38046 +static inline uint16_t dwc_full_frame_num(uint16_t frame)
38047 +{
38048 +       return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
38049 +}
38050 +
38051 +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
38052 +{
38053 +       return frame & 0x7;
38054 +}
38055 +
38056 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
38057 +                                 dwc_otg_hc_regs_t * hc_regs,
38058 +                                 dwc_otg_qtd_t * qtd);
38059 +
38060 +#ifdef DEBUG
38061 +/**
38062 + * Macro to sample the remaining PHY clocks left in the current frame. This
38063 + * may be used during debugging to determine the average time it takes to
38064 + * execute sections of code. There are two possible sample points, "a" and
38065 + * "b", so the _letter argument must be one of these values.
38066 + *
38067 + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
38068 + * example, "cat /sys/devices/lm0/hcd_frrem".
38069 + */
38070 +#define dwc_sample_frrem(_hcd, _qh, _letter) \
38071 +{ \
38072 +       hfnum_data_t hfnum; \
38073 +       dwc_otg_qtd_t *qtd; \
38074 +       qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
38075 +       if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
38076 +               hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
38077 +               switch (hfnum.b.frnum & 0x7) { \
38078 +               case 7: \
38079 +                       _hcd->hfnum_7_samples_##_letter++; \
38080 +                       _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
38081 +                       break; \
38082 +               case 0: \
38083 +                       _hcd->hfnum_0_samples_##_letter++; \
38084 +                       _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
38085 +                       break; \
38086 +               default: \
38087 +                       _hcd->hfnum_other_samples_##_letter++; \
38088 +                       _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
38089 +                       break; \
38090 +               } \
38091 +       } \
38092 +}
38093 +#else
38094 +#define dwc_sample_frrem(_hcd, _qh, _letter)
38095 +#endif
38096 +#endif
38097 +#endif /* DWC_DEVICE_ONLY */
38098 --- /dev/null
38099 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
38100 @@ -0,0 +1,1133 @@
38101 +/*==========================================================================
38102 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
38103 + * $Revision: #10 $
38104 + * $Date: 2011/10/20 $
38105 + * $Change: 1869464 $
38106 + *
38107 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
38108 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
38109 + * otherwise expressly agreed to in writing between Synopsys and you.
38110 + *
38111 + * The Software IS NOT an item of Licensed Software or Licensed Product under
38112 + * any End User Software License Agreement or Agreement for Licensed Product
38113 + * with Synopsys or any supplement thereto. You are permitted to use and
38114 + * redistribute this Software in source and binary forms, with or without
38115 + * modification, provided that redistributions of source code must retain this
38116 + * notice. You may not view, use, disclose, copy or distribute this file or
38117 + * any information contained herein except pursuant to this license grant from
38118 + * Synopsys. If you do not agree with this notice, including the disclaimer
38119 + * below, then you are not authorized to use the Software.
38120 + *
38121 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
38122 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38123 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38124 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
38125 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38126 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38127 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38128 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38129 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38130 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38131 + * DAMAGE.
38132 + * ========================================================================== */
38133 +#ifndef DWC_DEVICE_ONLY
38134 +
38135 +/** @file
38136 + * This file contains Descriptor DMA support implementation for host mode.
38137 + */
38138 +
38139 +#include "dwc_otg_hcd.h"
38140 +#include "dwc_otg_regs.h"
38141 +
38142 +extern bool microframe_schedule;
38143 +
38144 +static inline uint8_t frame_list_idx(uint16_t frame)
38145 +{
38146 +       return (frame & (MAX_FRLIST_EN_NUM - 1));
38147 +}
38148 +
38149 +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
38150 +{
38151 +       return (idx + inc) &
38152 +           (((speed ==
38153 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38154 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38155 +}
38156 +
38157 +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
38158 +{
38159 +       return (idx - inc) &
38160 +           (((speed ==
38161 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38162 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38163 +}
38164 +
38165 +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
38166 +{
38167 +       return (((qh->ep_type == UE_ISOCHRONOUS)
38168 +                && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))
38169 +               ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);
38170 +}
38171 +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
38172 +{
38173 +       return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)
38174 +               ? ((qh->interval + 8 - 1) / 8)
38175 +               : qh->interval);
38176 +}
38177 +
38178 +static int desc_list_alloc(dwc_otg_qh_t * qh)
38179 +{
38180 +       int retval = 0;
38181 +
38182 +       qh->desc_list = (dwc_otg_host_dma_desc_t *)
38183 +           DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
38184 +                         &qh->desc_list_dma);
38185 +
38186 +       if (!qh->desc_list) {
38187 +               retval = -DWC_E_NO_MEMORY;
38188 +               DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
38189 +
38190 +       }
38191 +
38192 +       dwc_memset(qh->desc_list, 0x00,
38193 +                  sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38194 +
38195 +       qh->n_bytes =
38196 +           (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));
38197 +
38198 +       if (!qh->n_bytes) {
38199 +               retval = -DWC_E_NO_MEMORY;
38200 +               DWC_ERROR
38201 +                   ("%s: Failed to allocate array for descriptors' size actual values\n",
38202 +                    __func__);
38203 +
38204 +       }
38205 +       return retval;
38206 +
38207 +}
38208 +
38209 +static void desc_list_free(dwc_otg_qh_t * qh)
38210 +{
38211 +       if (qh->desc_list) {
38212 +               DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,
38213 +                            qh->desc_list_dma);
38214 +               qh->desc_list = NULL;
38215 +       }
38216 +
38217 +       if (qh->n_bytes) {
38218 +               DWC_FREE(qh->n_bytes);
38219 +               qh->n_bytes = NULL;
38220 +       }
38221 +}
38222 +
38223 +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
38224 +{
38225 +       int retval = 0;
38226 +       if (hcd->frame_list)
38227 +               return 0;
38228 +
38229 +       hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,
38230 +                                       &hcd->frame_list_dma);
38231 +       if (!hcd->frame_list) {
38232 +               retval = -DWC_E_NO_MEMORY;
38233 +               DWC_ERROR("%s: Frame List allocation failed\n", __func__);
38234 +       }
38235 +
38236 +       dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
38237 +
38238 +       return retval;
38239 +}
38240 +
38241 +static void frame_list_free(dwc_otg_hcd_t * hcd)
38242 +{
38243 +       if (!hcd->frame_list)
38244 +               return;
38245 +
38246 +       DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
38247 +       hcd->frame_list = NULL;
38248 +}
38249 +
38250 +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
38251 +{
38252 +
38253 +       hcfg_data_t hcfg;
38254 +
38255 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38256 +
38257 +       if (hcfg.b.perschedena) {
38258 +               /* already enabled */
38259 +               return;
38260 +       }
38261 +
38262 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,
38263 +                       hcd->frame_list_dma);
38264 +
38265 +       switch (fr_list_en) {
38266 +       case 64:
38267 +               hcfg.b.frlisten = 3;
38268 +               break;
38269 +       case 32:
38270 +               hcfg.b.frlisten = 2;
38271 +               break;
38272 +       case 16:
38273 +               hcfg.b.frlisten = 1;
38274 +               break;
38275 +       case 8:
38276 +               hcfg.b.frlisten = 0;
38277 +               break;
38278 +       default:
38279 +               break;
38280 +       }
38281 +
38282 +       hcfg.b.perschedena = 1;
38283 +
38284 +       DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
38285 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38286 +
38287 +}
38288 +
38289 +static void per_sched_disable(dwc_otg_hcd_t * hcd)
38290 +{
38291 +       hcfg_data_t hcfg;
38292 +
38293 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38294 +
38295 +       if (!hcfg.b.perschedena) {
38296 +               /* already disabled */
38297 +               return;
38298 +       }
38299 +       hcfg.b.perschedena = 0;
38300 +
38301 +       DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
38302 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38303 +}
38304 +
38305 +/*
38306 + * Activates/Deactivates FrameList entries for the channel
38307 + * based on endpoint servicing period.
38308 + */
38309 +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
38310 +{
38311 +       uint16_t i, j, inc;
38312 +       dwc_hc_t *hc = NULL;
38313 +
38314 +       if (!qh->channel) {
38315 +               DWC_ERROR("qh->channel = %p", qh->channel);
38316 +               return;
38317 +       }
38318 +
38319 +       if (!hcd) {
38320 +               DWC_ERROR("------hcd = %p", hcd);
38321 +               return;
38322 +       }
38323 +
38324 +       if (!hcd->frame_list) {
38325 +               DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);
38326 +               return;
38327 +       }
38328 +
38329 +       hc = qh->channel;
38330 +       inc = frame_incr_val(qh);
38331 +       if (qh->ep_type == UE_ISOCHRONOUS)
38332 +               i = frame_list_idx(qh->sched_frame);
38333 +       else
38334 +               i = 0;
38335 +
38336 +       j = i;
38337 +       do {
38338 +               if (enable)
38339 +                       hcd->frame_list[j] |= (1 << hc->hc_num);
38340 +               else
38341 +                       hcd->frame_list[j] &= ~(1 << hc->hc_num);
38342 +               j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
38343 +       }
38344 +       while (j != i);
38345 +       if (!enable)
38346 +               return;
38347 +       hc->schinfo = 0;
38348 +       if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
38349 +               j = 1;
38350 +               /* TODO - check this */
38351 +               inc = (8 + qh->interval - 1) / qh->interval;
38352 +               for (i = 0; i < inc; i++) {
38353 +                       hc->schinfo |= j;
38354 +                       j = j << qh->interval;
38355 +               }
38356 +       } else {
38357 +               hc->schinfo = 0xff;
38358 +       }
38359 +}
38360 +
38361 +#if 1
38362 +void dump_frame_list(dwc_otg_hcd_t * hcd)
38363 +{
38364 +       int i = 0;
38365 +       DWC_PRINTF("--FRAME LIST (hex) --\n");
38366 +       for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
38367 +               DWC_PRINTF("%x\t", hcd->frame_list[i]);
38368 +               if (!(i % 8) && i)
38369 +                       DWC_PRINTF("\n");
38370 +       }
38371 +       DWC_PRINTF("\n----\n");
38372 +
38373 +}
38374 +#endif
38375 +
38376 +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38377 +{
38378 +       dwc_irqflags_t flags;
38379 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
38380 +
38381 +       dwc_hc_t *hc = qh->channel;
38382 +       if (dwc_qh_is_non_per(qh)) {
38383 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
38384 +               if (!microframe_schedule)
38385 +                       hcd->non_periodic_channels--;
38386 +               else
38387 +                       hcd->available_host_channels++;
38388 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
38389 +       } else
38390 +               update_frame_list(hcd, qh, 0);
38391 +
38392 +       /*
38393 +        * The condition is added to prevent double cleanup try in case of device
38394 +        * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
38395 +        */
38396 +       if (hc->qh) {
38397 +               dwc_otg_hc_cleanup(hcd->core_if, hc);
38398 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
38399 +               hc->qh = NULL;
38400 +       }
38401 +
38402 +       qh->channel = NULL;
38403 +       qh->ntd = 0;
38404 +
38405 +       if (qh->desc_list) {
38406 +               dwc_memset(qh->desc_list, 0x00,
38407 +                          sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38408 +       }
38409 +       DWC_SPINLOCK_FREE(channel_lock);
38410 +}
38411 +
38412 +/**
38413 + * Initializes a QH structure's Descriptor DMA related members.
38414 + * Allocates memory for descriptor list.
38415 + * On first periodic QH, allocates memory for FrameList
38416 + * and enables periodic scheduling.
38417 + *
38418 + * @param hcd The HCD state structure for the DWC OTG controller.
38419 + * @param qh The QH to init.
38420 + *
38421 + * @return 0 if successful, negative error code otherwise.
38422 + */
38423 +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38424 +{
38425 +       int retval = 0;
38426 +
38427 +       if (qh->do_split) {
38428 +               DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
38429 +               return -1;
38430 +       }
38431 +
38432 +       retval = desc_list_alloc(qh);
38433 +
38434 +       if ((retval == 0)
38435 +           && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
38436 +               if (!hcd->frame_list) {
38437 +                       retval = frame_list_alloc(hcd);
38438 +                       /* Enable periodic schedule on first periodic QH */
38439 +                       if (retval == 0)
38440 +                               per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
38441 +               }
38442 +       }
38443 +
38444 +       qh->ntd = 0;
38445 +
38446 +       return retval;
38447 +}
38448 +
38449 +/**
38450 + * Frees descriptor list memory associated with the QH.
38451 + * If QH is periodic and the last, frees FrameList memory
38452 + * and disables periodic scheduling.
38453 + *
38454 + * @param hcd The HCD state structure for the DWC OTG controller.
38455 + * @param qh The QH to init.
38456 + */
38457 +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38458 +{
38459 +       desc_list_free(qh);
38460 +
38461 +       /*
38462 +        * Channel still assigned due to some reasons.
38463 +        * Seen on Isoc URB dequeue. Channel halted but no subsequent
38464 +        * ChHalted interrupt to release the channel. Afterwards
38465 +        * when it comes here from endpoint disable routine
38466 +        * channel remains assigned.
38467 +        */
38468 +       if (qh->channel)
38469 +               release_channel_ddma(hcd, qh);
38470 +
38471 +       if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)
38472 +           && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {
38473 +
38474 +               per_sched_disable(hcd);
38475 +               frame_list_free(hcd);
38476 +       }
38477 +}
38478 +
38479 +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
38480 +{
38481 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38482 +               /*
38483 +                * Descriptor set(8 descriptors) index
38484 +                * which is 8-aligned.
38485 +                */
38486 +               return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
38487 +       } else {
38488 +               return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
38489 +       }
38490 +}
38491 +
38492 +/*
38493 + * Determine starting frame for Isochronous transfer.
38494 + * Few frames skipped to prevent race condition with HC.
38495 + */
38496 +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38497 +                                  uint8_t * skip_frames)
38498 +{
38499 +       uint16_t frame = 0;
38500 +       hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
38501 +
38502 +       /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
38503 +
38504 +       /*
38505 +        * skip_frames is used to limit activated descriptors number
38506 +        * to avoid the situation when HC services the last activated
38507 +        * descriptor firstly.
38508 +        * Example for FS:
38509 +        * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
38510 +        * corresponding to curr_frame+1, the descriptor corresponding to frame 2
38511 +        * will be fetched. If the number of descriptors is max=64 (or greather) the
38512 +        * list will be fully programmed with Active descriptors and it is possible
38513 +        * case(rare) that the latest descriptor(considering rollback) corresponding
38514 +        * to frame 2 will be serviced first. HS case is more probable because, in fact,
38515 +        * up to 11 uframes(16 in the code) may be skipped.
38516 +        */
38517 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38518 +               /*
38519 +                * Consider uframe counter also, to start xfer asap.
38520 +                * If half of the frame elapsed skip 2 frames otherwise
38521 +                * just 1 frame.
38522 +                * Starting descriptor index must be 8-aligned, so
38523 +                * if the current frame is near to complete the next one
38524 +                * is skipped as well.
38525 +                */
38526 +
38527 +               if (dwc_micro_frame_num(hcd->frame_number) >= 5) {
38528 +                       *skip_frames = 2 * 8;
38529 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38530 +               } else {
38531 +                       *skip_frames = 1 * 8;
38532 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38533 +               }
38534 +
38535 +               frame = dwc_full_frame_num(frame);
38536 +       } else {
38537 +               /*
38538 +                * Two frames are skipped for FS - the current and the next.
38539 +                * But for descriptor programming, 1 frame(descriptor) is enough,
38540 +                * see example above.
38541 +                */
38542 +               *skip_frames = 1;
38543 +               frame = dwc_frame_num_inc(hcd->frame_number, 2);
38544 +       }
38545 +
38546 +       return frame;
38547 +}
38548 +
38549 +/*
38550 + * Calculate initial descriptor index for isochronous transfer
38551 + * based on scheduled frame.
38552 + */
38553 +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38554 +{
38555 +       uint16_t frame = 0, fr_idx, fr_idx_tmp;
38556 +       uint8_t skip_frames = 0;
38557 +       /*
38558 +        * With current ISOC processing algorithm the channel is being
38559 +        * released when no more QTDs in the list(qh->ntd == 0).
38560 +        * Thus this function is called only when qh->ntd == 0 and qh->channel == 0.
38561 +        *
38562 +        * So qh->channel != NULL branch is not used and just not removed from the
38563 +        * source file. It is required for another possible approach which is,
38564 +        * do not disable and release the channel when ISOC session completed,
38565 +        * just move QH to inactive schedule until new QTD arrives.
38566 +        * On new QTD, the QH moved back to 'ready' schedule,
38567 +        * starting frame and therefore starting desc_index are recalculated.
38568 +        * In this case channel is released only on ep_disable.
38569 +        */
38570 +
38571 +       /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
38572 +       if (qh->channel) {
38573 +               frame = calc_starting_frame(hcd, qh, &skip_frames);
38574 +               /*
38575 +                * Calculate initial descriptor index based on FrameList current bitmap
38576 +                * and servicing period.
38577 +                */
38578 +               fr_idx_tmp = frame_list_idx(frame);
38579 +               fr_idx =
38580 +                   (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -
38581 +                    fr_idx_tmp)
38582 +                   % frame_incr_val(qh);
38583 +               fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
38584 +       } else {
38585 +               qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);
38586 +               fr_idx = frame_list_idx(qh->sched_frame);
38587 +       }
38588 +
38589 +       qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);
38590 +
38591 +       return skip_frames;
38592 +}
38593 +
38594 +#define        ISOC_URB_GIVEBACK_ASAP
38595 +
38596 +#define MAX_ISOC_XFER_SIZE_FS 1023
38597 +#define MAX_ISOC_XFER_SIZE_HS 3072
38598 +#define DESCNUM_THRESHOLD 4
38599 +
38600 +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38601 +                              uint8_t skip_frames)
38602 +{
38603 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
38604 +       dwc_otg_qtd_t *qtd;
38605 +       dwc_otg_host_dma_desc_t *dma_desc;
38606 +       uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
38607 +
38608 +       idx = qh->td_last;
38609 +       inc = qh->interval;
38610 +       n_desc = 0;
38611 +
38612 +       ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
38613 +       if (skip_frames && !qh->channel)
38614 +               ntd_max = ntd_max - skip_frames / qh->interval;
38615 +
38616 +       max_xfer_size =
38617 +           (qh->dev_speed ==
38618 +            DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :
38619 +           MAX_ISOC_XFER_SIZE_FS;
38620 +
38621 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38622 +               while ((qh->ntd < ntd_max)
38623 +                      && (qtd->isoc_frame_index_last <
38624 +                          qtd->urb->packet_count)) {
38625 +
38626 +                       dma_desc = &qh->desc_list[idx];
38627 +                       dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
38628 +
38629 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
38630 +
38631 +                       if (frame_desc->length > max_xfer_size)
38632 +                               qh->n_bytes[idx] = max_xfer_size;
38633 +                       else
38634 +                               qh->n_bytes[idx] = frame_desc->length;
38635 +                       dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
38636 +                       dma_desc->status.b_isoc.a = 1;
38637 +                       dma_desc->status.b_isoc.sts = 0;
38638 +
38639 +                       dma_desc->buf = qtd->urb->dma + frame_desc->offset;
38640 +
38641 +                       qh->ntd++;
38642 +
38643 +                       qtd->isoc_frame_index_last++;
38644 +
38645 +#ifdef ISOC_URB_GIVEBACK_ASAP
38646 +                       /*
38647 +                        * Set IOC for each descriptor corresponding to the
38648 +                        * last frame of the URB.
38649 +                        */
38650 +                       if (qtd->isoc_frame_index_last ==
38651 +                           qtd->urb->packet_count)
38652 +                               dma_desc->status.b_isoc.ioc = 1;
38653 +
38654 +#endif
38655 +                       idx = desclist_idx_inc(idx, inc, qh->dev_speed);
38656 +                       n_desc++;
38657 +
38658 +               }
38659 +               qtd->in_process = 1;
38660 +       }
38661 +
38662 +       qh->td_last = idx;
38663 +
38664 +#ifdef ISOC_URB_GIVEBACK_ASAP
38665 +       /* Set IOC for the last descriptor if descriptor list is full */
38666 +       if (qh->ntd == ntd_max) {
38667 +               idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38668 +               qh->desc_list[idx].status.b_isoc.ioc = 1;
38669 +       }
38670 +#else
38671 +       /*
38672 +        * Set IOC bit only for one descriptor.
38673 +        * Always try to be ahead of HW processing,
38674 +        * i.e. on IOC generation driver activates next descriptors but
38675 +        * core continues to process descriptors followed the one with IOC set.
38676 +        */
38677 +
38678 +       if (n_desc > DESCNUM_THRESHOLD) {
38679 +               /*
38680 +                * Move IOC "up". Required even if there is only one QTD
38681 +                * in the list, cause QTDs migth continue to be queued,
38682 +                * but during the activation it was only one queued.
38683 +                * Actually more than one QTD might be in the list if this function called
38684 +                * from XferCompletion - QTDs was queued during HW processing of the previous
38685 +                * descriptor chunk.
38686 +                */
38687 +               idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
38688 +       } else {
38689 +               /*
38690 +                * Set the IOC for the latest descriptor
38691 +                * if either number of descriptor is not greather than threshold
38692 +                * or no more new descriptors activated.
38693 +                */
38694 +               idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38695 +       }
38696 +
38697 +       qh->desc_list[idx].status.b_isoc.ioc = 1;
38698 +#endif
38699 +}
38700 +
38701 +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38702 +{
38703 +
38704 +       dwc_hc_t *hc;
38705 +       dwc_otg_host_dma_desc_t *dma_desc;
38706 +       dwc_otg_qtd_t *qtd;
38707 +       int num_packets, len, n_desc = 0;
38708 +
38709 +       hc = qh->channel;
38710 +
38711 +       /*
38712 +        * Start with hc->xfer_buff initialized in
38713 +        * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
38714 +        * this pointer re-assigned to the buffer of the currently processed QTD.
38715 +        * For non-SG request there is always one QTD active.
38716 +        */
38717 +
38718 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38719 +
38720 +               if (n_desc) {
38721 +                       /* SG request - more than 1 QTDs */
38722 +                       hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
38723 +                       hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
38724 +               }
38725 +
38726 +               qtd->n_desc = 0;
38727 +
38728 +               do {
38729 +                       dma_desc = &qh->desc_list[n_desc];
38730 +                       len = hc->xfer_len;
38731 +
38732 +                       if (len > MAX_DMA_DESC_SIZE)
38733 +                               len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
38734 +
38735 +                       if (hc->ep_is_in) {
38736 +                               if (len > 0) {
38737 +                                       num_packets = (len + hc->max_packet - 1) / hc->max_packet;
38738 +                               } else {
38739 +                                       /* Need 1 packet for transfer length of 0. */
38740 +                                       num_packets = 1;
38741 +                               }
38742 +                               /* Always program an integral # of max packets for IN transfers. */
38743 +                               len = num_packets * hc->max_packet;
38744 +                       }
38745 +
38746 +                       dma_desc->status.b.n_bytes = len;
38747 +
38748 +                       qh->n_bytes[n_desc] = len;
38749 +
38750 +                       if ((qh->ep_type == UE_CONTROL)
38751 +                           && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
38752 +                               dma_desc->status.b.sup = 1;     /* Setup Packet */
38753 +
38754 +                       dma_desc->status.b.a = 1;       /* Active descriptor */
38755 +                       dma_desc->status.b.sts = 0;
38756 +
38757 +                       dma_desc->buf =
38758 +                           ((unsigned long)hc->xfer_buff & 0xffffffff);
38759 +
38760 +                       /*
38761 +                        * Last descriptor(or single) of IN transfer
38762 +                        * with actual size less than MaxPacket.
38763 +                        */
38764 +                       if (len > hc->xfer_len) {
38765 +                               hc->xfer_len = 0;
38766 +                       } else {
38767 +                               hc->xfer_buff += len;
38768 +                               hc->xfer_len -= len;
38769 +                       }
38770 +
38771 +                       qtd->n_desc++;
38772 +                       n_desc++;
38773 +               }
38774 +               while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
38775 +
38776 +
38777 +               qtd->in_process = 1;
38778 +
38779 +               if (qh->ep_type == UE_CONTROL)
38780 +                       break;
38781 +
38782 +               if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
38783 +                       break;
38784 +       }
38785 +
38786 +       if (n_desc) {
38787 +               /* Request Transfer Complete interrupt for the last descriptor */
38788 +               qh->desc_list[n_desc - 1].status.b.ioc = 1;
38789 +               /* End of List indicator */
38790 +               qh->desc_list[n_desc - 1].status.b.eol = 1;
38791 +
38792 +               hc->ntd = n_desc;
38793 +       }
38794 +}
38795 +
38796 +/**
38797 + * For Control and Bulk endpoints initializes descriptor list
38798 + * and starts the transfer.
38799 + *
38800 + * For Interrupt and Isochronous endpoints initializes descriptor list
38801 + * then updates FrameList, marking appropriate entries as active.
38802 + * In case of Isochronous, the starting descriptor index is calculated based
38803 + * on the scheduled frame, but only on the first transfer descriptor within a session.
38804 + * Then starts the transfer via enabling the channel.
38805 + * For Isochronous endpoint the channel is not halted on XferComplete
38806 + * interrupt so remains assigned to the endpoint(QH) until session is done.
38807 + *
38808 + * @param hcd The HCD state structure for the DWC OTG controller.
38809 + * @param qh The QH to init.
38810 + *
38811 + * @return 0 if successful, negative error code otherwise.
38812 + */
38813 +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38814 +{
38815 +       /* Channel is already assigned */
38816 +       dwc_hc_t *hc = qh->channel;
38817 +       uint8_t skip_frames = 0;
38818 +
38819 +       switch (hc->ep_type) {
38820 +       case DWC_OTG_EP_TYPE_CONTROL:
38821 +       case DWC_OTG_EP_TYPE_BULK:
38822 +               init_non_isoc_dma_desc(hcd, qh);
38823 +
38824 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38825 +               break;
38826 +       case DWC_OTG_EP_TYPE_INTR:
38827 +               init_non_isoc_dma_desc(hcd, qh);
38828 +
38829 +               update_frame_list(hcd, qh, 1);
38830 +
38831 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38832 +               break;
38833 +       case DWC_OTG_EP_TYPE_ISOC:
38834 +
38835 +               if (!qh->ntd)
38836 +                       skip_frames = recalc_initial_desc_idx(hcd, qh);
38837 +
38838 +               init_isoc_dma_desc(hcd, qh, skip_frames);
38839 +
38840 +               if (!hc->xfer_started) {
38841 +
38842 +                       update_frame_list(hcd, qh, 1);
38843 +
38844 +                       /*
38845 +                        * Always set to max, instead of actual size.
38846 +                        * Otherwise ntd will be changed with
38847 +                        * channel being enabled. Not recommended.
38848 +                        *
38849 +                        */
38850 +                       hc->ntd = max_desc_num(qh);
38851 +                       /* Enable channel only once for ISOC */
38852 +                       dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38853 +               }
38854 +
38855 +               break;
38856 +       default:
38857 +
38858 +               break;
38859 +       }
38860 +}
38861 +
38862 +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
38863 +                                   dwc_hc_t * hc,
38864 +                                   dwc_otg_hc_regs_t * hc_regs,
38865 +                                   dwc_otg_halt_status_e halt_status)
38866 +{
38867 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
38868 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
38869 +       dwc_otg_qh_t *qh;
38870 +       dwc_otg_host_dma_desc_t *dma_desc;
38871 +       uint16_t idx, remain;
38872 +       uint8_t urb_compl;
38873 +
38874 +       qh = hc->qh;
38875 +       idx = qh->td_first;
38876 +
38877 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
38878 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
38879 +                   qtd->in_process = 0;
38880 +               return;
38881 +       } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||
38882 +                  (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
38883 +               /*
38884 +                * Channel is halted in these error cases.
38885 +                * Considered as serious issues.
38886 +                * Complete all URBs marking all frames as failed,
38887 +                * irrespective whether some of the descriptors(frames) succeeded or no.
38888 +                * Pass error code to completion routine as well, to
38889 +                * update urb->status, some of class drivers might use it to stop
38890 +                * queing transfer requests.
38891 +                */
38892 +               int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)
38893 +                   ? (-DWC_E_IO)
38894 +                   : (-DWC_E_OVERFLOW);
38895 +
38896 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
38897 +                       for (idx = 0; idx < qtd->urb->packet_count; idx++) {
38898 +                               frame_desc = &qtd->urb->iso_descs[idx];
38899 +                               frame_desc->status = err;
38900 +                       }
38901 +                       hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
38902 +                       dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
38903 +               }
38904 +               return;
38905 +       }
38906 +
38907 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
38908 +
38909 +               if (!qtd->in_process)
38910 +                       break;
38911 +
38912 +               urb_compl = 0;
38913 +
38914 +               do {
38915 +
38916 +                       dma_desc = &qh->desc_list[idx];
38917 +
38918 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
38919 +                       remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
38920 +
38921 +                       if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
38922 +                               /*
38923 +                                * XactError or, unable to complete all the transactions
38924 +                                * in the scheduled micro-frame/frame,
38925 +                                * both indicated by DMA_DESC_STS_PKTERR.
38926 +                                */
38927 +                               qtd->urb->error_count++;
38928 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
38929 +                               frame_desc->status = -DWC_E_PROTOCOL;
38930 +                       } else {
38931 +                               /* Success */
38932 +
38933 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
38934 +                               frame_desc->status = 0;
38935 +                       }
38936 +
38937 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
38938 +                               /*
38939 +                                * urb->status is not used for isoc transfers here.
38940 +                                * The individual frame_desc status are used instead.
38941 +                                */
38942 +
38943 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
38944 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
38945 +
38946 +                               /*
38947 +                                * This check is necessary because urb_dequeue can be called
38948 +                                * from urb complete callback(sound driver example).
38949 +                                * All pending URBs are dequeued there, so no need for
38950 +                                * further processing.
38951 +                                */
38952 +                               if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
38953 +                                       return;
38954 +                               }
38955 +
38956 +                               urb_compl = 1;
38957 +
38958 +                       }
38959 +
38960 +                       qh->ntd--;
38961 +
38962 +                       /* Stop if IOC requested descriptor reached */
38963 +                       if (dma_desc->status.b_isoc.ioc) {
38964 +                               idx = desclist_idx_inc(idx, qh->interval, hc->speed);
38965 +                               goto stop_scan;
38966 +                       }
38967 +
38968 +                       idx = desclist_idx_inc(idx, qh->interval, hc->speed);
38969 +
38970 +                       if (urb_compl)
38971 +                               break;
38972 +               }
38973 +               while (idx != qh->td_first);
38974 +       }
38975 +stop_scan:
38976 +       qh->td_first = idx;
38977 +}
38978 +
38979 +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
38980 +                                      dwc_hc_t * hc,
38981 +                                      dwc_otg_qtd_t * qtd,
38982 +                                      dwc_otg_host_dma_desc_t * dma_desc,
38983 +                                      dwc_otg_halt_status_e halt_status,
38984 +                                      uint32_t n_bytes, uint8_t * xfer_done)
38985 +{
38986 +
38987 +       uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
38988 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
38989 +
38990 +       if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
38991 +               urb->status = -DWC_E_IO;
38992 +               return 1;
38993 +       }
38994 +       if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
38995 +               switch (halt_status) {
38996 +               case DWC_OTG_HC_XFER_STALL:
38997 +                       urb->status = -DWC_E_PIPE;
38998 +                       break;
38999 +               case DWC_OTG_HC_XFER_BABBLE_ERR:
39000 +                       urb->status = -DWC_E_OVERFLOW;
39001 +                       break;
39002 +               case DWC_OTG_HC_XFER_XACT_ERR:
39003 +                       urb->status = -DWC_E_PROTOCOL;
39004 +                       break;
39005 +               default:
39006 +                       DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
39007 +                                 halt_status);
39008 +                       break;
39009 +               }
39010 +               return 1;
39011 +       }
39012 +
39013 +       if (dma_desc->status.b.a == 1) {
39014 +               DWC_DEBUGPL(DBG_HCDV,
39015 +                           "Active descriptor encountered on channel %d\n",
39016 +                           hc->hc_num);
39017 +               return 0;
39018 +       }
39019 +
39020 +       if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
39021 +               if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39022 +                       urb->actual_length += n_bytes - remain;
39023 +                       if (remain || urb->actual_length == urb->length) {
39024 +                               /*
39025 +                                * For Control Data stage do not set urb->status=0 to prevent
39026 +                                * URB callback. Set it when Status phase done. See below.
39027 +                                */
39028 +                               *xfer_done = 1;
39029 +                       }
39030 +
39031 +               } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
39032 +                       urb->status = 0;
39033 +                       *xfer_done = 1;
39034 +               }
39035 +               /* No handling for SETUP stage */
39036 +       } else {
39037 +               /* BULK and INTR */
39038 +               urb->actual_length += n_bytes - remain;
39039 +               if (remain || urb->actual_length == urb->length) {
39040 +                       urb->status = 0;
39041 +                       *xfer_done = 1;
39042 +               }
39043 +       }
39044 +
39045 +       return 0;
39046 +}
39047 +
39048 +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
39049 +                                       dwc_hc_t * hc,
39050 +                                       dwc_otg_hc_regs_t * hc_regs,
39051 +                                       dwc_otg_halt_status_e halt_status)
39052 +{
39053 +       dwc_otg_hcd_urb_t *urb = NULL;
39054 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
39055 +       dwc_otg_qh_t *qh;
39056 +       dwc_otg_host_dma_desc_t *dma_desc;
39057 +       uint32_t n_bytes, n_desc, i;
39058 +       uint8_t failed = 0, xfer_done;
39059 +
39060 +       n_desc = 0;
39061 +
39062 +       qh = hc->qh;
39063 +
39064 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39065 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39066 +                       qtd->in_process = 0;
39067 +               }
39068 +               return;
39069 +       }
39070 +
39071 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
39072 +
39073 +               urb = qtd->urb;
39074 +
39075 +               n_bytes = 0;
39076 +               xfer_done = 0;
39077 +
39078 +               for (i = 0; i < qtd->n_desc; i++) {
39079 +                       dma_desc = &qh->desc_list[n_desc];
39080 +
39081 +                       n_bytes = qh->n_bytes[n_desc];
39082 +
39083 +                       failed =
39084 +                           update_non_isoc_urb_state_ddma(hcd, hc, qtd,
39085 +                                                          dma_desc,
39086 +                                                          halt_status, n_bytes,
39087 +                                                          &xfer_done);
39088 +
39089 +                       if (failed
39090 +                           || (xfer_done
39091 +                               && (urb->status != -DWC_E_IN_PROGRESS))) {
39092 +
39093 +                               hcd->fops->complete(hcd, urb->priv, urb,
39094 +                                                   urb->status);
39095 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39096 +
39097 +                               if (failed)
39098 +                                       goto stop_scan;
39099 +                       } else if (qh->ep_type == UE_CONTROL) {
39100 +                               if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
39101 +                                       if (urb->length > 0) {
39102 +                                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
39103 +                                       } else {
39104 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39105 +                                       }
39106 +                                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction done\n");
39107 +                               } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39108 +                                       if (xfer_done) {
39109 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39110 +                                               DWC_DEBUGPL(DBG_HCDV, "  Control data transfer done\n");
39111 +                                       } else if (i + 1 == qtd->n_desc) {
39112 +                                               /*
39113 +                                                * Last descriptor for Control data stage which is
39114 +                                                * not completed yet.
39115 +                                                */
39116 +                                               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39117 +                                       }
39118 +                               }
39119 +                       }
39120 +
39121 +                       n_desc++;
39122 +               }
39123 +
39124 +       }
39125 +
39126 +stop_scan:
39127 +
39128 +       if (qh->ep_type != UE_CONTROL) {
39129 +               /*
39130 +                * Resetting the data toggle for bulk
39131 +                * and interrupt endpoints in case of stall. See handle_hc_stall_intr()
39132 +                */
39133 +               if (halt_status == DWC_OTG_HC_XFER_STALL)
39134 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
39135 +               else
39136 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39137 +       }
39138 +
39139 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39140 +               hcint_data_t hcint;
39141 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
39142 +               if (hcint.b.nyet) {
39143 +                       /*
39144 +                        * Got a NYET on the last transaction of the transfer. It
39145 +                        * means that the endpoint should be in the PING state at the
39146 +                        * beginning of the next transfer.
39147 +                        */
39148 +                       qh->ping_state = 1;
39149 +                       clear_hc_int(hc_regs, nyet);
39150 +               }
39151 +
39152 +       }
39153 +
39154 +}
39155 +
39156 +/**
39157 + * This function is called from interrupt handlers.
39158 + * Scans the descriptor list, updates URB's status and
39159 + * calls completion routine for the URB if it's done.
39160 + * Releases the channel to be used by other transfers.
39161 + * In case of Isochronous endpoint the channel is not halted until
39162 + * the end of the session, i.e. QTD list is empty.
39163 + * If periodic channel released the FrameList is updated accordingly.
39164 + *
39165 + * Calls transaction selection routines to activate pending transfers.
39166 + *
39167 + * @param hcd The HCD state structure for the DWC OTG controller.
39168 + * @param hc Host channel, the transfer is completed on.
39169 + * @param hc_regs Host channel registers.
39170 + * @param halt_status Reason the channel is being halted,
39171 + *                   or just XferComplete for isochronous transfer
39172 + */
39173 +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
39174 +                                   dwc_hc_t * hc,
39175 +                                   dwc_otg_hc_regs_t * hc_regs,
39176 +                                   dwc_otg_halt_status_e halt_status)
39177 +{
39178 +       uint8_t continue_isoc_xfer = 0;
39179 +       dwc_otg_transaction_type_e tr_type;
39180 +       dwc_otg_qh_t *qh = hc->qh;
39181 +
39182 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
39183 +
39184 +               complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39185 +
39186 +               /* Release the channel if halted or session completed */
39187 +               if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
39188 +                   DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39189 +
39190 +                       /* Halt the channel if session completed */
39191 +                       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39192 +                               dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
39193 +                       }
39194 +
39195 +                       release_channel_ddma(hcd, qh);
39196 +                       dwc_otg_hcd_qh_remove(hcd, qh);
39197 +               } else {
39198 +                       /* Keep in assigned schedule to continue transfer */
39199 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
39200 +                                          &qh->qh_list_entry);
39201 +                       continue_isoc_xfer = 1;
39202 +
39203 +               }
39204 +               /** @todo Consider the case when period exceeds FrameList size.
39205 +                *  Frame Rollover interrupt should be used.
39206 +                */
39207 +       } else {
39208 +               /* Scan descriptor list to complete the URB(s), then release the channel */
39209 +               complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39210 +
39211 +               release_channel_ddma(hcd, qh);
39212 +               dwc_otg_hcd_qh_remove(hcd, qh);
39213 +
39214 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39215 +                       /* Add back to inactive non-periodic schedule on normal completion */
39216 +                       dwc_otg_hcd_qh_add(hcd, qh);
39217 +               }
39218 +
39219 +       }
39220 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
39221 +       if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
39222 +               if (continue_isoc_xfer) {
39223 +                       if (tr_type == DWC_OTG_TRANSACTION_NONE) {
39224 +                               tr_type = DWC_OTG_TRANSACTION_PERIODIC;
39225 +                       } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
39226 +                               tr_type = DWC_OTG_TRANSACTION_ALL;
39227 +                       }
39228 +               }
39229 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
39230 +       }
39231 +}
39232 +
39233 +#endif /* DWC_DEVICE_ONLY */
39234 --- /dev/null
39235 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39236 @@ -0,0 +1,412 @@
39237 +/* ==========================================================================
39238 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
39239 + * $Revision: #12 $
39240 + * $Date: 2011/10/26 $
39241 + * $Change: 1873028 $
39242 + *
39243 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39244 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39245 + * otherwise expressly agreed to in writing between Synopsys and you.
39246 + *
39247 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39248 + * any End User Software License Agreement or Agreement for Licensed Product
39249 + * with Synopsys or any supplement thereto. You are permitted to use and
39250 + * redistribute this Software in source and binary forms, with or without
39251 + * modification, provided that redistributions of source code must retain this
39252 + * notice. You may not view, use, disclose, copy or distribute this file or
39253 + * any information contained herein except pursuant to this license grant from
39254 + * Synopsys. If you do not agree with this notice, including the disclaimer
39255 + * below, then you are not authorized to use the Software.
39256 + *
39257 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39258 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39259 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39260 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39261 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39262 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39263 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39264 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39265 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39266 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39267 + * DAMAGE.
39268 + * ========================================================================== */
39269 +#ifndef DWC_DEVICE_ONLY
39270 +#ifndef __DWC_HCD_IF_H__
39271 +#define __DWC_HCD_IF_H__
39272 +
39273 +#include "dwc_otg_core_if.h"
39274 +
39275 +/** @file
39276 + * This file defines DWC_OTG HCD Core API.
39277 + */
39278 +
39279 +struct dwc_otg_hcd;
39280 +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
39281 +
39282 +struct dwc_otg_hcd_urb;
39283 +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
39284 +
39285 +/** @name HCD Function Driver Callbacks */
39286 +/** @{ */
39287 +
39288 +/** This function is called whenever core switches to host mode. */
39289 +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
39290 +
39291 +/** This function is called when device has been disconnected */
39292 +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
39293 +
39294 +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
39295 +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39296 +                                                  void *urb_handle,
39297 +                                                  uint32_t * hub_addr,
39298 +                                                  uint32_t * port_addr);
39299 +/** Via this function HCD core gets device speed */
39300 +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39301 +                                               void *urb_handle);
39302 +
39303 +/** This function is called when urb is completed */
39304 +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
39305 +                                             void *urb_handle,
39306 +                                             dwc_otg_hcd_urb_t * dwc_otg_urb,
39307 +                                             int32_t status);
39308 +
39309 +/** Via this function HCD core gets b_hnp_enable parameter */
39310 +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
39311 +
39312 +struct dwc_otg_hcd_function_ops {
39313 +       dwc_otg_hcd_start_cb_t start;
39314 +       dwc_otg_hcd_disconnect_cb_t disconnect;
39315 +       dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
39316 +       dwc_otg_hcd_speed_from_urb_cb_t speed;
39317 +       dwc_otg_hcd_complete_urb_cb_t complete;
39318 +       dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
39319 +};
39320 +/** @} */
39321 +
39322 +/** @name HCD Core API */
39323 +/** @{ */
39324 +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
39325 +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
39326 +
39327 +/** This function should be called to initiate HCD Core.
39328 + *
39329 + * @param hcd The HCD
39330 + * @param core_if The DWC_OTG Core
39331 + *
39332 + * Returns -DWC_E_NO_MEMORY if no enough memory.
39333 + * Returns 0 on success
39334 + */
39335 +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
39336 +
39337 +/** Frees HCD
39338 + *
39339 + * @param hcd The HCD
39340 + */
39341 +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
39342 +
39343 +/** This function should be called on every hardware interrupt.
39344 + *
39345 + * @param dwc_otg_hcd The HCD
39346 + *
39347 + * Returns non zero if interrupt is handled
39348 + * Return 0 if interrupt is not handled
39349 + */
39350 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
39351 +
39352 +/**
39353 + * Returns private data set by
39354 + * dwc_otg_hcd_set_priv_data function.
39355 + *
39356 + * @param hcd The HCD
39357 + */
39358 +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
39359 +
39360 +/**
39361 + * Set private data.
39362 + *
39363 + * @param hcd The HCD
39364 + * @param priv_data pointer to be stored in private data
39365 + */
39366 +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
39367 +
39368 +/**
39369 + * This function initializes the HCD Core.
39370 + *
39371 + * @param hcd The HCD
39372 + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
39373 + *
39374 + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
39375 + * Returns 0 on success
39376 + */
39377 +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
39378 +                            struct dwc_otg_hcd_function_ops *fops);
39379 +
39380 +/**
39381 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
39382 + * stopped.
39383 + *
39384 + * @param hcd The HCD
39385 + */
39386 +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
39387 +
39388 +/**
39389 + * Handles hub class-specific requests.
39390 + *
39391 + * @param dwc_otg_hcd The HCD
39392 + * @param typeReq Request Type
39393 + * @param wValue wValue from control request
39394 + * @param wIndex wIndex from control request
39395 + * @param buf data buffer
39396 + * @param wLength data buffer length
39397 + *
39398 + * Returns -DWC_E_INVALID if invalid argument is passed
39399 + * Returns 0 on success
39400 + */
39401 +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
39402 +                                  uint16_t typeReq, uint16_t wValue,
39403 +                                  uint16_t wIndex, uint8_t * buf,
39404 +                                  uint16_t wLength);
39405 +
39406 +/**
39407 + * Returns otg port number.
39408 + *
39409 + * @param hcd The HCD
39410 + */
39411 +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
39412 +
39413 +/**
39414 + * Returns OTG version - either 1.3 or 2.0.
39415 + *
39416 + * @param core_if The core_if structure pointer
39417 + */
39418 +extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
39419 +
39420 +/**
39421 + * Returns 1 if currently core is acting as B host, and 0 otherwise.
39422 + *
39423 + * @param hcd The HCD
39424 + */
39425 +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
39426 +
39427 +/**
39428 + * Returns current frame number.
39429 + *
39430 + * @param hcd The HCD
39431 + */
39432 +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
39433 +
39434 +/**
39435 + * Dumps hcd state.
39436 + *
39437 + * @param hcd The HCD
39438 + */
39439 +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
39440 +
39441 +/**
39442 + * Dump the average frame remaining at SOF. This can be used to
39443 + * determine average interrupt latency. Frame remaining is also shown for
39444 + * start transfer and two additional sample points.
39445 + * Currently this function is not implemented.
39446 + *
39447 + * @param hcd The HCD
39448 + */
39449 +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
39450 +
39451 +/**
39452 + * Sends LPM transaction to the local device.
39453 + *
39454 + * @param hcd The HCD
39455 + * @param devaddr Device Address
39456 + * @param hird Host initiated resume duration
39457 + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
39458 + *
39459 + * Returns negative value if sending LPM transaction was not succeeded.
39460 + * Returns 0 on success.
39461 + */
39462 +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
39463 +                               uint8_t hird, uint8_t bRemoteWake);
39464 +
39465 +/* URB interface */
39466 +
39467 +/**
39468 + * Allocates memory for dwc_otg_hcd_urb structure.
39469 + * Allocated memory should be freed by call of DWC_FREE.
39470 + *
39471 + * @param hcd The HCD
39472 + * @param iso_desc_count Count of ISOC descriptors
39473 + * @param atomic_alloc Specefies whether to perform atomic allocation.
39474 + */
39475 +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
39476 +                                               int iso_desc_count,
39477 +                                               int atomic_alloc);
39478 +
39479 +/**
39480 + * Set pipe information in URB.
39481 + *
39482 + * @param hcd_urb DWC_OTG URB
39483 + * @param devaddr Device Address
39484 + * @param ep_num Endpoint Number
39485 + * @param ep_type Endpoint Type
39486 + * @param ep_dir Endpoint Direction
39487 + * @param mps Max Packet Size
39488 + */
39489 +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
39490 +                                        uint8_t devaddr, uint8_t ep_num,
39491 +                                        uint8_t ep_type, uint8_t ep_dir,
39492 +                                        uint16_t mps);
39493 +
39494 +/* Transfer flags */
39495 +#define URB_GIVEBACK_ASAP 0x1
39496 +#define URB_SEND_ZERO_PACKET 0x2
39497 +
39498 +/**
39499 + * Sets dwc_otg_hcd_urb parameters.
39500 + *
39501 + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
39502 + * @param urb_handle Unique handle for request, this will be passed back
39503 + * to function driver in completion callback.
39504 + * @param buf The buffer for the data
39505 + * @param dma The DMA buffer for the data
39506 + * @param buflen Transfer length
39507 + * @param sp Buffer for setup data
39508 + * @param sp_dma DMA address of setup data buffer
39509 + * @param flags Transfer flags
39510 + * @param interval Polling interval for interrupt or isochronous transfers.
39511 + */
39512 +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
39513 +                                      void *urb_handle, void *buf,
39514 +                                      dwc_dma_t dma, uint32_t buflen, void *sp,
39515 +                                      dwc_dma_t sp_dma, uint32_t flags,
39516 +                                      uint16_t interval);
39517 +
39518 +/** Gets status from dwc_otg_hcd_urb
39519 + *
39520 + * @param dwc_otg_urb DWC_OTG URB
39521 + */
39522 +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
39523 +
39524 +/** Gets actual length from dwc_otg_hcd_urb
39525 + *
39526 + * @param dwc_otg_urb DWC_OTG URB
39527 + */
39528 +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
39529 +                                                 dwc_otg_urb);
39530 +
39531 +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
39532 + *
39533 + * @param dwc_otg_urb DWC_OTG URB
39534 + */
39535 +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
39536 +                                               dwc_otg_urb);
39537 +
39538 +/** Set ISOC descriptor offset and length
39539 + *
39540 + * @param dwc_otg_urb DWC_OTG URB
39541 + * @param desc_num ISOC descriptor number
39542 + * @param offset Offset from beginig of buffer.
39543 + * @param length Transaction length
39544 + */
39545 +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
39546 +                                               int desc_num, uint32_t offset,
39547 +                                               uint32_t length);
39548 +
39549 +/** Get status of ISOC descriptor, specified by desc_num
39550 + *
39551 + * @param dwc_otg_urb DWC_OTG URB
39552 + * @param desc_num ISOC descriptor number
39553 + */
39554 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
39555 +                                                   dwc_otg_urb, int desc_num);
39556 +
39557 +/** Get actual length of ISOC descriptor, specified by desc_num
39558 + *
39559 + * @param dwc_otg_urb DWC_OTG URB
39560 + * @param desc_num ISOC descriptor number
39561 + */
39562 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
39563 +                                                          dwc_otg_urb,
39564 +                                                          int desc_num);
39565 +
39566 +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
39567 + *
39568 + * @param dwc_otg_hcd The HCD
39569 + * @param dwc_otg_urb DWC_OTG URB
39570 + * @param ep_handle Out parameter for returning endpoint handle
39571 + * @param atomic_alloc Flag to do atomic allocation if needed
39572 + *
39573 + * Returns -DWC_E_NO_DEVICE if no device is connected.
39574 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
39575 + * Returns 0 on success.
39576 + */
39577 +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
39578 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb,
39579 +                                  void **ep_handle, int atomic_alloc);
39580 +
39581 +/** De-queue the specified URB
39582 + *
39583 + * @param dwc_otg_hcd The HCD
39584 + * @param dwc_otg_urb DWC_OTG URB
39585 + */
39586 +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
39587 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb);
39588 +
39589 +/** Frees resources in the DWC_otg controller related to a given endpoint.
39590 + * Any URBs for the endpoint must already be dequeued.
39591 + *
39592 + * @param hcd The HCD
39593 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39594 + * @param retry Number of retries if there are queued transfers.
39595 + *
39596 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39597 + * Returns 0 on success
39598 + */
39599 +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
39600 +                                       int retry);
39601 +
39602 +/* Resets the data toggle in qh structure. This function can be called from
39603 + * usb_clear_halt routine.
39604 + *
39605 + * @param hcd The HCD
39606 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39607 + *
39608 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39609 + * Returns 0 on success
39610 + */
39611 +extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);
39612 +
39613 +/** Returns 1 if status of specified port is changed and 0 otherwise.
39614 + *
39615 + * @param hcd The HCD
39616 + * @param port Port number
39617 + */
39618 +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
39619 +
39620 +/** Call this function to check if bandwidth was allocated for specified endpoint.
39621 + * Only for ISOC and INTERRUPT endpoints.
39622 + *
39623 + * @param hcd The HCD
39624 + * @param ep_handle Endpoint handle
39625 + */
39626 +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
39627 +                                             void *ep_handle);
39628 +
39629 +/** Call this function to check if bandwidth was freed for specified endpoint.
39630 + *
39631 + * @param hcd The HCD
39632 + * @param ep_handle Endpoint handle
39633 + */
39634 +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
39635 +
39636 +/** Returns bandwidth allocated for specified endpoint in microseconds.
39637 + * Only for ISOC and INTERRUPT endpoints.
39638 + *
39639 + * @param hcd The HCD
39640 + * @param ep_handle Endpoint handle
39641 + */
39642 +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
39643 +                                           void *ep_handle);
39644 +
39645 +/** @} */
39646 +
39647 +#endif /* __DWC_HCD_IF_H__ */
39648 +#endif /* DWC_DEVICE_ONLY */
39649 --- /dev/null
39650 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39651 @@ -0,0 +1,2106 @@
39652 +/* ==========================================================================
39653 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
39654 + * $Revision: #89 $
39655 + * $Date: 2011/10/20 $
39656 + * $Change: 1869487 $
39657 + *
39658 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39659 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39660 + * otherwise expressly agreed to in writing between Synopsys and you.
39661 + *
39662 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39663 + * any End User Software License Agreement or Agreement for Licensed Product
39664 + * with Synopsys or any supplement thereto. You are permitted to use and
39665 + * redistribute this Software in source and binary forms, with or without
39666 + * modification, provided that redistributions of source code must retain this
39667 + * notice. You may not view, use, disclose, copy or distribute this file or
39668 + * any information contained herein except pursuant to this license grant from
39669 + * Synopsys. If you do not agree with this notice, including the disclaimer
39670 + * below, then you are not authorized to use the Software.
39671 + *
39672 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39673 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39674 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39675 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39676 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39677 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39678 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39679 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39680 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39681 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39682 + * DAMAGE.
39683 + * ========================================================================== */
39684 +#ifndef DWC_DEVICE_ONLY
39685 +
39686 +#include "dwc_otg_hcd.h"
39687 +#include "dwc_otg_regs.h"
39688 +
39689 +extern bool microframe_schedule;
39690 +
39691 +/** @file
39692 + * This file contains the implementation of the HCD Interrupt handlers.
39693 + */
39694 +
39695 +/** This function handles interrupts for the HCD. */
39696 +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39697 +{
39698 +       int retval = 0;
39699 +
39700 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
39701 +       gintsts_data_t gintsts;
39702 +#ifdef DEBUG
39703 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
39704 +
39705 +        //GRAYG: debugging
39706 +        if (NULL == global_regs) {
39707 +                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
39708 +                            "core_if=%p\n",
39709 +                            dwc_otg_hcd, global_regs);
39710 +                return retval;
39711 +        }
39712 +#endif
39713 +
39714 +       /* Exit from ISR if core is hibernated */
39715 +       if (core_if->hibernation_suspend == 1) {
39716 +               return retval;
39717 +       }
39718 +       DWC_SPINLOCK(dwc_otg_hcd->lock);
39719 +       /* Check if HOST Mode */
39720 +       if (dwc_otg_is_host_mode(core_if)) {
39721 +               gintsts.d32 = dwc_otg_read_core_intr(core_if);
39722 +               if (!gintsts.d32) {
39723 +                       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39724 +                       return 0;
39725 +               }
39726 +#ifdef DEBUG
39727 +               /* Don't print debug message in the interrupt handler on SOF */
39728 +#ifndef DEBUG_SOF
39729 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39730 +#endif
39731 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39732 +#endif
39733 +
39734 +#ifdef DEBUG
39735 +#ifndef DEBUG_SOF
39736 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39737 +#endif
39738 +                       DWC_DEBUGPL(DBG_HCDI,
39739 +                                   "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
39740 +                                   gintsts.d32, core_if);
39741 +#endif
39742 +
39743 +               if (gintsts.b.sofintr) {
39744 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
39745 +               }
39746 +               if (gintsts.b.rxstsqlvl) {
39747 +                       retval |=
39748 +                           dwc_otg_hcd_handle_rx_status_q_level_intr
39749 +                           (dwc_otg_hcd);
39750 +               }
39751 +               if (gintsts.b.nptxfempty) {
39752 +                       retval |=
39753 +                           dwc_otg_hcd_handle_np_tx_fifo_empty_intr
39754 +                           (dwc_otg_hcd);
39755 +               }
39756 +               if (gintsts.b.i2cintr) {
39757 +                       /** @todo Implement i2cintr handler. */
39758 +               }
39759 +               if (gintsts.b.portintr) {
39760 +                       retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
39761 +               }
39762 +               if (gintsts.b.hcintr) {
39763 +                       retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
39764 +               }
39765 +               if (gintsts.b.ptxfempty) {
39766 +                       retval |=
39767 +                           dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
39768 +                           (dwc_otg_hcd);
39769 +               }
39770 +#ifdef DEBUG
39771 +#ifndef DEBUG_SOF
39772 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39773 +#endif
39774 +               {
39775 +                       DWC_DEBUGPL(DBG_HCDI,
39776 +                                   "DWC OTG HCD Finished Servicing Interrupts\n");
39777 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
39778 +                                   DWC_READ_REG32(&global_regs->gintsts));
39779 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
39780 +                                   DWC_READ_REG32(&global_regs->gintmsk));
39781 +               }
39782 +#endif
39783 +
39784 +#ifdef DEBUG
39785 +#ifndef DEBUG_SOF
39786 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39787 +#endif
39788 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39789 +#endif
39790 +
39791 +       }
39792 +       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39793 +       return retval;
39794 +}
39795 +
39796 +#ifdef DWC_TRACK_MISSED_SOFS
39797 +#warning Compiling code to track missed SOFs
39798 +#define FRAME_NUM_ARRAY_SIZE 1000
39799 +/**
39800 + * This function is for debug only.
39801 + */
39802 +static inline void track_missed_sofs(uint16_t curr_frame_number)
39803 +{
39804 +       static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
39805 +       static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
39806 +       static int frame_num_idx = 0;
39807 +       static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
39808 +       static int dumped_frame_num_array = 0;
39809 +
39810 +       if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
39811 +               if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
39812 +                   curr_frame_number) {
39813 +                       frame_num_array[frame_num_idx] = curr_frame_number;
39814 +                       last_frame_num_array[frame_num_idx++] = last_frame_num;
39815 +               }
39816 +       } else if (!dumped_frame_num_array) {
39817 +               int i;
39818 +               DWC_PRINTF("Frame     Last Frame\n");
39819 +               DWC_PRINTF("-----     ----------\n");
39820 +               for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
39821 +                       DWC_PRINTF("0x%04x    0x%04x\n",
39822 +                                  frame_num_array[i], last_frame_num_array[i]);
39823 +               }
39824 +               dumped_frame_num_array = 1;
39825 +       }
39826 +       last_frame_num = curr_frame_number;
39827 +}
39828 +#endif
39829 +
39830 +/**
39831 + * Handles the start-of-frame interrupt in host mode. Non-periodic
39832 + * transactions may be queued to the DWC_otg controller for the current
39833 + * (micro)frame. Periodic transactions may be queued to the controller for the
39834 + * next (micro)frame.
39835 + */
39836 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
39837 +{
39838 +       hfnum_data_t hfnum;
39839 +       dwc_list_link_t *qh_entry;
39840 +       dwc_otg_qh_t *qh;
39841 +       dwc_otg_transaction_type_e tr_type;
39842 +       gintsts_data_t gintsts = {.d32 = 0 };
39843 +
39844 +       hfnum.d32 =
39845 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
39846 +
39847 +#ifdef DEBUG_SOF
39848 +       DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
39849 +#endif
39850 +       hcd->frame_number = hfnum.b.frnum;
39851 +
39852 +#ifdef DEBUG
39853 +       hcd->frrem_accum += hfnum.b.frrem;
39854 +       hcd->frrem_samples++;
39855 +#endif
39856 +
39857 +#ifdef DWC_TRACK_MISSED_SOFS
39858 +       track_missed_sofs(hcd->frame_number);
39859 +#endif
39860 +       /* Determine whether any periodic QHs should be executed. */
39861 +       qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
39862 +       while (qh_entry != &hcd->periodic_sched_inactive) {
39863 +               qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
39864 +               qh_entry = qh_entry->next;
39865 +               if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
39866 +                       /*
39867 +                        * Move QH to the ready list to be executed next
39868 +                        * (micro)frame.
39869 +                        */
39870 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
39871 +                                          &qh->qh_list_entry);
39872 +               }
39873 +       }
39874 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
39875 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
39876 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
39877 +       }
39878 +
39879 +       /* Clear interrupt */
39880 +       gintsts.b.sofintr = 1;
39881 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
39882 +
39883 +       return 1;
39884 +}
39885 +
39886 +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
39887 + * least one packet in the Rx FIFO.  The packets are moved from the FIFO to
39888 + * memory if the DWC_otg controller is operating in Slave mode. */
39889 +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39890 +{
39891 +       host_grxsts_data_t grxsts;
39892 +       dwc_hc_t *hc = NULL;
39893 +
39894 +       DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
39895 +
39896 +       grxsts.d32 =
39897 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
39898 +
39899 +       hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
39900 +       if (!hc) {
39901 +               DWC_ERROR("Unable to get corresponding channel\n");
39902 +               return 0;
39903 +       }
39904 +
39905 +       /* Packet Status */
39906 +       DWC_DEBUGPL(DBG_HCDV, "    Ch num = %d\n", grxsts.b.chnum);
39907 +       DWC_DEBUGPL(DBG_HCDV, "    Count = %d\n", grxsts.b.bcnt);
39908 +       DWC_DEBUGPL(DBG_HCDV, "    DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
39909 +                   hc->data_pid_start);
39910 +       DWC_DEBUGPL(DBG_HCDV, "    PStatus = %d\n", grxsts.b.pktsts);
39911 +
39912 +       switch (grxsts.b.pktsts) {
39913 +       case DWC_GRXSTS_PKTSTS_IN:
39914 +               /* Read the data into the host buffer. */
39915 +               if (grxsts.b.bcnt > 0) {
39916 +                       dwc_otg_read_packet(dwc_otg_hcd->core_if,
39917 +                                           hc->xfer_buff, grxsts.b.bcnt);
39918 +
39919 +                       /* Update the HC fields for the next packet received. */
39920 +                       hc->xfer_count += grxsts.b.bcnt;
39921 +                       hc->xfer_buff += grxsts.b.bcnt;
39922 +               }
39923 +
39924 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
39925 +       case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
39926 +       case DWC_GRXSTS_PKTSTS_CH_HALTED:
39927 +               /* Handled in interrupt, just ignore data */
39928 +               break;
39929 +       default:
39930 +               DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
39931 +                         grxsts.b.pktsts);
39932 +               break;
39933 +       }
39934 +
39935 +       return 1;
39936 +}
39937 +
39938 +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
39939 + * data packets may be written to the FIFO for OUT transfers. More requests
39940 + * may be written to the non-periodic request queue for IN transfers. This
39941 + * interrupt is enabled only in Slave mode. */
39942 +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39943 +{
39944 +       DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
39945 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
39946 +                                      DWC_OTG_TRANSACTION_NON_PERIODIC);
39947 +       return 1;
39948 +}
39949 +
39950 +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
39951 + * packets may be written to the FIFO for OUT transfers. More requests may be
39952 + * written to the periodic request queue for IN transfers. This interrupt is
39953 + * enabled only in Slave mode. */
39954 +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39955 +{
39956 +       DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
39957 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
39958 +                                      DWC_OTG_TRANSACTION_PERIODIC);
39959 +       return 1;
39960 +}
39961 +
39962 +/** There are multiple conditions that can cause a port interrupt. This function
39963 + * determines which interrupt conditions have occurred and handles them
39964 + * appropriately. */
39965 +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39966 +{
39967 +       int retval = 0;
39968 +       hprt0_data_t hprt0;
39969 +       hprt0_data_t hprt0_modify;
39970 +
39971 +       hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
39972 +       hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
39973 +
39974 +       /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
39975 +        * GINTSTS */
39976 +
39977 +       hprt0_modify.b.prtena = 0;
39978 +       hprt0_modify.b.prtconndet = 0;
39979 +       hprt0_modify.b.prtenchng = 0;
39980 +       hprt0_modify.b.prtovrcurrchng = 0;
39981 +
39982 +       /* Port Connect Detected
39983 +        * Set flag and clear if detected */
39984 +       if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
39985 +               // Dont modify port status if we are in hibernation state
39986 +               hprt0_modify.b.prtconndet = 1;
39987 +               hprt0_modify.b.prtenchng = 1;
39988 +               DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
39989 +               hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
39990 +               return retval;
39991 +       }
39992 +
39993 +       if (hprt0.b.prtconndet) {
39994 +               /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
39995 +               if (dwc_otg_hcd->core_if->adp_enable &&
39996 +                               dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
39997 +                       DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
39998 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
39999 +                       dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40000 +                       /* TODO - check if this is required, as
40001 +                        * host initialization was already performed
40002 +                        * after initial ADP probing
40003 +                        */
40004 +                       /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40005 +                       dwc_otg_core_init(dwc_otg_hcd->core_if);
40006 +                       dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
40007 +                       cil_hcd_start(dwc_otg_hcd->core_if);*/
40008 +               } else {
40009 +
40010 +                       DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
40011 +                                   "Port Connect Detected--\n", hprt0.d32);
40012 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
40013 +                       dwc_otg_hcd->flags.b.port_connect_status = 1;
40014 +                       hprt0_modify.b.prtconndet = 1;
40015 +
40016 +                       /* B-Device has connected, Delete the connection timer. */
40017 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
40018 +               }
40019 +               /* The Hub driver asserts a reset when it sees port connect
40020 +                * status change flag */
40021 +               retval |= 1;
40022 +       }
40023 +
40024 +       /* Port Enable Changed
40025 +        * Clear if detected - Set internal flag if disabled */
40026 +       if (hprt0.b.prtenchng) {
40027 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40028 +                           "Port Enable Changed--\n", hprt0.d32);
40029 +               hprt0_modify.b.prtenchng = 1;
40030 +               if (hprt0.b.prtena == 1) {
40031 +                       hfir_data_t hfir;
40032 +                       int do_reset = 0;
40033 +                       dwc_otg_core_params_t *params =
40034 +                           dwc_otg_hcd->core_if->core_params;
40035 +                       dwc_otg_core_global_regs_t *global_regs =
40036 +                           dwc_otg_hcd->core_if->core_global_regs;
40037 +                       dwc_otg_host_if_t *host_if =
40038 +                           dwc_otg_hcd->core_if->host_if;
40039 +
40040 +                       /* Every time when port enables calculate
40041 +                        * HFIR.FrInterval
40042 +                        */
40043 +                       hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
40044 +                       hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
40045 +                       DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
40046 +
40047 +                       /* Check if we need to adjust the PHY clock speed for
40048 +                        * low power and adjust it */
40049 +                       if (params->host_support_fs_ls_low_power) {
40050 +                               gusbcfg_data_t usbcfg;
40051 +
40052 +                               usbcfg.d32 =
40053 +                                   DWC_READ_REG32(&global_regs->gusbcfg);
40054 +
40055 +                               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
40056 +                                   || hprt0.b.prtspd ==
40057 +                                   DWC_HPRT0_PRTSPD_FULL_SPEED) {
40058 +                                       /*
40059 +                                        * Low power
40060 +                                        */
40061 +                                       hcfg_data_t hcfg;
40062 +                                       if (usbcfg.b.phylpwrclksel == 0) {
40063 +                                               /* Set PHY low power clock select for FS/LS devices */
40064 +                                               usbcfg.b.phylpwrclksel = 1;
40065 +                                               DWC_WRITE_REG32
40066 +                                                   (&global_regs->gusbcfg,
40067 +                                                    usbcfg.d32);
40068 +                                               do_reset = 1;
40069 +                                       }
40070 +
40071 +                                       hcfg.d32 =
40072 +                                           DWC_READ_REG32
40073 +                                           (&host_if->host_global_regs->hcfg);
40074 +
40075 +                                       if (hprt0.b.prtspd ==
40076 +                                           DWC_HPRT0_PRTSPD_LOW_SPEED
40077 +                                           && params->host_ls_low_power_phy_clk
40078 +                                           ==
40079 +                                           DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
40080 +                                       {
40081 +                                               /* 6 MHZ */
40082 +                                               DWC_DEBUGPL(DBG_CIL,
40083 +                                                           "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
40084 +                                               if (hcfg.b.fslspclksel !=
40085 +                                                   DWC_HCFG_6_MHZ) {
40086 +                                                       hcfg.b.fslspclksel =
40087 +                                                           DWC_HCFG_6_MHZ;
40088 +                                                       DWC_WRITE_REG32
40089 +                                                           (&host_if->host_global_regs->hcfg,
40090 +                                                            hcfg.d32);
40091 +                                                       do_reset = 1;
40092 +                                               }
40093 +                                       } else {
40094 +                                               /* 48 MHZ */
40095 +                                               DWC_DEBUGPL(DBG_CIL,
40096 +                                                           "FS_PHY programming HCFG to 48 MHz ()\n");
40097 +                                               if (hcfg.b.fslspclksel !=
40098 +                                                   DWC_HCFG_48_MHZ) {
40099 +                                                       hcfg.b.fslspclksel =
40100 +                                                           DWC_HCFG_48_MHZ;
40101 +                                                       DWC_WRITE_REG32
40102 +                                                           (&host_if->host_global_regs->hcfg,
40103 +                                                            hcfg.d32);
40104 +                                                       do_reset = 1;
40105 +                                               }
40106 +                                       }
40107 +                               } else {
40108 +                                       /*
40109 +                                        * Not low power
40110 +                                        */
40111 +                                       if (usbcfg.b.phylpwrclksel == 1) {
40112 +                                               usbcfg.b.phylpwrclksel = 0;
40113 +                                               DWC_WRITE_REG32
40114 +                                                   (&global_regs->gusbcfg,
40115 +                                                    usbcfg.d32);
40116 +                                               do_reset = 1;
40117 +                                       }
40118 +                               }
40119 +
40120 +                               if (do_reset) {
40121 +                                       DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
40122 +                               }
40123 +                       }
40124 +
40125 +                       if (!do_reset) {
40126 +                               /* Port has been enabled set the reset change flag */
40127 +                               dwc_otg_hcd->flags.b.port_reset_change = 1;
40128 +                       }
40129 +               } else {
40130 +                       dwc_otg_hcd->flags.b.port_enable_change = 1;
40131 +               }
40132 +               retval |= 1;
40133 +       }
40134 +
40135 +       /** Overcurrent Change Interrupt */
40136 +       if (hprt0.b.prtovrcurrchng) {
40137 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40138 +                           "Port Overcurrent Changed--\n", hprt0.d32);
40139 +               dwc_otg_hcd->flags.b.port_over_current_change = 1;
40140 +               hprt0_modify.b.prtovrcurrchng = 1;
40141 +               retval |= 1;
40142 +       }
40143 +
40144 +       /* Clear Port Interrupts */
40145 +       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40146 +
40147 +       return retval;
40148 +}
40149 +
40150 +/** This interrupt indicates that one or more host channels has a pending
40151 + * interrupt. There are multiple conditions that can cause each host channel
40152 + * interrupt. This function determines which conditions have occurred for each
40153 + * host channel interrupt and handles them appropriately. */
40154 +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40155 +{
40156 +       int i;
40157 +       int retval = 0;
40158 +       haint_data_t haint;
40159 +
40160 +       /* Clear appropriate bits in HCINTn to clear the interrupt bit in
40161 +        * GINTSTS */
40162 +
40163 +       haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
40164 +
40165 +       for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
40166 +               if (haint.b2.chint & (1 << i)) {
40167 +                       retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
40168 +               }
40169 +       }
40170 +
40171 +       return retval;
40172 +}
40173 +
40174 +/**
40175 + * Gets the actual length of a transfer after the transfer halts. _halt_status
40176 + * holds the reason for the halt.
40177 + *
40178 + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
40179 + * *short_read is set to 1 upon return if less than the requested
40180 + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
40181 + * return. short_read may also be NULL on entry, in which case it remains
40182 + * unchanged.
40183 + */
40184 +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
40185 +                                      dwc_otg_hc_regs_t * hc_regs,
40186 +                                      dwc_otg_qtd_t * qtd,
40187 +                                      dwc_otg_halt_status_e halt_status,
40188 +                                      int *short_read)
40189 +{
40190 +       hctsiz_data_t hctsiz;
40191 +       uint32_t length;
40192 +
40193 +       if (short_read != NULL) {
40194 +               *short_read = 0;
40195 +       }
40196 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40197 +
40198 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
40199 +               if (hc->ep_is_in) {
40200 +                       length = hc->xfer_len - hctsiz.b.xfersize;
40201 +                       if (short_read != NULL) {
40202 +                               *short_read = (hctsiz.b.xfersize != 0);
40203 +                       }
40204 +               } else if (hc->qh->do_split) {
40205 +                       length = qtd->ssplit_out_xfer_count;
40206 +               } else {
40207 +                       length = hc->xfer_len;
40208 +               }
40209 +       } else {
40210 +               /*
40211 +                * Must use the hctsiz.pktcnt field to determine how much data
40212 +                * has been transferred. This field reflects the number of
40213 +                * packets that have been transferred via the USB. This is
40214 +                * always an integral number of packets if the transfer was
40215 +                * halted before its normal completion. (Can't use the
40216 +                * hctsiz.xfersize field because that reflects the number of
40217 +                * bytes transferred via the AHB, not the USB).
40218 +                */
40219 +               length =
40220 +                   (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
40221 +       }
40222 +
40223 +       return length;
40224 +}
40225 +
40226 +/**
40227 + * Updates the state of the URB after a Transfer Complete interrupt on the
40228 + * host channel. Updates the actual_length field of the URB based on the
40229 + * number of bytes transferred via the host channel. Sets the URB status
40230 + * if the data transfer is finished.
40231 + *
40232 + * @return 1 if the data transfer specified by the URB is completely finished,
40233 + * 0 otherwise.
40234 + */
40235 +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
40236 +                                     dwc_otg_hc_regs_t * hc_regs,
40237 +                                     dwc_otg_hcd_urb_t * urb,
40238 +                                     dwc_otg_qtd_t * qtd)
40239 +{
40240 +       int xfer_done = 0;
40241 +       int short_read = 0;
40242 +
40243 +       int xfer_length;
40244 +
40245 +       xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
40246 +                                            DWC_OTG_HC_XFER_COMPLETE,
40247 +                                            &short_read);
40248 +
40249 +
40250 +       /* non DWORD-aligned buffer case handling. */
40251 +       if (hc->align_buff && xfer_length && hc->ep_is_in) {
40252 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40253 +                          xfer_length);
40254 +       }
40255 +
40256 +       urb->actual_length += xfer_length;
40257 +
40258 +       if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
40259 +           (urb->flags & URB_SEND_ZERO_PACKET)
40260 +           && (urb->actual_length == urb->length)
40261 +           && !(urb->length % hc->max_packet)) {
40262 +               xfer_done = 0;
40263 +       } else if (short_read || urb->actual_length >= urb->length) {
40264 +               xfer_done = 1;
40265 +               urb->status = 0;
40266 +       }
40267 +
40268 +#ifdef DEBUG
40269 +       {
40270 +               hctsiz_data_t hctsiz;
40271 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40272 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40273 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
40274 +                           hc->hc_num);
40275 +               DWC_DEBUGPL(DBG_HCDV, "  hc->xfer_len %d\n", hc->xfer_len);
40276 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.xfersize %d\n",
40277 +                           hctsiz.b.xfersize);
40278 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
40279 +                           urb->length);
40280 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
40281 +                           urb->actual_length);
40282 +               DWC_DEBUGPL(DBG_HCDV, "  short_read %d, xfer_done %d\n",
40283 +                           short_read, xfer_done);
40284 +       }
40285 +#endif
40286 +
40287 +       return xfer_done;
40288 +}
40289 +
40290 +/*
40291 + * Save the starting data toggle for the next transfer. The data toggle is
40292 + * saved in the QH for non-control transfers and it's saved in the QTD for
40293 + * control transfers.
40294 + */
40295 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
40296 +                            dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
40297 +{
40298 +       hctsiz_data_t hctsiz;
40299 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40300 +
40301 +       if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
40302 +               dwc_otg_qh_t *qh = hc->qh;
40303 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40304 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
40305 +               } else {
40306 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA1;
40307 +               }
40308 +       } else {
40309 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40310 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
40311 +               } else {
40312 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
40313 +               }
40314 +       }
40315 +}
40316 +
40317 +/**
40318 + * Updates the state of an Isochronous URB when the transfer is stopped for
40319 + * any reason. The fields of the current entry in the frame descriptor array
40320 + * are set based on the transfer state and the input _halt_status. Completes
40321 + * the Isochronous URB if all the URB frames have been completed.
40322 + *
40323 + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
40324 + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
40325 + */
40326 +static dwc_otg_halt_status_e
40327 +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
40328 +                     dwc_hc_t * hc,
40329 +                     dwc_otg_hc_regs_t * hc_regs,
40330 +                     dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40331 +{
40332 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40333 +       dwc_otg_halt_status_e ret_val = halt_status;
40334 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40335 +
40336 +       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
40337 +       switch (halt_status) {
40338 +       case DWC_OTG_HC_XFER_COMPLETE:
40339 +               frame_desc->status = 0;
40340 +               frame_desc->actual_length =
40341 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40342 +
40343 +               /* non DWORD-aligned buffer case handling. */
40344 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40345 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40346 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40347 +               }
40348 +
40349 +               break;
40350 +       case DWC_OTG_HC_XFER_FRAME_OVERRUN:
40351 +               urb->error_count++;
40352 +               if (hc->ep_is_in) {
40353 +                       frame_desc->status = -DWC_E_NO_STREAM_RES;
40354 +               } else {
40355 +                       frame_desc->status = -DWC_E_COMMUNICATION;
40356 +               }
40357 +               frame_desc->actual_length = 0;
40358 +               break;
40359 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40360 +               urb->error_count++;
40361 +               frame_desc->status = -DWC_E_OVERFLOW;
40362 +               /* Don't need to update actual_length in this case. */
40363 +               break;
40364 +       case DWC_OTG_HC_XFER_XACT_ERR:
40365 +               urb->error_count++;
40366 +               frame_desc->status = -DWC_E_PROTOCOL;
40367 +               frame_desc->actual_length =
40368 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40369 +
40370 +               /* non DWORD-aligned buffer case handling. */
40371 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40372 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40373 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40374 +               }
40375 +               /* Skip whole frame */
40376 +               if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
40377 +                   hc->ep_is_in && hcd->core_if->dma_enable) {
40378 +                       qtd->complete_split = 0;
40379 +                       qtd->isoc_split_offset = 0;
40380 +               }
40381 +
40382 +               break;
40383 +       default:
40384 +               DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
40385 +               break;
40386 +       }
40387 +       if (++qtd->isoc_frame_index == urb->packet_count) {
40388 +               /*
40389 +                * urb->status is not used for isoc transfers.
40390 +                * The individual frame_desc statuses are used instead.
40391 +                */
40392 +               hcd->fops->complete(hcd, urb->priv, urb, 0);
40393 +               ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
40394 +       } else {
40395 +               ret_val = DWC_OTG_HC_XFER_COMPLETE;
40396 +       }
40397 +       return ret_val;
40398 +}
40399 +
40400 +/**
40401 + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
40402 + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
40403 + * still linked to the QH, the QH is added to the end of the inactive
40404 + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
40405 + * schedule if no more QTDs are linked to the QH.
40406 + */
40407 +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
40408 +{
40409 +       int continue_split = 0;
40410 +       dwc_otg_qtd_t *qtd;
40411 +
40412 +       DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
40413 +
40414 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
40415 +
40416 +       if (qtd->complete_split) {
40417 +               continue_split = 1;
40418 +       } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
40419 +                  qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
40420 +               continue_split = 1;
40421 +       }
40422 +
40423 +       if (free_qtd) {
40424 +               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
40425 +               continue_split = 0;
40426 +       }
40427 +
40428 +       qh->channel = NULL;
40429 +       dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
40430 +}
40431 +
40432 +/**
40433 + * Releases a host channel for use by other transfers. Attempts to select and
40434 + * queue more transactions since at least one host channel is available.
40435 + *
40436 + * @param hcd The HCD state structure.
40437 + * @param hc The host channel to release.
40438 + * @param qtd The QTD associated with the host channel. This QTD may be freed
40439 + * if the transfer is complete or an error has occurred.
40440 + * @param halt_status Reason the channel is being released. This status
40441 + * determines the actions taken by this function.
40442 + */
40443 +static void release_channel(dwc_otg_hcd_t * hcd,
40444 +                           dwc_hc_t * hc,
40445 +                           dwc_otg_qtd_t * qtd,
40446 +                           dwc_otg_halt_status_e halt_status)
40447 +{
40448 +       dwc_otg_transaction_type_e tr_type;
40449 +       int free_qtd;
40450 +       dwc_irqflags_t flags;
40451 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
40452 +
40453 +       DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
40454 +                   __func__, hc->hc_num, halt_status, hc->xfer_len);
40455 +
40456 +       switch (halt_status) {
40457 +       case DWC_OTG_HC_XFER_URB_COMPLETE:
40458 +               free_qtd = 1;
40459 +               break;
40460 +       case DWC_OTG_HC_XFER_AHB_ERR:
40461 +       case DWC_OTG_HC_XFER_STALL:
40462 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40463 +               free_qtd = 1;
40464 +               break;
40465 +       case DWC_OTG_HC_XFER_XACT_ERR:
40466 +               if (qtd->error_count >= 3) {
40467 +                       DWC_DEBUGPL(DBG_HCDV,
40468 +                                   "  Complete URB with transaction error\n");
40469 +                       free_qtd = 1;
40470 +                       qtd->urb->status = -DWC_E_PROTOCOL;
40471 +                       hcd->fops->complete(hcd, qtd->urb->priv,
40472 +                                           qtd->urb, -DWC_E_PROTOCOL);
40473 +               } else {
40474 +                       free_qtd = 0;
40475 +               }
40476 +               break;
40477 +       case DWC_OTG_HC_XFER_URB_DEQUEUE:
40478 +               /*
40479 +                * The QTD has already been removed and the QH has been
40480 +                * deactivated. Don't want to do anything except release the
40481 +                * host channel and try to queue more transfers.
40482 +                */
40483 +               goto cleanup;
40484 +       case DWC_OTG_HC_XFER_NO_HALT_STATUS:
40485 +               free_qtd = 0;
40486 +               break;
40487 +       case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
40488 +               DWC_DEBUGPL(DBG_HCDV,
40489 +                       "  Complete URB with I/O error\n");
40490 +               free_qtd = 1;
40491 +               qtd->urb->status = -DWC_E_IO;
40492 +               hcd->fops->complete(hcd, qtd->urb->priv,
40493 +                       qtd->urb, -DWC_E_IO);
40494 +               break;
40495 +       default:
40496 +               free_qtd = 0;
40497 +               break;
40498 +       }
40499 +
40500 +       deactivate_qh(hcd, hc->qh, free_qtd);
40501 +
40502 +cleanup:
40503 +       /*
40504 +        * Release the host channel for use by other transfers. The cleanup
40505 +        * function clears the channel interrupt enables and conditions, so
40506 +        * there's no need to clear the Channel Halted interrupt separately.
40507 +        */
40508 +       dwc_otg_hc_cleanup(hcd->core_if, hc);
40509 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
40510 +
40511 +       if (!microframe_schedule) {
40512 +               switch (hc->ep_type) {
40513 +               case DWC_OTG_EP_TYPE_CONTROL:
40514 +               case DWC_OTG_EP_TYPE_BULK:
40515 +                       hcd->non_periodic_channels--;
40516 +                       break;
40517 +
40518 +               default:
40519 +                       /*
40520 +                        * Don't release reservations for periodic channels here.
40521 +                        * That's done when a periodic transfer is descheduled (i.e.
40522 +                        * when the QH is removed from the periodic schedule).
40523 +                        */
40524 +                       break;
40525 +               }
40526 +       } else {
40527 +
40528 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
40529 +               hcd->available_host_channels++;
40530 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
40531 +       }
40532 +
40533 +       /* Try to queue more transfers now that there's a free channel. */
40534 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
40535 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40536 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
40537 +       }
40538 +       DWC_SPINLOCK_FREE(channel_lock);
40539 +}
40540 +
40541 +/**
40542 + * Halts a host channel. If the channel cannot be halted immediately because
40543 + * the request queue is full, this function ensures that the FIFO empty
40544 + * interrupt for the appropriate queue is enabled so that the halt request can
40545 + * be queued when there is space in the request queue.
40546 + *
40547 + * This function may also be called in DMA mode. In that case, the channel is
40548 + * simply released since the core always halts the channel automatically in
40549 + * DMA mode.
40550 + */
40551 +static void halt_channel(dwc_otg_hcd_t * hcd,
40552 +                        dwc_hc_t * hc,
40553 +                        dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40554 +{
40555 +       if (hcd->core_if->dma_enable) {
40556 +               release_channel(hcd, hc, qtd, halt_status);
40557 +               return;
40558 +       }
40559 +
40560 +       /* Slave mode processing... */
40561 +       dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
40562 +
40563 +       if (hc->halt_on_queue) {
40564 +               gintmsk_data_t gintmsk = {.d32 = 0 };
40565 +               dwc_otg_core_global_regs_t *global_regs;
40566 +               global_regs = hcd->core_if->core_global_regs;
40567 +
40568 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
40569 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
40570 +                       /*
40571 +                        * Make sure the Non-periodic Tx FIFO empty interrupt
40572 +                        * is enabled so that the non-periodic schedule will
40573 +                        * be processed.
40574 +                        */
40575 +                       gintmsk.b.nptxfempty = 1;
40576 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40577 +               } else {
40578 +                       /*
40579 +                        * Move the QH from the periodic queued schedule to
40580 +                        * the periodic assigned schedule. This allows the
40581 +                        * halt to be queued when the periodic schedule is
40582 +                        * processed.
40583 +                        */
40584 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
40585 +                                          &hc->qh->qh_list_entry);
40586 +
40587 +                       /*
40588 +                        * Make sure the Periodic Tx FIFO Empty interrupt is
40589 +                        * enabled so that the periodic schedule will be
40590 +                        * processed.
40591 +                        */
40592 +                       gintmsk.b.ptxfempty = 1;
40593 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40594 +               }
40595 +       }
40596 +}
40597 +
40598 +/**
40599 + * Performs common cleanup for non-periodic transfers after a Transfer
40600 + * Complete interrupt. This function should be called after any endpoint type
40601 + * specific handling is finished to release the host channel.
40602 + */
40603 +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
40604 +                                      dwc_hc_t * hc,
40605 +                                      dwc_otg_hc_regs_t * hc_regs,
40606 +                                      dwc_otg_qtd_t * qtd,
40607 +                                      dwc_otg_halt_status_e halt_status)
40608 +{
40609 +       hcint_data_t hcint;
40610 +
40611 +       qtd->error_count = 0;
40612 +
40613 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
40614 +       if (hcint.b.nyet) {
40615 +               /*
40616 +                * Got a NYET on the last transaction of the transfer. This
40617 +                * means that the endpoint should be in the PING state at the
40618 +                * beginning of the next transfer.
40619 +                */
40620 +               hc->qh->ping_state = 1;
40621 +               clear_hc_int(hc_regs, nyet);
40622 +       }
40623 +
40624 +       /*
40625 +        * Always halt and release the host channel to make it available for
40626 +        * more transfers. There may still be more phases for a control
40627 +        * transfer or more data packets for a bulk transfer at this point,
40628 +        * but the host channel is still halted. A channel will be reassigned
40629 +        * to the transfer when the non-periodic schedule is processed after
40630 +        * the channel is released. This allows transactions to be queued
40631 +        * properly via dwc_otg_hcd_queue_transactions, which also enables the
40632 +        * Tx FIFO Empty interrupt if necessary.
40633 +        */
40634 +       if (hc->ep_is_in) {
40635 +               /*
40636 +                * IN transfers in Slave mode require an explicit disable to
40637 +                * halt the channel. (In DMA mode, this call simply releases
40638 +                * the channel.)
40639 +                */
40640 +               halt_channel(hcd, hc, qtd, halt_status);
40641 +       } else {
40642 +               /*
40643 +                * The channel is automatically disabled by the core for OUT
40644 +                * transfers in Slave mode.
40645 +                */
40646 +               release_channel(hcd, hc, qtd, halt_status);
40647 +       }
40648 +}
40649 +
40650 +/**
40651 + * Performs common cleanup for periodic transfers after a Transfer Complete
40652 + * interrupt. This function should be called after any endpoint type specific
40653 + * handling is finished to release the host channel.
40654 + */
40655 +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
40656 +                                  dwc_hc_t * hc,
40657 +                                  dwc_otg_hc_regs_t * hc_regs,
40658 +                                  dwc_otg_qtd_t * qtd,
40659 +                                  dwc_otg_halt_status_e halt_status)
40660 +{
40661 +       hctsiz_data_t hctsiz;
40662 +       qtd->error_count = 0;
40663 +
40664 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40665 +       if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
40666 +               /* Core halts channel in these cases. */
40667 +               release_channel(hcd, hc, qtd, halt_status);
40668 +       } else {
40669 +               /* Flush any outstanding requests from the Tx queue. */
40670 +               halt_channel(hcd, hc, qtd, halt_status);
40671 +       }
40672 +}
40673 +
40674 +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
40675 +                                            dwc_hc_t * hc,
40676 +                                            dwc_otg_hc_regs_t * hc_regs,
40677 +                                            dwc_otg_qtd_t * qtd)
40678 +{
40679 +       uint32_t len;
40680 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40681 +       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
40682 +
40683 +       len = get_actual_xfer_length(hc, hc_regs, qtd,
40684 +                                    DWC_OTG_HC_XFER_COMPLETE, NULL);
40685 +
40686 +       if (!len) {
40687 +               qtd->complete_split = 0;
40688 +               qtd->isoc_split_offset = 0;
40689 +               return 0;
40690 +       }
40691 +       frame_desc->actual_length += len;
40692 +
40693 +       if (hc->align_buff && len)
40694 +               dwc_memcpy(qtd->urb->buf + frame_desc->offset +
40695 +                          qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
40696 +       qtd->isoc_split_offset += len;
40697 +
40698 +       if (frame_desc->length == frame_desc->actual_length) {
40699 +               frame_desc->status = 0;
40700 +               qtd->isoc_frame_index++;
40701 +               qtd->complete_split = 0;
40702 +               qtd->isoc_split_offset = 0;
40703 +       }
40704 +
40705 +       if (qtd->isoc_frame_index == qtd->urb->packet_count) {
40706 +               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
40707 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
40708 +       } else {
40709 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
40710 +       }
40711 +
40712 +       return 1;               /* Indicates that channel released */
40713 +}
40714 +
40715 +/**
40716 + * Handles a host channel Transfer Complete interrupt. This handler may be
40717 + * called in either DMA mode or Slave mode.
40718 + */
40719 +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
40720 +                                      dwc_hc_t * hc,
40721 +                                      dwc_otg_hc_regs_t * hc_regs,
40722 +                                      dwc_otg_qtd_t * qtd)
40723 +{
40724 +       int urb_xfer_done;
40725 +       dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
40726 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40727 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40728 +
40729 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40730 +                   "Transfer Complete--\n", hc->hc_num);
40731 +
40732 +       if (hcd->core_if->dma_desc_enable) {
40733 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
40734 +               if (pipe_type == UE_ISOCHRONOUS) {
40735 +                       /* Do not disable the interrupt, just clear it */
40736 +                       clear_hc_int(hc_regs, xfercomp);
40737 +                       return 1;
40738 +               }
40739 +               goto handle_xfercomp_done;
40740 +       }
40741 +
40742 +       /*
40743 +        * Handle xfer complete on CSPLIT.
40744 +        */
40745 +
40746 +       if (hc->qh->do_split) {
40747 +               if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
40748 +                   && hcd->core_if->dma_enable) {
40749 +                       if (qtd->complete_split
40750 +                           && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
40751 +                                                            qtd))
40752 +                               goto handle_xfercomp_done;
40753 +               } else {
40754 +                       qtd->complete_split = 0;
40755 +               }
40756 +       }
40757 +
40758 +       /* Update the QTD and URB states. */
40759 +       switch (pipe_type) {
40760 +       case UE_CONTROL:
40761 +               switch (qtd->control_phase) {
40762 +               case DWC_OTG_CONTROL_SETUP:
40763 +                       if (urb->length > 0) {
40764 +                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
40765 +                       } else {
40766 +                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
40767 +                       }
40768 +                       DWC_DEBUGPL(DBG_HCDV,
40769 +                                   "  Control setup transaction done\n");
40770 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40771 +                       break;
40772 +               case DWC_OTG_CONTROL_DATA:{
40773 +                               urb_xfer_done =
40774 +                                   update_urb_state_xfer_comp(hc, hc_regs, urb,
40775 +                                                              qtd);
40776 +                               if (urb_xfer_done) {
40777 +                                       qtd->control_phase =
40778 +                                           DWC_OTG_CONTROL_STATUS;
40779 +                                       DWC_DEBUGPL(DBG_HCDV,
40780 +                                                   "  Control data transfer done\n");
40781 +                               } else {
40782 +                                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40783 +                               }
40784 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40785 +                               break;
40786 +                       }
40787 +               case DWC_OTG_CONTROL_STATUS:
40788 +                       DWC_DEBUGPL(DBG_HCDV, "  Control transfer complete\n");
40789 +                       if (urb->status == -DWC_E_IN_PROGRESS) {
40790 +                               urb->status = 0;
40791 +                       }
40792 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40793 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40794 +                       break;
40795 +               }
40796 +
40797 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40798 +               break;
40799 +       case UE_BULK:
40800 +               DWC_DEBUGPL(DBG_HCDV, "  Bulk transfer complete\n");
40801 +               urb_xfer_done =
40802 +                   update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40803 +               if (urb_xfer_done) {
40804 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40805 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40806 +               } else {
40807 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40808 +               }
40809 +
40810 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40811 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40812 +               break;
40813 +       case UE_INTERRUPT:
40814 +               DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");
40815 +               urb_xfer_done =
40816 +                       update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40817 +
40818 +               /*
40819 +                * Interrupt URB is done on the first transfer complete
40820 +                * interrupt.
40821 +                */
40822 +               if (urb_xfer_done) {
40823 +                               hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40824 +                               halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40825 +               } else {
40826 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40827 +               }
40828 +
40829 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40830 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40831 +               break;
40832 +       case UE_ISOCHRONOUS:
40833 +               DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");
40834 +               if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
40835 +                       halt_status =
40836 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
40837 +                                                 DWC_OTG_HC_XFER_COMPLETE);
40838 +               }
40839 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40840 +               break;
40841 +       }
40842 +
40843 +handle_xfercomp_done:
40844 +       disable_hc_int(hc_regs, xfercompl);
40845 +
40846 +       return 1;
40847 +}
40848 +
40849 +/**
40850 + * Handles a host channel STALL interrupt. This handler may be called in
40851 + * either DMA mode or Slave mode.
40852 + */
40853 +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
40854 +                                   dwc_hc_t * hc,
40855 +                                   dwc_otg_hc_regs_t * hc_regs,
40856 +                                   dwc_otg_qtd_t * qtd)
40857 +{
40858 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40859 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40860 +
40861 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
40862 +                   "STALL Received--\n", hc->hc_num);
40863 +
40864 +       if (hcd->core_if->dma_desc_enable) {
40865 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
40866 +               goto handle_stall_done;
40867 +       }
40868 +
40869 +       if (pipe_type == UE_CONTROL) {
40870 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
40871 +       }
40872 +
40873 +       if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
40874 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
40875 +               /*
40876 +                * USB protocol requires resetting the data toggle for bulk
40877 +                * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
40878 +                * setup command is issued to the endpoint. Anticipate the
40879 +                * CLEAR_FEATURE command since a STALL has occurred and reset
40880 +                * the data toggle now.
40881 +                */
40882 +               hc->qh->data_toggle = 0;
40883 +       }
40884 +
40885 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
40886 +
40887 +handle_stall_done:
40888 +       disable_hc_int(hc_regs, stall);
40889 +
40890 +       return 1;
40891 +}
40892 +
40893 +/*
40894 + * Updates the state of the URB when a transfer has been stopped due to an
40895 + * abnormal condition before the transfer completes. Modifies the
40896 + * actual_length field of the URB to reflect the number of bytes that have
40897 + * actually been transferred via the host channel.
40898 + */
40899 +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
40900 +                                      dwc_otg_hc_regs_t * hc_regs,
40901 +                                      dwc_otg_hcd_urb_t * urb,
40902 +                                      dwc_otg_qtd_t * qtd,
40903 +                                      dwc_otg_halt_status_e halt_status)
40904 +{
40905 +       uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
40906 +                                                           halt_status, NULL);
40907 +       /* non DWORD-aligned buffer case handling. */
40908 +       if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
40909 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40910 +                          bytes_transferred);
40911 +       }
40912 +
40913 +       urb->actual_length += bytes_transferred;
40914 +
40915 +#ifdef DEBUG
40916 +       {
40917 +               hctsiz_data_t hctsiz;
40918 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40919 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40920 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
40921 +                           hc->hc_num);
40922 +               DWC_DEBUGPL(DBG_HCDV, "  hc->start_pkt_count %d\n",
40923 +                           hc->start_pkt_count);
40924 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
40925 +               DWC_DEBUGPL(DBG_HCDV, "  hc->max_packet %d\n", hc->max_packet);
40926 +               DWC_DEBUGPL(DBG_HCDV, "  bytes_transferred %d\n",
40927 +                           bytes_transferred);
40928 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
40929 +                           urb->actual_length);
40930 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
40931 +                           urb->length);
40932 +       }
40933 +#endif
40934 +}
40935 +
40936 +/**
40937 + * Handles a host channel NAK interrupt. This handler may be called in either
40938 + * DMA mode or Slave mode.
40939 + */
40940 +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
40941 +                                 dwc_hc_t * hc,
40942 +                                 dwc_otg_hc_regs_t * hc_regs,
40943 +                                 dwc_otg_qtd_t * qtd)
40944 +{
40945 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40946 +                   "NAK Received--\n", hc->hc_num);
40947 +
40948 +       /*
40949 +        * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
40950 +        * interrupt.  Re-start the SSPLIT transfer.
40951 +        */
40952 +       if (hc->do_split) {
40953 +               if (hc->complete_split) {
40954 +                       qtd->error_count = 0;
40955 +               }
40956 +               qtd->complete_split = 0;
40957 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
40958 +               goto handle_nak_done;
40959 +       }
40960 +
40961 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
40962 +       case UE_CONTROL:
40963 +       case UE_BULK:
40964 +               if (hcd->core_if->dma_enable && hc->ep_is_in) {
40965 +                       /*
40966 +                        * NAK interrupts are enabled on bulk/control IN
40967 +                        * transfers in DMA mode for the sole purpose of
40968 +                        * resetting the error count after a transaction error
40969 +                        * occurs. The core will continue transferring data.
40970 +                        */
40971 +                       qtd->error_count = 0;
40972 +                       goto handle_nak_done;
40973 +               }
40974 +
40975 +               /*
40976 +                * NAK interrupts normally occur during OUT transfers in DMA
40977 +                * or Slave mode. For IN transfers, more requests will be
40978 +                * queued as request queue space is available.
40979 +                */
40980 +               qtd->error_count = 0;
40981 +
40982 +               if (!hc->qh->ping_state) {
40983 +                       update_urb_state_xfer_intr(hc, hc_regs,
40984 +                                                  qtd->urb, qtd,
40985 +                                                  DWC_OTG_HC_XFER_NAK);
40986 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40987 +
40988 +                       if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
40989 +                               hc->qh->ping_state = 1;
40990 +               }
40991 +
40992 +               /*
40993 +                * Halt the channel so the transfer can be re-started from
40994 +                * the appropriate point or the PING protocol will
40995 +                * start/continue.
40996 +                */
40997 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
40998 +               break;
40999 +       case UE_INTERRUPT:
41000 +               qtd->error_count = 0;
41001 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41002 +               break;
41003 +       case UE_ISOCHRONOUS:
41004 +               /* Should never get called for isochronous transfers. */
41005 +               DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
41006 +               break;
41007 +       }
41008 +
41009 +handle_nak_done:
41010 +       disable_hc_int(hc_regs, nak);
41011 +
41012 +       return 1;
41013 +}
41014 +
41015 +/**
41016 + * Handles a host channel ACK interrupt. This interrupt is enabled when
41017 + * performing the PING protocol in Slave mode, when errors occur during
41018 + * either Slave mode or DMA mode, and during Start Split transactions.
41019 + */
41020 +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
41021 +                                 dwc_hc_t * hc,
41022 +                                 dwc_otg_hc_regs_t * hc_regs,
41023 +                                 dwc_otg_qtd_t * qtd)
41024 +{
41025 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41026 +                   "ACK Received--\n", hc->hc_num);
41027 +
41028 +       if (hc->do_split) {
41029 +               /*
41030 +                * Handle ACK on SSPLIT.
41031 +                * ACK should not occur in CSPLIT.
41032 +                */
41033 +               if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
41034 +                       qtd->ssplit_out_xfer_count = hc->xfer_len;
41035 +               }
41036 +               if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
41037 +                       /* Don't need complete for isochronous out transfers. */
41038 +                       qtd->complete_split = 1;
41039 +               }
41040 +
41041 +               /* ISOC OUT */
41042 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41043 +                       switch (hc->xact_pos) {
41044 +                       case DWC_HCSPLIT_XACTPOS_ALL:
41045 +                               break;
41046 +                       case DWC_HCSPLIT_XACTPOS_END:
41047 +                               qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
41048 +                               qtd->isoc_split_offset = 0;
41049 +                               break;
41050 +                       case DWC_HCSPLIT_XACTPOS_BEGIN:
41051 +                       case DWC_HCSPLIT_XACTPOS_MID:
41052 +                               /*
41053 +                                * For BEGIN or MID, calculate the length for
41054 +                                * the next microframe to determine the correct
41055 +                                * SSPLIT token, either MID or END.
41056 +                                */
41057 +                               {
41058 +                                       struct dwc_otg_hcd_iso_packet_desc
41059 +                                       *frame_desc;
41060 +
41061 +                                       frame_desc =
41062 +                                           &qtd->urb->
41063 +                                           iso_descs[qtd->isoc_frame_index];
41064 +                                       qtd->isoc_split_offset += 188;
41065 +
41066 +                                       if ((frame_desc->length -
41067 +                                            qtd->isoc_split_offset) <= 188) {
41068 +                                               qtd->isoc_split_pos =
41069 +                                                   DWC_HCSPLIT_XACTPOS_END;
41070 +                                       } else {
41071 +                                               qtd->isoc_split_pos =
41072 +                                                   DWC_HCSPLIT_XACTPOS_MID;
41073 +                                       }
41074 +
41075 +                               }
41076 +                               break;
41077 +                       }
41078 +               } else {
41079 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41080 +               }
41081 +       } else {
41082 +               qtd->error_count = 0;
41083 +
41084 +               if (hc->qh->ping_state) {
41085 +                       hc->qh->ping_state = 0;
41086 +                       /*
41087 +                        * Halt the channel so the transfer can be re-started
41088 +                        * from the appropriate point. This only happens in
41089 +                        * Slave mode. In DMA mode, the ping_state is cleared
41090 +                        * when the transfer is started because the core
41091 +                        * automatically executes the PING, then the transfer.
41092 +                        */
41093 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41094 +               }
41095 +       }
41096 +
41097 +       /*
41098 +        * If the ACK occurred when _not_ in the PING state, let the channel
41099 +        * continue transferring data after clearing the error count.
41100 +        */
41101 +
41102 +       disable_hc_int(hc_regs, ack);
41103 +
41104 +       return 1;
41105 +}
41106 +
41107 +/**
41108 + * Handles a host channel NYET interrupt. This interrupt should only occur on
41109 + * Bulk and Control OUT endpoints and for complete split transactions. If a
41110 + * NYET occurs at the same time as a Transfer Complete interrupt, it is
41111 + * handled in the xfercomp interrupt handler, not here. This handler may be
41112 + * called in either DMA mode or Slave mode.
41113 + */
41114 +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
41115 +                                  dwc_hc_t * hc,
41116 +                                  dwc_otg_hc_regs_t * hc_regs,
41117 +                                  dwc_otg_qtd_t * qtd)
41118 +{
41119 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41120 +                   "NYET Received--\n", hc->hc_num);
41121 +
41122 +       /*
41123 +        * NYET on CSPLIT
41124 +        * re-do the CSPLIT immediately on non-periodic
41125 +        */
41126 +       if (hc->do_split && hc->complete_split) {
41127 +               if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
41128 +                   && hcd->core_if->dma_enable) {
41129 +                       qtd->complete_split = 0;
41130 +                       qtd->isoc_split_offset = 0;
41131 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
41132 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
41133 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
41134 +                       }
41135 +                       else
41136 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
41137 +                       goto handle_nyet_done;
41138 +               }
41139 +
41140 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41141 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41142 +                       int frnum = dwc_otg_hcd_get_frame_number(hcd);
41143 +
41144 +                       if (dwc_full_frame_num(frnum) !=
41145 +                           dwc_full_frame_num(hc->qh->sched_frame)) {
41146 +                               /*
41147 +                                * No longer in the same full speed frame.
41148 +                                * Treat this as a transaction error.
41149 +                                */
41150 +#if 0
41151 +                               /** @todo Fix system performance so this can
41152 +                                * be treated as an error. Right now complete
41153 +                                * splits cannot be scheduled precisely enough
41154 +                                * due to other system activity, so this error
41155 +                                * occurs regularly in Slave mode.
41156 +                                */
41157 +                               qtd->error_count++;
41158 +#endif
41159 +                               qtd->complete_split = 0;
41160 +                               halt_channel(hcd, hc, qtd,
41161 +                                            DWC_OTG_HC_XFER_XACT_ERR);
41162 +                               /** @todo add support for isoc release */
41163 +                               goto handle_nyet_done;
41164 +                       }
41165 +               }
41166 +
41167 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41168 +               goto handle_nyet_done;
41169 +       }
41170 +
41171 +       hc->qh->ping_state = 1;
41172 +       qtd->error_count = 0;
41173 +
41174 +       update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
41175 +                                  DWC_OTG_HC_XFER_NYET);
41176 +       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41177 +
41178 +       /*
41179 +        * Halt the channel and re-start the transfer so the PING
41180 +        * protocol will start.
41181 +        */
41182 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41183 +
41184 +handle_nyet_done:
41185 +       disable_hc_int(hc_regs, nyet);
41186 +       return 1;
41187 +}
41188 +
41189 +/**
41190 + * Handles a host channel babble interrupt. This handler may be called in
41191 + * either DMA mode or Slave mode.
41192 + */
41193 +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
41194 +                                    dwc_hc_t * hc,
41195 +                                    dwc_otg_hc_regs_t * hc_regs,
41196 +                                    dwc_otg_qtd_t * qtd)
41197 +{
41198 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41199 +                   "Babble Error--\n", hc->hc_num);
41200 +
41201 +       if (hcd->core_if->dma_desc_enable) {
41202 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41203 +                                              DWC_OTG_HC_XFER_BABBLE_ERR);
41204 +               goto handle_babble_done;
41205 +       }
41206 +
41207 +       if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
41208 +               hcd->fops->complete(hcd, qtd->urb->priv,
41209 +                                   qtd->urb, -DWC_E_OVERFLOW);
41210 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
41211 +       } else {
41212 +               dwc_otg_halt_status_e halt_status;
41213 +               halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41214 +                                                   DWC_OTG_HC_XFER_BABBLE_ERR);
41215 +               halt_channel(hcd, hc, qtd, halt_status);
41216 +       }
41217 +
41218 +handle_babble_done:
41219 +       disable_hc_int(hc_regs, bblerr);
41220 +       return 1;
41221 +}
41222 +
41223 +/**
41224 + * Handles a host channel AHB error interrupt. This handler is only called in
41225 + * DMA mode.
41226 + */
41227 +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
41228 +                                    dwc_hc_t * hc,
41229 +                                    dwc_otg_hc_regs_t * hc_regs,
41230 +                                    dwc_otg_qtd_t * qtd)
41231 +{
41232 +       hcchar_data_t hcchar;
41233 +       hcsplt_data_t hcsplt;
41234 +       hctsiz_data_t hctsiz;
41235 +       uint32_t hcdma;
41236 +       char *pipetype, *speed;
41237 +
41238 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
41239 +
41240 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41241 +                   "AHB Error--\n", hc->hc_num);
41242 +
41243 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41244 +       hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41245 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41246 +       hcdma = DWC_READ_REG32(&hc_regs->hcdma);
41247 +
41248 +       DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
41249 +       DWC_ERROR("  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
41250 +       DWC_ERROR("  hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
41251 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
41252 +       DWC_ERROR("  Device address: %d\n",
41253 +                 dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
41254 +       DWC_ERROR("  Endpoint: %d, %s\n",
41255 +                 dwc_otg_hcd_get_ep_num(&urb->pipe_info),
41256 +                 (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
41257 +
41258 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
41259 +       case UE_CONTROL:
41260 +               pipetype = "CONTROL";
41261 +               break;
41262 +       case UE_BULK:
41263 +               pipetype = "BULK";
41264 +               break;
41265 +       case UE_INTERRUPT:
41266 +               pipetype = "INTERRUPT";
41267 +               break;
41268 +       case UE_ISOCHRONOUS:
41269 +               pipetype = "ISOCHRONOUS";
41270 +               break;
41271 +       default:
41272 +               pipetype = "UNKNOWN";
41273 +               break;
41274 +       }
41275 +
41276 +       DWC_ERROR("  Endpoint type: %s\n", pipetype);
41277 +
41278 +       switch (hc->speed) {
41279 +       case DWC_OTG_EP_SPEED_HIGH:
41280 +               speed = "HIGH";
41281 +               break;
41282 +       case DWC_OTG_EP_SPEED_FULL:
41283 +               speed = "FULL";
41284 +               break;
41285 +       case DWC_OTG_EP_SPEED_LOW:
41286 +               speed = "LOW";
41287 +               break;
41288 +       default:
41289 +               speed = "UNKNOWN";
41290 +               break;
41291 +       };
41292 +
41293 +       DWC_ERROR("  Speed: %s\n", speed);
41294 +
41295 +       DWC_ERROR("  Max packet size: %d\n",
41296 +                 dwc_otg_hcd_get_mps(&urb->pipe_info));
41297 +       DWC_ERROR("  Data buffer length: %d\n", urb->length);
41298 +       DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",
41299 +                 urb->buf, (void *)urb->dma);
41300 +       DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",
41301 +                 urb->setup_packet, (void *)urb->setup_dma);
41302 +       DWC_ERROR("  Interval: %d\n", urb->interval);
41303 +
41304 +       /* Core haltes the channel for Descriptor DMA mode */
41305 +       if (hcd->core_if->dma_desc_enable) {
41306 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41307 +                                              DWC_OTG_HC_XFER_AHB_ERR);
41308 +               goto handle_ahberr_done;
41309 +       }
41310 +
41311 +       hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
41312 +
41313 +       /*
41314 +        * Force a channel halt. Don't call halt_channel because that won't
41315 +        * write to the HCCHARn register in DMA mode to force the halt.
41316 +        */
41317 +       dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
41318 +handle_ahberr_done:
41319 +       disable_hc_int(hc_regs, ahberr);
41320 +       return 1;
41321 +}
41322 +
41323 +/**
41324 + * Handles a host channel transaction error interrupt. This handler may be
41325 + * called in either DMA mode or Slave mode.
41326 + */
41327 +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
41328 +                                     dwc_hc_t * hc,
41329 +                                     dwc_otg_hc_regs_t * hc_regs,
41330 +                                     dwc_otg_qtd_t * qtd)
41331 +{
41332 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41333 +                   "Transaction Error--\n", hc->hc_num);
41334 +
41335 +       if (hcd->core_if->dma_desc_enable) {
41336 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41337 +                                              DWC_OTG_HC_XFER_XACT_ERR);
41338 +               goto handle_xacterr_done;
41339 +       }
41340 +
41341 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41342 +       case UE_CONTROL:
41343 +       case UE_BULK:
41344 +               qtd->error_count++;
41345 +               if (!hc->qh->ping_state) {
41346 +
41347 +                       update_urb_state_xfer_intr(hc, hc_regs,
41348 +                                                  qtd->urb, qtd,
41349 +                                                  DWC_OTG_HC_XFER_XACT_ERR);
41350 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41351 +                       if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
41352 +                               hc->qh->ping_state = 1;
41353 +                       }
41354 +               }
41355 +
41356 +               /*
41357 +                * Halt the channel so the transfer can be re-started from
41358 +                * the appropriate point or the PING protocol will start.
41359 +                */
41360 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41361 +               break;
41362 +       case UE_INTERRUPT:
41363 +               qtd->error_count++;
41364 +               if (hc->do_split && hc->complete_split) {
41365 +                       qtd->complete_split = 0;
41366 +               }
41367 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41368 +               break;
41369 +       case UE_ISOCHRONOUS:
41370 +               {
41371 +                       dwc_otg_halt_status_e halt_status;
41372 +                       halt_status =
41373 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41374 +                                                 DWC_OTG_HC_XFER_XACT_ERR);
41375 +
41376 +                       halt_channel(hcd, hc, qtd, halt_status);
41377 +               }
41378 +               break;
41379 +       }
41380 +handle_xacterr_done:
41381 +       disable_hc_int(hc_regs, xacterr);
41382 +
41383 +       return 1;
41384 +}
41385 +
41386 +/**
41387 + * Handles a host channel frame overrun interrupt. This handler may be called
41388 + * in either DMA mode or Slave mode.
41389 + */
41390 +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
41391 +                                      dwc_hc_t * hc,
41392 +                                      dwc_otg_hc_regs_t * hc_regs,
41393 +                                      dwc_otg_qtd_t * qtd)
41394 +{
41395 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41396 +                   "Frame Overrun--\n", hc->hc_num);
41397 +
41398 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41399 +       case UE_CONTROL:
41400 +       case UE_BULK:
41401 +               break;
41402 +       case UE_INTERRUPT:
41403 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
41404 +               break;
41405 +       case UE_ISOCHRONOUS:
41406 +               {
41407 +                       dwc_otg_halt_status_e halt_status;
41408 +                       halt_status =
41409 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41410 +                                                 DWC_OTG_HC_XFER_FRAME_OVERRUN);
41411 +
41412 +                       halt_channel(hcd, hc, qtd, halt_status);
41413 +               }
41414 +               break;
41415 +       }
41416 +
41417 +       disable_hc_int(hc_regs, frmovrun);
41418 +
41419 +       return 1;
41420 +}
41421 +
41422 +/**
41423 + * Handles a host channel data toggle error interrupt. This handler may be
41424 + * called in either DMA mode or Slave mode.
41425 + */
41426 +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
41427 +                                        dwc_hc_t * hc,
41428 +                                        dwc_otg_hc_regs_t * hc_regs,
41429 +                                        dwc_otg_qtd_t * qtd)
41430 +{
41431 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41432 +                   "Data Toggle Error--\n", hc->hc_num);
41433 +
41434 +       if (hc->ep_is_in) {
41435 +               qtd->error_count = 0;
41436 +       } else {
41437 +               DWC_ERROR("Data Toggle Error on OUT transfer,"
41438 +                         "channel %d\n", hc->hc_num);
41439 +       }
41440 +
41441 +       disable_hc_int(hc_regs, datatglerr);
41442 +
41443 +       return 1;
41444 +}
41445 +
41446 +#ifdef DEBUG
41447 +/**
41448 + * This function is for debug only. It checks that a valid halt status is set
41449 + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
41450 + * taken and a warning is issued.
41451 + * @return 1 if halt status is ok, 0 otherwise.
41452 + */
41453 +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
41454 +                                dwc_hc_t * hc,
41455 +                                dwc_otg_hc_regs_t * hc_regs,
41456 +                                dwc_otg_qtd_t * qtd)
41457 +{
41458 +       hcchar_data_t hcchar;
41459 +       hctsiz_data_t hctsiz;
41460 +       hcint_data_t hcint;
41461 +       hcintmsk_data_t hcintmsk;
41462 +       hcsplt_data_t hcsplt;
41463 +
41464 +       if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
41465 +               /*
41466 +                * This code is here only as a check. This condition should
41467 +                * never happen. Ignore the halt if it does occur.
41468 +                */
41469 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41470 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41471 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41472 +               hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41473 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41474 +               DWC_WARN
41475 +                   ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
41476 +                    "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
41477 +                    "hcint 0x%08x, hcintmsk 0x%08x, "
41478 +                    "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
41479 +                    hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
41480 +                    hcintmsk.d32, hcsplt.d32, qtd->complete_split);
41481 +
41482 +               DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
41483 +                        __func__, hc->hc_num);
41484 +               DWC_WARN("\n");
41485 +               clear_hc_int(hc_regs, chhltd);
41486 +               return 0;
41487 +       }
41488 +
41489 +       /*
41490 +        * This code is here only as a check. hcchar.chdis should
41491 +        * never be set when the halt interrupt occurs. Halt the
41492 +        * channel again if it does occur.
41493 +        */
41494 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41495 +       if (hcchar.b.chdis) {
41496 +               DWC_WARN("%s: hcchar.chdis set unexpectedly, "
41497 +                        "hcchar 0x%08x, trying to halt again\n",
41498 +                        __func__, hcchar.d32);
41499 +               clear_hc_int(hc_regs, chhltd);
41500 +               hc->halt_pending = 0;
41501 +               halt_channel(hcd, hc, qtd, hc->halt_status);
41502 +               return 0;
41503 +       }
41504 +
41505 +       return 1;
41506 +}
41507 +#endif
41508 +
41509 +/**
41510 + * Handles a host Channel Halted interrupt in DMA mode. This handler
41511 + * determines the reason the channel halted and proceeds accordingly.
41512 + */
41513 +static void handle_hc_chhltd_intr_dma(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 +       hcint_data_t hcint;
41519 +       hcintmsk_data_t hcintmsk;
41520 +       int out_nak_enh = 0;
41521 +
41522 +       /* For core with OUT NAK enhancement, the flow for high-
41523 +        * speed CONTROL/BULK OUT is handled a little differently.
41524 +        */
41525 +       if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
41526 +               if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
41527 +                   (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
41528 +                    hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
41529 +                       out_nak_enh = 1;
41530 +               }
41531 +       }
41532 +
41533 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
41534 +           (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
41535 +            && !hcd->core_if->dma_desc_enable)) {
41536 +               /*
41537 +                * Just release the channel. A dequeue can happen on a
41538 +                * transfer timeout. In the case of an AHB Error, the channel
41539 +                * was forced to halt because there's no way to gracefully
41540 +                * recover.
41541 +                */
41542 +               if (hcd->core_if->dma_desc_enable)
41543 +                       dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41544 +                                                      hc->halt_status);
41545 +               else
41546 +                       release_channel(hcd, hc, qtd, hc->halt_status);
41547 +               return;
41548 +       }
41549 +
41550 +       /* Read the HCINTn register to determine the cause for the halt. */
41551 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41552 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41553 +
41554 +       if (hcint.b.xfercomp) {
41555 +               /** @todo This is here because of a possible hardware bug.  Spec
41556 +                * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
41557 +                * interrupt w/ACK bit set should occur, but I only see the
41558 +                * XFERCOMP bit, even with it masked out.  This is a workaround
41559 +                * for that behavior.  Should fix this when hardware is fixed.
41560 +                */
41561 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41562 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41563 +               }
41564 +               handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
41565 +       } else if (hcint.b.stall) {
41566 +               handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
41567 +       } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
41568 +               if (out_nak_enh) {
41569 +                       if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
41570 +                               DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
41571 +                               qtd->error_count = 0;
41572 +                       } else {
41573 +                               DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
41574 +                       }
41575 +               }
41576 +
41577 +               /*
41578 +                * Must handle xacterr before nak or ack. Could get a xacterr
41579 +                * at the same time as either of these on a BULK/CONTROL OUT
41580 +                * that started with a PING. The xacterr takes precedence.
41581 +                */
41582 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41583 +       } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
41584 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41585 +       } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
41586 +               handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
41587 +       } else if (hcint.b.bblerr) {
41588 +               handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
41589 +       } else if (hcint.b.frmovrun) {
41590 +               handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
41591 +       } else if (!out_nak_enh) {
41592 +               if (hcint.b.nyet) {
41593 +                       /*
41594 +                        * Must handle nyet before nak or ack. Could get a nyet at the
41595 +                        * same time as either of those on a BULK/CONTROL OUT that
41596 +                        * started with a PING. The nyet takes precedence.
41597 +                        */
41598 +                       handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
41599 +               } else if (hcint.b.nak && !hcintmsk.b.nak) {
41600 +                       /*
41601 +                        * If nak is not masked, it's because a non-split IN transfer
41602 +                        * is in an error state. In that case, the nak is handled by
41603 +                        * the nak interrupt handler, not here. Handle nak here for
41604 +                        * BULK/CONTROL OUT transfers, which halt on a NAK to allow
41605 +                        * rewinding the buffer pointer.
41606 +                        */
41607 +                       handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
41608 +               } else if (hcint.b.ack && !hcintmsk.b.ack) {
41609 +                       /*
41610 +                        * If ack is not masked, it's because a non-split IN transfer
41611 +                        * is in an error state. In that case, the ack is handled by
41612 +                        * the ack interrupt handler, not here. Handle ack here for
41613 +                        * split transfers. Start splits halt on ACK.
41614 +                        */
41615 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41616 +               } else {
41617 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41618 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41619 +                               /*
41620 +                                * A periodic transfer halted with no other channel
41621 +                                * interrupts set. Assume it was halted by the core
41622 +                                * because it could not be completed in its scheduled
41623 +                                * (micro)frame.
41624 +                                */
41625 +#ifdef DEBUG
41626 +                               DWC_PRINTF
41627 +                                   ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
41628 +                                    __func__, hc->hc_num);
41629 +#endif
41630 +                               halt_channel(hcd, hc, qtd,
41631 +                                            DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
41632 +                       } else {
41633 +                               DWC_ERROR
41634 +                                   ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
41635 +                                    "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
41636 +                                    __func__, hc->hc_num, hcint.d32,
41637 +                                    DWC_READ_REG32(&hcd->
41638 +                                                   core_if->core_global_regs->
41639 +                                                   gintsts));
41640 +                       }
41641 +
41642 +               }
41643 +       } else {
41644 +               DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
41645 +                          hcint.d32);
41646 +       }
41647 +}
41648 +
41649 +/**
41650 + * Handles a host channel Channel Halted interrupt.
41651 + *
41652 + * In slave mode, this handler is called only when the driver specifically
41653 + * requests a halt. This occurs during handling other host channel interrupts
41654 + * (e.g. nak, xacterr, stall, nyet, etc.).
41655 + *
41656 + * In DMA mode, this is the interrupt that occurs when the core has finished
41657 + * processing a transfer on a channel. Other host channel interrupts (except
41658 + * ahberr) are disabled in DMA mode.
41659 + */
41660 +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
41661 +                                    dwc_hc_t * hc,
41662 +                                    dwc_otg_hc_regs_t * hc_regs,
41663 +                                    dwc_otg_qtd_t * qtd)
41664 +{
41665 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41666 +                   "Channel Halted--\n", hc->hc_num);
41667 +
41668 +       if (hcd->core_if->dma_enable) {
41669 +               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
41670 +       } else {
41671 +#ifdef DEBUG
41672 +               if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
41673 +                       return 1;
41674 +               }
41675 +#endif
41676 +               release_channel(hcd, hc, qtd, hc->halt_status);
41677 +       }
41678 +
41679 +       return 1;
41680 +}
41681 +
41682 +/** Handles interrupt for a specific Host Channel */
41683 +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
41684 +{
41685 +       int retval = 0;
41686 +       hcint_data_t hcint;
41687 +       hcintmsk_data_t hcintmsk;
41688 +       dwc_hc_t *hc;
41689 +       dwc_otg_hc_regs_t *hc_regs;
41690 +       dwc_otg_qtd_t *qtd;
41691 +
41692 +       DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
41693 +
41694 +       hc = dwc_otg_hcd->hc_ptr_array[num];
41695 +       hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
41696 +       qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
41697 +
41698 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41699 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41700 +       DWC_DEBUGPL(DBG_HCDV,
41701 +                   "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
41702 +                   hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
41703 +       hcint.d32 = hcint.d32 & hcintmsk.d32;
41704 +
41705 +       if (!dwc_otg_hcd->core_if->dma_enable) {
41706 +               if (hcint.b.chhltd && hcint.d32 != 0x2) {
41707 +                       hcint.b.chhltd = 0;
41708 +               }
41709 +       }
41710 +
41711 +       if (hcint.b.xfercomp) {
41712 +               retval |=
41713 +                   handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41714 +               /*
41715 +                * If NYET occurred at same time as Xfer Complete, the NYET is
41716 +                * handled by the Xfer Complete interrupt handler. Don't want
41717 +                * to call the NYET interrupt handler in this case.
41718 +                */
41719 +               hcint.b.nyet = 0;
41720 +       }
41721 +       if (hcint.b.chhltd) {
41722 +               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41723 +       }
41724 +       if (hcint.b.ahberr) {
41725 +               retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41726 +       }
41727 +       if (hcint.b.stall) {
41728 +               retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41729 +       }
41730 +       if (hcint.b.nak) {
41731 +               retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41732 +       }
41733 +       if (hcint.b.ack) {
41734 +               retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41735 +       }
41736 +       if (hcint.b.nyet) {
41737 +               retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41738 +       }
41739 +       if (hcint.b.xacterr) {
41740 +               retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41741 +       }
41742 +       if (hcint.b.bblerr) {
41743 +               retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41744 +       }
41745 +       if (hcint.b.frmovrun) {
41746 +               retval |=
41747 +                   handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41748 +       }
41749 +       if (hcint.b.datatglerr) {
41750 +               retval |=
41751 +                   handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41752 +       }
41753 +
41754 +       return retval;
41755 +}
41756 +
41757 +#endif /* DWC_DEVICE_ONLY */
41758 --- /dev/null
41759 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41760 @@ -0,0 +1,893 @@
41761 +/* ==========================================================================
41762 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
41763 + * $Revision: #20 $
41764 + * $Date: 2011/10/26 $
41765 + * $Change: 1872981 $
41766 + *
41767 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
41768 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
41769 + * otherwise expressly agreed to in writing between Synopsys and you.
41770 + *
41771 + * The Software IS NOT an item of Licensed Software or Licensed Product under
41772 + * any End User Software License Agreement or Agreement for Licensed Product
41773 + * with Synopsys or any supplement thereto. You are permitted to use and
41774 + * redistribute this Software in source and binary forms, with or without
41775 + * modification, provided that redistributions of source code must retain this
41776 + * notice. You may not view, use, disclose, copy or distribute this file or
41777 + * any information contained herein except pursuant to this license grant from
41778 + * Synopsys. If you do not agree with this notice, including the disclaimer
41779 + * below, then you are not authorized to use the Software.
41780 + *
41781 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
41782 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41783 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41784 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
41785 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41786 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41787 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41788 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41789 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41790 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41791 + * DAMAGE.
41792 + * ========================================================================== */
41793 +#ifndef DWC_DEVICE_ONLY
41794 +
41795 +/**
41796 + * @file
41797 + *
41798 + * This file contains the implementation of the HCD. In Linux, the HCD
41799 + * implements the hc_driver API.
41800 + */
41801 +#include <linux/kernel.h>
41802 +#include <linux/module.h>
41803 +#include <linux/moduleparam.h>
41804 +#include <linux/init.h>
41805 +#include <linux/device.h>
41806 +#include <linux/errno.h>
41807 +#include <linux/list.h>
41808 +#include <linux/interrupt.h>
41809 +#include <linux/string.h>
41810 +#include <linux/dma-mapping.h>
41811 +#include <linux/version.h>
41812 +#include <asm/io.h>
41813 +#include <linux/usb.h>
41814 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
41815 +#include <../drivers/usb/core/hcd.h>
41816 +#else
41817 +#include <linux/usb/hcd.h>
41818 +#endif
41819 +
41820 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
41821 +#define USB_URB_EP_LINKING 1
41822 +#else
41823 +#define USB_URB_EP_LINKING 0
41824 +#endif
41825 +
41826 +#include "dwc_otg_hcd_if.h"
41827 +#include "dwc_otg_dbg.h"
41828 +#include "dwc_otg_driver.h"
41829 +#include "dwc_otg_hcd.h"
41830 +/**
41831 + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
41832 + * qualified with its direction (possible 32 endpoints per device).
41833 + */
41834 +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
41835 +                                                    ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
41836 +
41837 +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
41838 +
41839 +/** @name Linux HC Driver API Functions */
41840 +/** @{ */
41841 +/* manage i/o requests, device state */
41842 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
41843 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41844 +                      struct usb_host_endpoint *ep,
41845 +#endif
41846 +                      struct urb *urb, gfp_t mem_flags);
41847 +
41848 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
41849 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41850 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
41851 +#endif
41852 +#else /* kernels at or post 2.6.30 */
41853 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,
41854 +                               struct urb *urb, int status);
41855 +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
41856 +
41857 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
41858 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
41859 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
41860 +#endif
41861 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
41862 +extern int hcd_start(struct usb_hcd *hcd);
41863 +extern void hcd_stop(struct usb_hcd *hcd);
41864 +static int get_frame_number(struct usb_hcd *hcd);
41865 +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
41866 +extern int hub_control(struct usb_hcd *hcd,
41867 +                      u16 typeReq,
41868 +                      u16 wValue, u16 wIndex, char *buf, u16 wLength);
41869 +
41870 +struct wrapper_priv_data {
41871 +       dwc_otg_hcd_t *dwc_otg_hcd;
41872 +};
41873 +
41874 +/** @} */
41875 +
41876 +static struct hc_driver dwc_otg_hc_driver = {
41877 +
41878 +       .description = dwc_otg_hcd_name,
41879 +       .product_desc = "DWC OTG Controller",
41880 +       .hcd_priv_size = sizeof(struct wrapper_priv_data),
41881 +
41882 +       .irq = dwc_otg_hcd_irq,
41883 +
41884 +       .flags = HCD_MEMORY | HCD_USB2,
41885 +
41886 +       //.reset =
41887 +       .start = hcd_start,
41888 +       //.suspend =
41889 +       //.resume =
41890 +       .stop = hcd_stop,
41891 +
41892 +       .urb_enqueue = dwc_otg_urb_enqueue,
41893 +       .urb_dequeue = dwc_otg_urb_dequeue,
41894 +       .endpoint_disable = endpoint_disable,
41895 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
41896 +       .endpoint_reset = endpoint_reset,
41897 +#endif
41898 +       .get_frame_number = get_frame_number,
41899 +
41900 +       .hub_status_data = hub_status_data,
41901 +       .hub_control = hub_control,
41902 +       //.bus_suspend =
41903 +       //.bus_resume =
41904 +};
41905 +
41906 +/** Gets the dwc_otg_hcd from a struct usb_hcd */
41907 +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
41908 +{
41909 +       struct wrapper_priv_data *p;
41910 +       p = (struct wrapper_priv_data *)(hcd->hcd_priv);
41911 +       return p->dwc_otg_hcd;
41912 +}
41913 +
41914 +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
41915 +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
41916 +{
41917 +       return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
41918 +}
41919 +
41920 +/** Gets the usb_host_endpoint associated with an URB. */
41921 +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
41922 +{
41923 +       struct usb_device *dev = urb->dev;
41924 +       int ep_num = usb_pipeendpoint(urb->pipe);
41925 +
41926 +       if (usb_pipein(urb->pipe))
41927 +               return dev->ep_in[ep_num];
41928 +       else
41929 +               return dev->ep_out[ep_num];
41930 +}
41931 +
41932 +static int _disconnect(dwc_otg_hcd_t * hcd)
41933 +{
41934 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
41935 +
41936 +       usb_hcd->self.is_b_host = 0;
41937 +       return 0;
41938 +}
41939 +
41940 +static int _start(dwc_otg_hcd_t * hcd)
41941 +{
41942 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
41943 +
41944 +       usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
41945 +       hcd_start(usb_hcd);
41946 +
41947 +       return 0;
41948 +}
41949 +
41950 +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
41951 +                    uint32_t * port_addr)
41952 +{
41953 +   struct urb *urb = (struct urb *)urb_handle;
41954 +   struct usb_bus *bus;
41955 +#if 1 //GRAYG - temporary
41956 +   if (NULL == urb_handle)
41957 +      DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
41958 +   if (NULL == urb->dev)
41959 +      DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
41960 +   if (NULL == port_addr)
41961 +      DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
41962 +#endif
41963 +   if (urb->dev->tt) {
41964 +        if (NULL == urb->dev->tt->hub) {
41965 +                DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
41966 +                           __func__); //GRAYG
41967 +                //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
41968 +                *hub_addr = 0; //GRAYG
41969 +                // we probably shouldn't have a transaction translator if
41970 +                // there's no associated hub?
41971 +        } else {
41972 +               bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
41973 +               if (urb->dev->tt->hub == bus->root_hub)
41974 +                       *hub_addr = 0;
41975 +               else
41976 +                       *hub_addr = urb->dev->tt->hub->devnum;
41977 +       }
41978 +       *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
41979 +   } else {
41980 +        *hub_addr = 0;
41981 +       *port_addr = urb->dev->ttport;
41982 +   }
41983 +   return 0;
41984 +}
41985 +
41986 +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
41987 +{
41988 +       struct urb *urb = (struct urb *)urb_handle;
41989 +       return urb->dev->speed;
41990 +}
41991 +
41992 +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
41993 +{
41994 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
41995 +       return usb_hcd->self.b_hnp_enable;
41996 +}
41997 +
41998 +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
41999 +                                  struct urb *urb)
42000 +{
42001 +       hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
42002 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42003 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
42004 +       } else {
42005 +               hcd_to_bus(hcd)->bandwidth_int_reqs++;
42006 +       }
42007 +}
42008 +
42009 +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42010 +                              struct urb *urb)
42011 +{
42012 +       hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
42013 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42014 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
42015 +       } else {
42016 +               hcd_to_bus(hcd)->bandwidth_int_reqs--;
42017 +       }
42018 +}
42019 +
42020 +/**
42021 + * Sets the final status of an URB and returns it to the device driver. Any
42022 + * required cleanup of the URB is performed.
42023 + */
42024 +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
42025 +                    dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
42026 +{
42027 +       struct urb *urb = (struct urb *)urb_handle;
42028 +
42029 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42030 +               DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
42031 +                          __func__, urb, usb_pipedevice(urb->pipe),
42032 +                          usb_pipeendpoint(urb->pipe),
42033 +                          usb_pipein(urb->pipe) ? "IN" : "OUT", status);
42034 +               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42035 +                       int i;
42036 +                       for (i = 0; i < urb->number_of_packets; i++) {
42037 +                               DWC_PRINTF("  ISO Desc %d status: %d\n",
42038 +                                          i, urb->iso_frame_desc[i].status);
42039 +                       }
42040 +               }
42041 +       }
42042 +
42043 +       urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
42044 +       /* Convert status value. */
42045 +       switch (status) {
42046 +       case -DWC_E_PROTOCOL:
42047 +               status = -EPROTO;
42048 +               break;
42049 +       case -DWC_E_IN_PROGRESS:
42050 +               status = -EINPROGRESS;
42051 +               break;
42052 +       case -DWC_E_PIPE:
42053 +               status = -EPIPE;
42054 +               break;
42055 +       case -DWC_E_IO:
42056 +               status = -EIO;
42057 +               break;
42058 +       case -DWC_E_TIMEOUT:
42059 +               status = -ETIMEDOUT;
42060 +               break;
42061 +       case -DWC_E_OVERFLOW:
42062 +               status = -EOVERFLOW;
42063 +               break;
42064 +       default:
42065 +               if (status) {
42066 +                       DWC_PRINTF("Uknown urb status %d\n", status);
42067 +
42068 +               }
42069 +       }
42070 +
42071 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42072 +               int i;
42073 +
42074 +               urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
42075 +               for (i = 0; i < urb->number_of_packets; ++i) {
42076 +                       urb->iso_frame_desc[i].actual_length =
42077 +                           dwc_otg_hcd_urb_get_iso_desc_actual_length
42078 +                           (dwc_otg_urb, i);
42079 +                       urb->iso_frame_desc[i].status =
42080 +                           dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
42081 +               }
42082 +       }
42083 +
42084 +       urb->status = status;
42085 +       urb->hcpriv = NULL;
42086 +       if (!status) {
42087 +               if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
42088 +                   (urb->actual_length < urb->transfer_buffer_length)) {
42089 +                       urb->status = -EREMOTEIO;
42090 +               }
42091 +       }
42092 +
42093 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
42094 +           (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42095 +               struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
42096 +               if (ep) {
42097 +                       free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
42098 +                                          dwc_otg_hcd_get_ep_bandwidth(hcd,
42099 +                                                                       ep->hcpriv),
42100 +                                          urb);
42101 +               }
42102 +       }
42103 +
42104 +       DWC_FREE(dwc_otg_urb);
42105 +
42106 +#if USB_URB_EP_LINKING
42107 +        usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
42108 +#endif
42109 +       DWC_SPINUNLOCK(hcd->lock);
42110 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42111 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
42112 +#else
42113 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
42114 +#endif
42115 +       DWC_SPINLOCK(hcd->lock);
42116 +
42117 +       return 0;
42118 +}
42119 +
42120 +static struct dwc_otg_hcd_function_ops hcd_fops = {
42121 +       .start = _start,
42122 +       .disconnect = _disconnect,
42123 +       .hub_info = _hub_info,
42124 +       .speed = _speed,
42125 +       .complete = _complete,
42126 +       .get_b_hnp_enable = _get_b_hnp_enable,
42127 +};
42128 +
42129 +/**
42130 + * Initializes the HCD. This function allocates memory for and initializes the
42131 + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
42132 + * USB bus with the core and calls the hc_driver->start() function. It returns
42133 + * a negative error on failure.
42134 + */
42135 +int hcd_init(dwc_bus_dev_t *_dev)
42136 +{
42137 +       struct usb_hcd *hcd = NULL;
42138 +       dwc_otg_hcd_t *dwc_otg_hcd = NULL;
42139 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42140 +       int retval = 0;
42141 +        u64 dmamask;
42142 +
42143 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
42144 +
42145 +       /* Set device flags indicating whether the HCD supports DMA. */
42146 +       if (dwc_otg_is_dma_enable(otg_dev->core_if))
42147 +                dmamask = DMA_BIT_MASK(32);
42148 +        else
42149 +                dmamask = 0;
42150 +
42151 +#if    defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
42152 +        dma_set_mask(&_dev->dev, dmamask);
42153 +        dma_set_coherent_mask(&_dev->dev, dmamask);
42154 +#elif  defined(PCI_INTERFACE)
42155 +        pci_set_dma_mask(_dev, dmamask);
42156 +        pci_set_consistent_dma_mask(_dev, dmamask);
42157 +#endif
42158 +
42159 +       /*
42160 +        * Allocate memory for the base HCD plus the DWC OTG HCD.
42161 +        * Initialize the base HCD.
42162 +        */
42163 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
42164 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
42165 +#else
42166 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
42167 +       hcd->has_tt = 1;
42168 +//      hcd->uses_new_polling = 1;
42169 +//      hcd->poll_rh = 0;
42170 +#endif
42171 +       if (!hcd) {
42172 +               retval = -ENOMEM;
42173 +               goto error1;
42174 +       }
42175 +
42176 +       hcd->regs = otg_dev->os_dep.base;
42177 +
42178 +       /* Initialize the DWC OTG HCD. */
42179 +       dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
42180 +       if (!dwc_otg_hcd) {
42181 +               goto error2;
42182 +       }
42183 +       ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
42184 +           dwc_otg_hcd;
42185 +       otg_dev->hcd = dwc_otg_hcd;
42186 +
42187 +       if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
42188 +               goto error2;
42189 +       }
42190 +
42191 +       otg_dev->hcd->otg_dev = otg_dev;
42192 +       hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
42193 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
42194 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later
42195 +       hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
42196 +#endif
42197 +       /* Don't support SG list at this point */
42198 +       hcd->self.sg_tablesize = 0;
42199 +#endif
42200 +       /*
42201 +        * Finish generic HCD initialization and start the HCD. This function
42202 +        * allocates the DMA buffer pool, registers the USB bus, requests the
42203 +        * IRQ line, and calls hcd_start method.
42204 +        */
42205 +#ifdef PLATFORM_INTERFACE
42206 +        retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
42207 +#else
42208 +        retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
42209 +#endif
42210 +       if (retval < 0) {
42211 +               goto error2;
42212 +       }
42213 +
42214 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
42215 +       return 0;
42216 +
42217 +error2:
42218 +       usb_put_hcd(hcd);
42219 +error1:
42220 +       return retval;
42221 +}
42222 +
42223 +/**
42224 + * Removes the HCD.
42225 + * Frees memory and resources associated with the HCD and deregisters the bus.
42226 + */
42227 +void hcd_remove(dwc_bus_dev_t *_dev)
42228 +{
42229 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42230 +       dwc_otg_hcd_t *dwc_otg_hcd;
42231 +       struct usb_hcd *hcd;
42232 +
42233 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
42234 +
42235 +       if (!otg_dev) {
42236 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
42237 +               return;
42238 +       }
42239 +
42240 +       dwc_otg_hcd = otg_dev->hcd;
42241 +
42242 +       if (!dwc_otg_hcd) {
42243 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
42244 +               return;
42245 +       }
42246 +
42247 +       hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
42248 +
42249 +       if (!hcd) {
42250 +               DWC_DEBUGPL(DBG_ANY,
42251 +                           "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
42252 +                           __func__);
42253 +               return;
42254 +       }
42255 +       usb_remove_hcd(hcd);
42256 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
42257 +       dwc_otg_hcd_remove(dwc_otg_hcd);
42258 +       usb_put_hcd(hcd);
42259 +}
42260 +
42261 +/* =========================================================================
42262 + *  Linux HC Driver Functions
42263 + * ========================================================================= */
42264 +
42265 +/** Initializes the DWC_otg controller and its root hub and prepares it for host
42266 + * mode operation. Activates the root port. Returns 0 on success and a negative
42267 + * error code on failure. */
42268 +int hcd_start(struct usb_hcd *hcd)
42269 +{
42270 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42271 +       struct usb_bus *bus;
42272 +
42273 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
42274 +       bus = hcd_to_bus(hcd);
42275 +
42276 +       hcd->state = HC_STATE_RUNNING;
42277 +       if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
42278 +               return 0;
42279 +       }
42280 +
42281 +       /* Initialize and connect root hub if one is not already attached */
42282 +       if (bus->root_hub) {
42283 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
42284 +               /* Inform the HUB driver to resume. */
42285 +               usb_hcd_resume_root_hub(hcd);
42286 +       }
42287 +
42288 +       return 0;
42289 +}
42290 +
42291 +/**
42292 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
42293 + * stopped.
42294 + */
42295 +void hcd_stop(struct usb_hcd *hcd)
42296 +{
42297 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42298 +
42299 +       dwc_otg_hcd_stop(dwc_otg_hcd);
42300 +}
42301 +
42302 +/** Returns the current frame number. */
42303 +static int get_frame_number(struct usb_hcd *hcd)
42304 +{
42305 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42306 +
42307 +       return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
42308 +}
42309 +
42310 +#ifdef DEBUG
42311 +static void dump_urb_info(struct urb *urb, char *fn_name)
42312 +{
42313 +       DWC_PRINTF("%s, urb %p\n", fn_name, urb);
42314 +       DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));
42315 +       DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
42316 +                  (usb_pipein(urb->pipe) ? "IN" : "OUT"));
42317 +       DWC_PRINTF("  Endpoint type: %s\n", ( {
42318 +                                            char *pipetype;
42319 +                                            switch (usb_pipetype(urb->pipe)) {
42320 +case PIPE_CONTROL:
42321 +pipetype = "CONTROL"; break; case PIPE_BULK:
42322 +pipetype = "BULK"; break; case PIPE_INTERRUPT:
42323 +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
42324 +pipetype = "ISOCHRONOUS"; break; default:
42325 +                                            pipetype = "UNKNOWN"; break;};
42326 +                                            pipetype;}
42327 +                  )) ;
42328 +       DWC_PRINTF("  Speed: %s\n", ( {
42329 +                                    char *speed; switch (urb->dev->speed) {
42330 +case USB_SPEED_HIGH:
42331 +speed = "HIGH"; break; case USB_SPEED_FULL:
42332 +speed = "FULL"; break; case USB_SPEED_LOW:
42333 +speed = "LOW"; break; default:
42334 +                                    speed = "UNKNOWN"; break;};
42335 +                                    speed;}
42336 +                  )) ;
42337 +       DWC_PRINTF("  Max packet size: %d\n",
42338 +                  usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
42339 +       DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);
42340 +       DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",
42341 +                  urb->transfer_buffer, (void *)urb->transfer_dma);
42342 +       DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",
42343 +                  urb->setup_packet, (void *)urb->setup_dma);
42344 +       DWC_PRINTF("  Interval: %d\n", urb->interval);
42345 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42346 +               int i;
42347 +               for (i = 0; i < urb->number_of_packets; i++) {
42348 +                       DWC_PRINTF("  ISO Desc %d:\n", i);
42349 +                       DWC_PRINTF("    offset: %d, length %d\n",
42350 +                                  urb->iso_frame_desc[i].offset,
42351 +                                  urb->iso_frame_desc[i].length);
42352 +               }
42353 +       }
42354 +}
42355 +#endif
42356 +
42357 +/** Starts processing a USB transfer request specified by a USB Request Block
42358 + * (URB). mem_flags indicates the type of memory allocation to use while
42359 + * processing this URB. */
42360 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
42361 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42362 +                      struct usb_host_endpoint *ep,
42363 +#endif
42364 +                      struct urb *urb, gfp_t mem_flags)
42365 +{
42366 +       int retval = 0;
42367 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
42368 +       struct usb_host_endpoint *ep = urb->ep;
42369 +#endif
42370 +#if USB_URB_EP_LINKING
42371 +       dwc_irqflags_t irqflags;
42372 +#endif
42373 +        void **ref_ep_hcpriv = &ep->hcpriv;
42374 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42375 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
42376 +       int i;
42377 +       int alloc_bandwidth = 0;
42378 +       uint8_t ep_type = 0;
42379 +       uint32_t flags = 0;
42380 +       void *buf;
42381 +
42382 +#ifdef DEBUG
42383 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42384 +               dump_urb_info(urb, "dwc_otg_urb_enqueue");
42385 +       }
42386 +#endif
42387 +
42388 +       if (!urb->transfer_buffer && urb->transfer_buffer_length)
42389 +               return -EINVAL;
42390 +
42391 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
42392 +           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42393 +               if (!dwc_otg_hcd_is_bandwidth_allocated
42394 +                   (dwc_otg_hcd, ref_ep_hcpriv)) {
42395 +                       alloc_bandwidth = 1;
42396 +               }
42397 +       }
42398 +
42399 +       switch (usb_pipetype(urb->pipe)) {
42400 +       case PIPE_CONTROL:
42401 +               ep_type = USB_ENDPOINT_XFER_CONTROL;
42402 +               break;
42403 +       case PIPE_ISOCHRONOUS:
42404 +               ep_type = USB_ENDPOINT_XFER_ISOC;
42405 +               break;
42406 +       case PIPE_BULK:
42407 +               ep_type = USB_ENDPOINT_XFER_BULK;
42408 +               break;
42409 +       case PIPE_INTERRUPT:
42410 +               ep_type = USB_ENDPOINT_XFER_INT;
42411 +               break;
42412 +       default:
42413 +                DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));
42414 +       }
42415 +
42416 +        /* # of packets is often 0 - do we really need to call this then? */
42417 +       dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
42418 +                                           urb->number_of_packets,
42419 +                                           mem_flags == GFP_ATOMIC ? 1 : 0);
42420 +
42421 +       if(dwc_otg_urb == NULL)
42422 +               return -ENOMEM;
42423 +
42424 +        urb->hcpriv = dwc_otg_urb;
42425 +        if (!dwc_otg_urb && urb->number_of_packets)
42426 +                return -ENOMEM;
42427 +
42428 +       dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
42429 +                                    usb_pipeendpoint(urb->pipe), ep_type,
42430 +                                    usb_pipein(urb->pipe),
42431 +                                    usb_maxpacket(urb->dev, urb->pipe,
42432 +                                                  !(usb_pipein(urb->pipe))));
42433 +
42434 +       buf = urb->transfer_buffer;
42435 +       if (hcd->self.uses_dma) {
42436 +               /*
42437 +                * Calculate virtual address from physical address,
42438 +                * because some class driver may not fill transfer_buffer.
42439 +                * In Buffer DMA mode virual address is used,
42440 +                * when handling non DWORD aligned buffers.
42441 +                */
42442 +               //buf = phys_to_virt(urb->transfer_dma);
42443 +                // DMA addresses are bus addresses not physical addresses!
42444 +                buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
42445 +       }
42446 +
42447 +       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
42448 +               flags |= URB_GIVEBACK_ASAP;
42449 +       if (urb->transfer_flags & URB_ZERO_PACKET)
42450 +               flags |= URB_SEND_ZERO_PACKET;
42451 +
42452 +       dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
42453 +                                  urb->transfer_dma,
42454 +                                  urb->transfer_buffer_length,
42455 +                                  urb->setup_packet,
42456 +                                  urb->setup_dma, flags, urb->interval);
42457 +
42458 +       for (i = 0; i < urb->number_of_packets; ++i) {
42459 +               dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
42460 +                                                   urb->
42461 +                                                   iso_frame_desc[i].offset,
42462 +                                                   urb->
42463 +                                                   iso_frame_desc[i].length);
42464 +       }
42465 +
42466 +#if USB_URB_EP_LINKING
42467 +        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42468 +       retval = usb_hcd_link_urb_to_ep(hcd, urb);
42469 +        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42470 +       if (0 == retval)
42471 +#endif
42472 +        {
42473 +                retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
42474 +                                                 /*(dwc_otg_qh_t **)*/
42475 +                                                 ref_ep_hcpriv,
42476 +                                                 mem_flags == GFP_ATOMIC ? 1 : 0);
42477 +                if (0 == retval) {
42478 +                        if (alloc_bandwidth) {
42479 +                                allocate_bus_bandwidth(hcd,
42480 +                                        dwc_otg_hcd_get_ep_bandwidth(
42481 +                                                dwc_otg_hcd, *ref_ep_hcpriv),
42482 +                                                       urb);
42483 +                        }
42484 +                } else {
42485 +#if USB_URB_EP_LINKING
42486 +                       dwc_irqflags_t irqflags;
42487 +                        DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
42488 +                        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42489 +                        usb_hcd_unlink_urb_from_ep(hcd, urb);
42490 +                        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42491 +#endif
42492 +                        if (retval == -DWC_E_NO_DEVICE) {
42493 +                                retval = -ENODEV;
42494 +                        }
42495 +                }
42496 +        }
42497 +       return retval;
42498 +}
42499 +
42500 +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
42501 + * success.  */
42502 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42503 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
42504 +#else
42505 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
42506 +#endif
42507 +{
42508 +       dwc_irqflags_t flags;
42509 +       dwc_otg_hcd_t *dwc_otg_hcd;
42510 +        int rc;
42511 +
42512 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
42513 +
42514 +       dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42515 +
42516 +#ifdef DEBUG
42517 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42518 +               dump_urb_info(urb, "dwc_otg_urb_dequeue");
42519 +       }
42520 +#endif
42521 +
42522 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42523 +       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
42524 +       if (0 == rc) {
42525 +               if(urb->hcpriv != NULL) {
42526 +                       dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,
42527 +                                           (dwc_otg_hcd_urb_t *)urb->hcpriv);
42528 +
42529 +                       DWC_FREE(urb->hcpriv);
42530 +                       urb->hcpriv = NULL;
42531 +               }
42532 +        }
42533 +
42534 +        if (0 == rc) {
42535 +               /* Higher layer software sets URB status. */
42536 +#if USB_URB_EP_LINKING
42537 +                usb_hcd_unlink_urb_from_ep(hcd, urb);
42538 +#endif
42539 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42540 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42541 +                usb_hcd_giveback_urb(hcd, urb);
42542 +#else
42543 +                usb_hcd_giveback_urb(hcd, urb, status);
42544 +#endif
42545 +                if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42546 +                        DWC_PRINTF("Called usb_hcd_giveback_urb() \n");
42547 +                        DWC_PRINTF("  1urb->status = %d\n", urb->status);
42548 +                }
42549 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");
42550 +        } else {
42551 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42552 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",
42553 +                            rc);
42554 +        }
42555 +
42556 +       return rc;
42557 +}
42558 +
42559 +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
42560 + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
42561 + * must already be dequeued. */
42562 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42563 +{
42564 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42565 +
42566 +       DWC_DEBUGPL(DBG_HCD,
42567 +                   "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
42568 +                   "endpoint=%d\n", ep->desc.bEndpointAddress,
42569 +                   dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
42570 +       dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
42571 +       ep->hcpriv = NULL;
42572 +}
42573 +
42574 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42575 +/* Resets endpoint specific parameter values, in current version used to reset
42576 + * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
42577 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42578 +{
42579 +       dwc_irqflags_t flags;
42580 +       struct usb_device *udev = NULL;
42581 +       int epnum = usb_endpoint_num(&ep->desc);
42582 +       int is_out = usb_endpoint_dir_out(&ep->desc);
42583 +       int is_control = usb_endpoint_xfer_control(&ep->desc);
42584 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42585 +        struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);
42586 +
42587 +       if (dev)
42588 +               udev = to_usb_device(dev);
42589 +       else
42590 +               return;
42591 +
42592 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
42593 +
42594 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42595 +       usb_settoggle(udev, epnum, is_out, 0);
42596 +       if (is_control)
42597 +               usb_settoggle(udev, epnum, !is_out, 0);
42598 +
42599 +       if (ep->hcpriv) {
42600 +               dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
42601 +       }
42602 +       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42603 +}
42604 +#endif
42605 +
42606 +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
42607 + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
42608 + * interrupt.
42609 + *
42610 + * This function is called by the USB core when an interrupt occurs */
42611 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
42612 +{
42613 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42614 +       int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
42615 +       if (retval != 0) {
42616 +               S3C2410X_CLEAR_EINTPEND();
42617 +       }
42618 +       return IRQ_RETVAL(retval);
42619 +}
42620 +
42621 +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
42622 + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
42623 + * is the status change indicator for the single root port. Returns 1 if either
42624 + * change indicator is 1, otherwise returns 0. */
42625 +int hub_status_data(struct usb_hcd *hcd, char *buf)
42626 +{
42627 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42628 +
42629 +       buf[0] = 0;
42630 +       buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
42631 +
42632 +       return (buf[0] != 0);
42633 +}
42634 +
42635 +/** Handles hub class-specific requests. */
42636 +int hub_control(struct usb_hcd *hcd,
42637 +               u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
42638 +{
42639 +       int retval;
42640 +
42641 +       retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
42642 +                                        typeReq, wValue, wIndex, buf, wLength);
42643 +
42644 +       switch (retval) {
42645 +       case -DWC_E_INVALID:
42646 +               retval = -EINVAL;
42647 +               break;
42648 +       }
42649 +
42650 +       return retval;
42651 +}
42652 +
42653 +#endif /* DWC_DEVICE_ONLY */
42654 --- /dev/null
42655 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42656 @@ -0,0 +1,923 @@
42657 +/* ==========================================================================
42658 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
42659 + * $Revision: #44 $
42660 + * $Date: 2011/10/26 $
42661 + * $Change: 1873028 $
42662 + *
42663 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42664 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
42665 + * otherwise expressly agreed to in writing between Synopsys and you.
42666 + *
42667 + * The Software IS NOT an item of Licensed Software or Licensed Product under
42668 + * any End User Software License Agreement or Agreement for Licensed Product
42669 + * with Synopsys or any supplement thereto. You are permitted to use and
42670 + * redistribute this Software in source and binary forms, with or without
42671 + * modification, provided that redistributions of source code must retain this
42672 + * notice. You may not view, use, disclose, copy or distribute this file or
42673 + * any information contained herein except pursuant to this license grant from
42674 + * Synopsys. If you do not agree with this notice, including the disclaimer
42675 + * below, then you are not authorized to use the Software.
42676 + *
42677 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
42678 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42679 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42680 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
42681 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42682 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42683 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42684 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42685 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42686 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
42687 + * DAMAGE.
42688 + * ========================================================================== */
42689 +#ifndef DWC_DEVICE_ONLY
42690 +
42691 +/**
42692 + * @file
42693 + *
42694 + * This file contains the functions to manage Queue Heads and Queue
42695 + * Transfer Descriptors.
42696 + */
42697 +
42698 +#include "dwc_otg_hcd.h"
42699 +#include "dwc_otg_regs.h"
42700 +
42701 +extern bool microframe_schedule;
42702 +
42703 +/**
42704 + * Free each QTD in the QH's QTD-list then free the QH.  QH should already be
42705 + * removed from a list.  QTD list should already be empty if called from URB
42706 + * Dequeue.
42707 + *
42708 + * @param hcd HCD instance.
42709 + * @param qh The QH to free.
42710 + */
42711 +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
42712 +{
42713 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
42714 +       dwc_irqflags_t flags;
42715 +
42716 +       /* Free each QTD in the QTD list */
42717 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
42718 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
42719 +               DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
42720 +               dwc_otg_hcd_qtd_free(qtd);
42721 +       }
42722 +
42723 +       if (hcd->core_if->dma_desc_enable) {
42724 +               dwc_otg_hcd_qh_free_ddma(hcd, qh);
42725 +       } else if (qh->dw_align_buf) {
42726 +               uint32_t buf_size;
42727 +               if (qh->ep_type == UE_ISOCHRONOUS) {
42728 +                       buf_size = 4096;
42729 +               } else {
42730 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
42731 +               }
42732 +               DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
42733 +       }
42734 +
42735 +       DWC_FREE(qh);
42736 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
42737 +       return;
42738 +}
42739 +
42740 +#define BitStuffTime(bytecount)  ((8 * 7* bytecount) / 6)
42741 +#define HS_HOST_DELAY          5       /* nanoseconds */
42742 +#define FS_LS_HOST_DELAY       1000    /* nanoseconds */
42743 +#define HUB_LS_SETUP           333     /* nanoseconds */
42744 +#define NS_TO_US(ns)           ((ns + 500) / 1000)
42745 +                               /* convert & round nanoseconds to microseconds */
42746 +
42747 +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)
42748 +{
42749 +       unsigned long retval;
42750 +
42751 +       switch (speed) {
42752 +       case USB_SPEED_HIGH:
42753 +               if (is_isoc) {
42754 +                       retval =
42755 +                           ((38 * 8 * 2083) +
42756 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42757 +                           HS_HOST_DELAY;
42758 +               } else {
42759 +                       retval =
42760 +                           ((55 * 8 * 2083) +
42761 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42762 +                           HS_HOST_DELAY;
42763 +               }
42764 +               break;
42765 +       case USB_SPEED_FULL:
42766 +               if (is_isoc) {
42767 +                       retval =
42768 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42769 +                       if (is_in) {
42770 +                               retval = 7268 + FS_LS_HOST_DELAY + retval;
42771 +                       } else {
42772 +                               retval = 6265 + FS_LS_HOST_DELAY + retval;
42773 +                       }
42774 +               } else {
42775 +                       retval =
42776 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42777 +                       retval = 9107 + FS_LS_HOST_DELAY + retval;
42778 +               }
42779 +               break;
42780 +       case USB_SPEED_LOW:
42781 +               if (is_in) {
42782 +                       retval =
42783 +                           (67667 * (31 + 10 * BitStuffTime(bytecount))) /
42784 +                           1000;
42785 +                       retval =
42786 +                           64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42787 +                           retval;
42788 +               } else {
42789 +                       retval =
42790 +                           (66700 * (31 + 10 * BitStuffTime(bytecount))) /
42791 +                           1000;
42792 +                       retval =
42793 +                           64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42794 +                           retval;
42795 +               }
42796 +               break;
42797 +       default:
42798 +               DWC_WARN("Unknown device speed\n");
42799 +               retval = -1;
42800 +       }
42801 +
42802 +       return NS_TO_US(retval);
42803 +}
42804 +
42805 +/**
42806 + * Initializes a QH structure.
42807 + *
42808 + * @param hcd The HCD state structure for the DWC OTG controller.
42809 + * @param qh  The QH to init.
42810 + * @param urb Holds the information about the device/endpoint that we need
42811 + *           to initialize the QH.
42812 + */
42813 +#define SCHEDULE_SLOP 10
42814 +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
42815 +{
42816 +       char *speed, *type;
42817 +       int dev_speed;
42818 +       uint32_t hub_addr, hub_port;
42819 +
42820 +       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
42821 +
42822 +       /* Initialize QH */
42823 +       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
42824 +       qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
42825 +
42826 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
42827 +       qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
42828 +       DWC_CIRCLEQ_INIT(&qh->qtd_list);
42829 +       DWC_LIST_INIT(&qh->qh_list_entry);
42830 +       qh->channel = NULL;
42831 +
42832 +       /* FS/LS Enpoint on HS Hub
42833 +        * NOT virtual root hub */
42834 +       dev_speed = hcd->fops->speed(hcd, urb->priv);
42835 +
42836 +       hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
42837 +       qh->do_split = 0;
42838 +       if (microframe_schedule)
42839 +               qh->speed = dev_speed;
42840 +
42841 +
42842 +       if (((dev_speed == USB_SPEED_LOW) ||
42843 +            (dev_speed == USB_SPEED_FULL)) &&
42844 +           (hub_addr != 0 && hub_addr != 1)) {
42845 +               DWC_DEBUGPL(DBG_HCD,
42846 +                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
42847 +                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
42848 +                           hub_port);
42849 +               qh->do_split = 1;
42850 +       }
42851 +
42852 +       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
42853 +               /* Compute scheduling parameters once and save them. */
42854 +               hprt0_data_t hprt;
42855 +
42856 +               /** @todo Account for split transfers in the bus time. */
42857 +               int bytecount =
42858 +                   dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
42859 +
42860 +               qh->usecs =
42861 +                   calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
42862 +                                 qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),
42863 +                                 bytecount);
42864 +               /* Start in a slightly future (micro)frame. */
42865 +               qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
42866 +                                                   SCHEDULE_SLOP);
42867 +               qh->interval = urb->interval;
42868 +
42869 +#if 0
42870 +               /* Increase interrupt polling rate for debugging. */
42871 +               if (qh->ep_type == UE_INTERRUPT) {
42872 +                       qh->interval = 8;
42873 +               }
42874 +#endif
42875 +               hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
42876 +               if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
42877 +                   ((dev_speed == USB_SPEED_LOW) ||
42878 +                    (dev_speed == USB_SPEED_FULL))) {
42879 +                       qh->interval *= 8;
42880 +                       qh->sched_frame |= 0x7;
42881 +                       qh->start_split_frame = qh->sched_frame;
42882 +               }
42883 +
42884 +       }
42885 +
42886 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
42887 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);
42888 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
42889 +                   dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
42890 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
42891 +                   dwc_otg_hcd_get_ep_num(&urb->pipe_info),
42892 +                   dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
42893 +       switch (dev_speed) {
42894 +       case USB_SPEED_LOW:
42895 +               qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
42896 +               speed = "low";
42897 +               break;
42898 +       case USB_SPEED_FULL:
42899 +               qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
42900 +               speed = "full";
42901 +               break;
42902 +       case USB_SPEED_HIGH:
42903 +               qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
42904 +               speed = "high";
42905 +               break;
42906 +       default:
42907 +               speed = "?";
42908 +               break;
42909 +       }
42910 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);
42911 +
42912 +       switch (qh->ep_type) {
42913 +       case UE_ISOCHRONOUS:
42914 +               type = "isochronous";
42915 +               break;
42916 +       case UE_INTERRUPT:
42917 +               type = "interrupt";
42918 +               break;
42919 +       case UE_CONTROL:
42920 +               type = "control";
42921 +               break;
42922 +       case UE_BULK:
42923 +               type = "bulk";
42924 +               break;
42925 +       default:
42926 +               type = "?";
42927 +               break;
42928 +       }
42929 +
42930 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n", type);
42931 +
42932 +#ifdef DEBUG
42933 +       if (qh->ep_type == UE_INTERRUPT) {
42934 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
42935 +                           qh->usecs);
42936 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
42937 +                           qh->interval);
42938 +       }
42939 +#endif
42940 +
42941 +}
42942 +
42943 +/**
42944 + * This function allocates and initializes a QH.
42945 + *
42946 + * @param hcd The HCD state structure for the DWC OTG controller.
42947 + * @param urb Holds the information about the device/endpoint that we need
42948 + *           to initialize the QH.
42949 + * @param atomic_alloc Flag to do atomic allocation if needed
42950 + *
42951 + * @return Returns pointer to the newly allocated QH, or NULL on error. */
42952 +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
42953 +                                   dwc_otg_hcd_urb_t * urb, int atomic_alloc)
42954 +{
42955 +       dwc_otg_qh_t *qh;
42956 +
42957 +       /* Allocate memory */
42958 +       /** @todo add memflags argument */
42959 +       qh = dwc_otg_hcd_qh_alloc(atomic_alloc);
42960 +       if (qh == NULL) {
42961 +               DWC_ERROR("qh allocation failed");
42962 +               return NULL;
42963 +       }
42964 +
42965 +       qh_init(hcd, qh, urb);
42966 +
42967 +       if (hcd->core_if->dma_desc_enable
42968 +           && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
42969 +               dwc_otg_hcd_qh_free(hcd, qh);
42970 +               return NULL;
42971 +       }
42972 +
42973 +       return qh;
42974 +}
42975 +
42976 +/* microframe_schedule=0 start */
42977 +
42978 +/**
42979 + * Checks that a channel is available for a periodic transfer.
42980 + *
42981 + * @return 0 if successful, negative error code otherise.
42982 + */
42983 +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
42984 +{
42985 +       /*
42986 +        * Currently assuming that there is a dedicated host channnel for each
42987 +        * periodic transaction plus at least one host channel for
42988 +        * non-periodic transactions.
42989 +        */
42990 +       int status;
42991 +       int num_channels;
42992 +
42993 +       num_channels = hcd->core_if->core_params->host_channels;
42994 +       if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)
42995 +           && (hcd->periodic_channels < num_channels - 1)) {
42996 +               status = 0;
42997 +       } else {
42998 +               DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
42999 +                       __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels);    //NOTICE
43000 +               status = -DWC_E_NO_SPACE;
43001 +       }
43002 +
43003 +       return status;
43004 +}
43005 +
43006 +/**
43007 + * Checks that there is sufficient bandwidth for the specified QH in the
43008 + * periodic schedule. For simplicity, this calculation assumes that all the
43009 + * transfers in the periodic schedule may occur in the same (micro)frame.
43010 + *
43011 + * @param hcd The HCD state structure for the DWC OTG controller.
43012 + * @param qh QH containing periodic bandwidth required.
43013 + *
43014 + * @return 0 if successful, negative error code otherwise.
43015 + */
43016 +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43017 +{
43018 +       int status;
43019 +       int16_t max_claimed_usecs;
43020 +
43021 +       status = 0;
43022 +
43023 +       if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
43024 +               /*
43025 +                * High speed mode.
43026 +                * Max periodic usecs is 80% x 125 usec = 100 usec.
43027 +                */
43028 +
43029 +               max_claimed_usecs = 100 - qh->usecs;
43030 +       } else {
43031 +               /*
43032 +                * Full speed mode.
43033 +                * Max periodic usecs is 90% x 1000 usec = 900 usec.
43034 +                */
43035 +               max_claimed_usecs = 900 - qh->usecs;
43036 +       }
43037 +
43038 +       if (hcd->periodic_usecs > max_claimed_usecs) {
43039 +               DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs);        //NOTICE
43040 +               status = -DWC_E_NO_SPACE;
43041 +       }
43042 +
43043 +       return status;
43044 +}
43045 +
43046 +/* microframe_schedule=0 end */
43047 +
43048 +/**
43049 + * Microframe scheduler
43050 + * track the total use in hcd->frame_usecs
43051 + * keep each qh use in qh->frame_usecs
43052 + * when surrendering the qh then donate the time back
43053 + */
43054 +const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
43055 +
43056 +/*
43057 + * called from dwc_otg_hcd.c:dwc_otg_hcd_init
43058 + */
43059 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
43060 +{
43061 +       int i;
43062 +       for (i=0; i<8; i++) {
43063 +               _hcd->frame_usecs[i] = max_uframe_usecs[i];
43064 +       }
43065 +       return 0;
43066 +}
43067 +
43068 +static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43069 +{
43070 +       int i;
43071 +       unsigned short utime;
43072 +       int t_left;
43073 +       int ret;
43074 +       int done;
43075 +
43076 +       ret = -1;
43077 +       utime = _qh->usecs;
43078 +       t_left = utime;
43079 +       i = 0;
43080 +       done = 0;
43081 +       while (done == 0) {
43082 +               /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
43083 +               if (utime <= _hcd->frame_usecs[i]) {
43084 +                       _hcd->frame_usecs[i] -= utime;
43085 +                       _qh->frame_usecs[i] += utime;
43086 +                       t_left -= utime;
43087 +                       ret = i;
43088 +                       done = 1;
43089 +                       return ret;
43090 +               } else {
43091 +                       i++;
43092 +                       if (i == 8) {
43093 +                               done = 1;
43094 +                               ret = -1;
43095 +                       }
43096 +               }
43097 +       }
43098 +       return ret;
43099 + }
43100 +
43101 +/*
43102 + * use this for FS apps that can span multiple uframes
43103 +  */
43104 +static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43105 +{
43106 +       int i;
43107 +       int j;
43108 +       unsigned short utime;
43109 +       int t_left;
43110 +       int ret;
43111 +       int done;
43112 +       unsigned short xtime;
43113 +
43114 +       ret = -1;
43115 +       utime = _qh->usecs;
43116 +       t_left = utime;
43117 +       i = 0;
43118 +       done = 0;
43119 +loop:
43120 +       while (done == 0) {
43121 +               if(_hcd->frame_usecs[i] <= 0) {
43122 +                       i++;
43123 +                       if (i == 8) {
43124 +                               done = 1;
43125 +                               ret = -1;
43126 +                       }
43127 +                       goto loop;
43128 +               }
43129 +
43130 +               /*
43131 +                * we need n consecutive slots
43132 +                * so use j as a start slot j plus j+1 must be enough time (for now)
43133 +                */
43134 +               xtime= _hcd->frame_usecs[i];
43135 +               for (j = i+1 ; j < 8 ; j++ ) {
43136 +                       /*
43137 +                        * if we add this frame remaining time to xtime we may
43138 +                        * be OK, if not we need to test j for a complete frame
43139 +                        */
43140 +                       if ((xtime+_hcd->frame_usecs[j]) < utime) {
43141 +                               if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
43142 +                                       j = 8;
43143 +                                       ret = -1;
43144 +                                       continue;
43145 +                               }
43146 +                       }
43147 +                       if (xtime >= utime) {
43148 +                               ret = i;
43149 +                               j = 8;  /* stop loop with a good value ret */
43150 +                               continue;
43151 +                       }
43152 +                       /* add the frame time to x time */
43153 +                       xtime += _hcd->frame_usecs[j];
43154 +                      /* we must have a fully available next frame or break */
43155 +                      if ((xtime < utime)
43156 +                                      && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
43157 +                              ret = -1;
43158 +                              j = 8;  /* stop loop with a bad value ret */
43159 +                              continue;
43160 +                      }
43161 +               }
43162 +               if (ret >= 0) {
43163 +                       t_left = utime;
43164 +                       for (j = i; (t_left>0) && (j < 8); j++ ) {
43165 +                               t_left -= _hcd->frame_usecs[j];
43166 +                               if ( t_left <= 0 ) {
43167 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
43168 +                                       _hcd->frame_usecs[j]= -t_left;
43169 +                                       ret = i;
43170 +                                       done = 1;
43171 +                               } else {
43172 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j];
43173 +                                       _hcd->frame_usecs[j] = 0;
43174 +                               }
43175 +                       }
43176 +               } else {
43177 +                       i++;
43178 +                       if (i == 8) {
43179 +                               done = 1;
43180 +                               ret = -1;
43181 +                       }
43182 +               }
43183 +       }
43184 +       return ret;
43185 +}
43186 +
43187 +static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43188 +{
43189 +       int ret;
43190 +       ret = -1;
43191 +
43192 +       if (_qh->speed == USB_SPEED_HIGH) {
43193 +               /* if this is a hs transaction we need a full frame */
43194 +               ret = find_single_uframe(_hcd, _qh);
43195 +       } else {
43196 +               /* if this is a fs transaction we may need a sequence of frames */
43197 +               ret = find_multi_uframe(_hcd, _qh);
43198 +       }
43199 +       return ret;
43200 +}
43201 +
43202 +/**
43203 + * Checks that the max transfer size allowed in a host channel is large enough
43204 + * to handle the maximum data transfer in a single (micro)frame for a periodic
43205 + * transfer.
43206 + *
43207 + * @param hcd The HCD state structure for the DWC OTG controller.
43208 + * @param qh QH for a periodic endpoint.
43209 + *
43210 + * @return 0 if successful, negative error code otherwise.
43211 + */
43212 +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43213 +{
43214 +       int status;
43215 +       uint32_t max_xfer_size;
43216 +       uint32_t max_channel_xfer_size;
43217 +
43218 +       status = 0;
43219 +
43220 +       max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
43221 +       max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
43222 +
43223 +       if (max_xfer_size > max_channel_xfer_size) {
43224 +               DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
43225 +                               __func__, max_xfer_size, max_channel_xfer_size);        //NOTICE
43226 +               status = -DWC_E_NO_SPACE;
43227 +       }
43228 +
43229 +       return status;
43230 +}
43231 +
43232 +/**
43233 + * Schedules an interrupt or isochronous transfer in the periodic schedule.
43234 + *
43235 + * @param hcd The HCD state structure for the DWC OTG controller.
43236 + * @param qh QH for the periodic transfer. The QH should already contain the
43237 + * scheduling information.
43238 + *
43239 + * @return 0 if successful, negative error code otherwise.
43240 + */
43241 +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43242 +{
43243 +       int status = 0;
43244 +
43245 +       if (microframe_schedule) {
43246 +               int frame;
43247 +               status = find_uframe(hcd, qh);
43248 +               frame = -1;
43249 +               if (status == 0) {
43250 +                       frame = 7;
43251 +               } else {
43252 +                       if (status > 0 )
43253 +                               frame = status-1;
43254 +               }
43255 +
43256 +               /* Set the new frame up */
43257 +               if (frame > -1) {
43258 +                       qh->sched_frame &= ~0x7;
43259 +                       qh->sched_frame |= (frame & 7);
43260 +               }
43261 +
43262 +               if (status != -1)
43263 +                       status = 0;
43264 +       } else {
43265 +               status = periodic_channel_available(hcd);
43266 +               if (status) {
43267 +                       DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__);        //NOTICE
43268 +                       return status;
43269 +               }
43270 +
43271 +               status = check_periodic_bandwidth(hcd, qh);
43272 +       }
43273 +       if (status) {
43274 +               DWC_INFO("%s: Insufficient periodic bandwidth for "
43275 +                           "periodic transfer.\n", __func__);
43276 +               return status;
43277 +       }
43278 +       status = check_max_xfer_size(hcd, qh);
43279 +       if (status) {
43280 +               DWC_INFO("%s: Channel max transfer size too small "
43281 +                           "for periodic transfer.\n", __func__);
43282 +               return status;
43283 +       }
43284 +
43285 +       if (hcd->core_if->dma_desc_enable) {
43286 +               /* Don't rely on SOF and start in ready schedule */
43287 +               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
43288 +       }
43289 +       else {
43290 +       /* Always start in the inactive schedule. */
43291 +       DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
43292 +       }
43293 +
43294 +       if (!microframe_schedule) {
43295 +               /* Reserve the periodic channel. */
43296 +               hcd->periodic_channels++;
43297 +       }
43298 +
43299 +       /* Update claimed usecs per (micro)frame. */
43300 +       hcd->periodic_usecs += qh->usecs;
43301 +
43302 +       return status;
43303 +}
43304 +
43305 +/**
43306 + * This function adds a QH to either the non periodic or periodic schedule if
43307 + * it is not already in the schedule. If the QH is already in the schedule, no
43308 + * action is taken.
43309 + *
43310 + * @return 0 if successful, negative error code otherwise.
43311 + */
43312 +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43313 +{
43314 +       int status = 0;
43315 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43316 +
43317 +       if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43318 +               /* QH already in a schedule. */
43319 +               return status;
43320 +       }
43321 +
43322 +       /* Add the new QH to the appropriate schedule */
43323 +       if (dwc_qh_is_non_per(qh)) {
43324 +               /* Always start in the inactive schedule. */
43325 +               DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
43326 +                                    &qh->qh_list_entry);
43327 +       } else {
43328 +               status = schedule_periodic(hcd, qh);
43329 +               if ( !hcd->periodic_qh_count ) {
43330 +                       intr_mask.b.sofintr = 1;
43331 +                       DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43332 +                                                               intr_mask.d32, intr_mask.d32);
43333 +               }
43334 +               hcd->periodic_qh_count++;
43335 +       }
43336 +
43337 +       return status;
43338 +}
43339 +
43340 +/**
43341 + * Removes an interrupt or isochronous transfer from the periodic schedule.
43342 + *
43343 + * @param hcd The HCD state structure for the DWC OTG controller.
43344 + * @param qh QH for the periodic transfer.
43345 + */
43346 +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43347 +{
43348 +       int i;
43349 +       DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43350 +
43351 +       /* Update claimed usecs per (micro)frame. */
43352 +       hcd->periodic_usecs -= qh->usecs;
43353 +
43354 +       if (!microframe_schedule) {
43355 +               /* Release the periodic channel reservation. */
43356 +               hcd->periodic_channels--;
43357 +       } else {
43358 +               for (i = 0; i < 8; i++) {
43359 +                       hcd->frame_usecs[i] += qh->frame_usecs[i];
43360 +                       qh->frame_usecs[i] = 0;
43361 +               }
43362 +       }
43363 +}
43364 +
43365 +/**
43366 + * Removes a QH from either the non-periodic or periodic schedule.  Memory is
43367 + * not freed.
43368 + *
43369 + * @param hcd The HCD state structure.
43370 + * @param qh QH to remove from schedule. */
43371 +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43372 +{
43373 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43374 +
43375 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43376 +               /* QH is not in a schedule. */
43377 +               return;
43378 +       }
43379 +
43380 +       if (dwc_qh_is_non_per(qh)) {
43381 +               if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
43382 +                       hcd->non_periodic_qh_ptr =
43383 +                           hcd->non_periodic_qh_ptr->next;
43384 +               }
43385 +               DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43386 +       } else {
43387 +               deschedule_periodic(hcd, qh);
43388 +               hcd->periodic_qh_count--;
43389 +               if( !hcd->periodic_qh_count ) {
43390 +                       intr_mask.b.sofintr = 1;
43391 +                               DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43392 +                                                                       intr_mask.d32, 0);
43393 +               }
43394 +       }
43395 +}
43396 +
43397 +/**
43398 + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
43399 + * non-periodic schedule. The QH is added to the inactive non-periodic
43400 + * schedule if any QTDs are still attached to the QH.
43401 + *
43402 + * For periodic QHs, the QH is removed from the periodic queued schedule. If
43403 + * there are any QTDs still attached to the QH, the QH is added to either the
43404 + * periodic inactive schedule or the periodic ready schedule and its next
43405 + * scheduled frame is calculated. The QH is placed in the ready schedule if
43406 + * the scheduled frame has been reached already. Otherwise it's placed in the
43407 + * inactive schedule. If there are no QTDs attached to the QH, the QH is
43408 + * completely removed from the periodic schedule.
43409 + */
43410 +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
43411 +                              int sched_next_periodic_split)
43412 +{
43413 +       if (dwc_qh_is_non_per(qh)) {
43414 +               dwc_otg_hcd_qh_remove(hcd, qh);
43415 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43416 +                       /* Add back to inactive non-periodic schedule. */
43417 +                       dwc_otg_hcd_qh_add(hcd, qh);
43418 +               }
43419 +       } else {
43420 +               uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
43421 +
43422 +               if (qh->do_split) {
43423 +                       /* Schedule the next continuing periodic split transfer */
43424 +                       if (sched_next_periodic_split) {
43425 +
43426 +                               qh->sched_frame = frame_number;
43427 +                               if (dwc_frame_num_le(frame_number,
43428 +                                                    dwc_frame_num_inc
43429 +                                                    (qh->start_split_frame,
43430 +                                                     1))) {
43431 +                                       /*
43432 +                                        * Allow one frame to elapse after start
43433 +                                        * split microframe before scheduling
43434 +                                        * complete split, but DONT if we are
43435 +                                        * doing the next start split in the
43436 +                                        * same frame for an ISOC out.
43437 +                                        */
43438 +                                       if ((qh->ep_type != UE_ISOCHRONOUS) ||
43439 +                                           (qh->ep_is_in != 0)) {
43440 +                                               qh->sched_frame =
43441 +                                                   dwc_frame_num_inc(qh->sched_frame, 1);
43442 +                                       }
43443 +                               }
43444 +                       } else {
43445 +                               qh->sched_frame =
43446 +                                   dwc_frame_num_inc(qh->start_split_frame,
43447 +                                                     qh->interval);
43448 +                               if (dwc_frame_num_le
43449 +                                   (qh->sched_frame, frame_number)) {
43450 +                                       qh->sched_frame = frame_number;
43451 +                               }
43452 +                               qh->sched_frame |= 0x7;
43453 +                               qh->start_split_frame = qh->sched_frame;
43454 +                       }
43455 +               } else {
43456 +                       qh->sched_frame =
43457 +                           dwc_frame_num_inc(qh->sched_frame, qh->interval);
43458 +                       if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
43459 +                               qh->sched_frame = frame_number;
43460 +                       }
43461 +               }
43462 +
43463 +               if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43464 +                       dwc_otg_hcd_qh_remove(hcd, qh);
43465 +               } else {
43466 +                       /*
43467 +                        * Remove from periodic_sched_queued and move to
43468 +                        * appropriate queue.
43469 +                        */
43470 +                       if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||
43471 +                       (!microframe_schedule && qh->sched_frame == frame_number)) {
43472 +                               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
43473 +                                                  &qh->qh_list_entry);
43474 +                       } else {
43475 +                               DWC_LIST_MOVE_HEAD
43476 +                                   (&hcd->periodic_sched_inactive,
43477 +                                    &qh->qh_list_entry);
43478 +                       }
43479 +               }
43480 +       }
43481 +}
43482 +
43483 +/**
43484 + * This function allocates and initializes a QTD.
43485 + *
43486 + * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up
43487 + *           pointing to each other so each pair should have a unique correlation.
43488 + * @param atomic_alloc Flag to do atomic alloc if needed
43489 + *
43490 + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
43491 +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43492 +{
43493 +       dwc_otg_qtd_t *qtd;
43494 +
43495 +       qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);
43496 +       if (qtd == NULL) {
43497 +               return NULL;
43498 +       }
43499 +
43500 +       dwc_otg_hcd_qtd_init(qtd, urb);
43501 +       return qtd;
43502 +}
43503 +
43504 +/**
43505 + * Initializes a QTD structure.
43506 + *
43507 + * @param qtd The QTD to initialize.
43508 + * @param urb The URB to use for initialization.  */
43509 +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
43510 +{
43511 +       dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
43512 +       qtd->urb = urb;
43513 +       if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
43514 +               /*
43515 +                * The only time the QTD data toggle is used is on the data
43516 +                * phase of control transfers. This phase always starts with
43517 +                * DATA1.
43518 +                */
43519 +               qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
43520 +               qtd->control_phase = DWC_OTG_CONTROL_SETUP;
43521 +       }
43522 +
43523 +       /* start split */
43524 +       qtd->complete_split = 0;
43525 +       qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
43526 +       qtd->isoc_split_offset = 0;
43527 +       qtd->in_process = 0;
43528 +
43529 +       /* Store the qtd ptr in the urb to reference what QTD. */
43530 +       urb->qtd = qtd;
43531 +       return;
43532 +}
43533 +
43534 +/**
43535 + * This function adds a QTD to the QTD-list of a QH.  It will find the correct
43536 + * QH to place the QTD into.  If it does not find a QH, then it will create a
43537 + * new QH. If the QH to which the QTD is added is not currently scheduled, it
43538 + * is placed into the proper schedule based on its EP type.
43539 + *
43540 + * @param[in] qtd The QTD to add
43541 + * @param[in] hcd The DWC HCD structure
43542 + * @param[out] qh out parameter to return queue head
43543 + * @param atomic_alloc Flag to do atomic alloc if needed
43544 + *
43545 + * @return 0 if successful, negative error code otherwise.
43546 + */
43547 +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
43548 +                       dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
43549 +{
43550 +       int retval = 0;
43551 +       dwc_irqflags_t flags;
43552 +
43553 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
43554 +
43555 +       /*
43556 +        * Get the QH which holds the QTD-list to insert to. Create QH if it
43557 +        * doesn't exist.
43558 +        */
43559 +       if (*qh == NULL) {
43560 +               *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
43561 +               if (*qh == NULL) {
43562 +                       retval = -1;
43563 +                       goto done;
43564 +               }
43565 +       }
43566 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
43567 +       retval = dwc_otg_hcd_qh_add(hcd, *qh);
43568 +       if (retval == 0) {
43569 +               DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
43570 +                                       qtd_list_entry);
43571 +       }
43572 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
43573 +
43574 +done:
43575 +
43576 +       return retval;
43577 +}
43578 +
43579 +#endif /* DWC_DEVICE_ONLY */
43580 --- /dev/null
43581 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43582 @@ -0,0 +1,185 @@
43583 +#ifndef _DWC_OS_DEP_H_
43584 +#define _DWC_OS_DEP_H_
43585 +
43586 +/**
43587 + * @file
43588 + *
43589 + * This file contains OS dependent structures.
43590 + *
43591 + */
43592 +
43593 +#include <linux/kernel.h>
43594 +#include <linux/module.h>
43595 +#include <linux/moduleparam.h>
43596 +#include <linux/init.h>
43597 +#include <linux/device.h>
43598 +#include <linux/errno.h>
43599 +#include <linux/types.h>
43600 +#include <linux/slab.h>
43601 +#include <linux/list.h>
43602 +#include <linux/interrupt.h>
43603 +#include <linux/ctype.h>
43604 +#include <linux/string.h>
43605 +#include <linux/dma-mapping.h>
43606 +#include <linux/jiffies.h>
43607 +#include <linux/delay.h>
43608 +#include <linux/timer.h>
43609 +#include <linux/workqueue.h>
43610 +#include <linux/stat.h>
43611 +#include <linux/pci.h>
43612 +
43613 +#include <linux/version.h>
43614 +
43615 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
43616 +# include <linux/irq.h>
43617 +#endif
43618 +
43619 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
43620 +# include <linux/usb/ch9.h>
43621 +#else
43622 +# include <linux/usb_ch9.h>
43623 +#endif
43624 +
43625 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
43626 +# include <linux/usb/gadget.h>
43627 +#else
43628 +# include <linux/usb_gadget.h>
43629 +#endif
43630 +
43631 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
43632 +# include <asm/irq.h>
43633 +#endif
43634 +
43635 +#ifdef PCI_INTERFACE
43636 +# include <asm/io.h>
43637 +#endif
43638 +
43639 +#ifdef LM_INTERFACE
43640 +# include <asm/unaligned.h>
43641 +# include <asm/sizes.h>
43642 +# include <asm/param.h>
43643 +# include <asm/io.h>
43644 +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
43645 +#  include <asm/arch/hardware.h>
43646 +#  include <asm/arch/lm.h>
43647 +#  include <asm/arch/irqs.h>
43648 +#  include <asm/arch/regs-irq.h>
43649 +# else
43650 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
43651 +   here we assume that the machine architecture provides definitions
43652 +   in its own header
43653 +*/
43654 +#  include <mach/lm.h>
43655 +#  include <mach/hardware.h>
43656 +# endif
43657 +#endif
43658 +
43659 +#ifdef PLATFORM_INTERFACE
43660 +#include <linux/platform_device.h>
43661 +#include <asm/mach/map.h>
43662 +#endif
43663 +
43664 +/** The OS page size */
43665 +#define DWC_OS_PAGE_SIZE       PAGE_SIZE
43666 +
43667 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
43668 +typedef int gfp_t;
43669 +#endif
43670 +
43671 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
43672 +# define IRQF_SHARED SA_SHIRQ
43673 +#endif
43674 +
43675 +typedef struct os_dependent {
43676 +       /** Base address returned from ioremap() */
43677 +       void *base;
43678 +
43679 +       /** Register offset for Diagnostic API */
43680 +       uint32_t reg_offset;
43681 +
43682 +#ifdef LM_INTERFACE
43683 +       struct lm_device *lmdev;
43684 +#elif  defined(PCI_INTERFACE)
43685 +       struct pci_dev *pcidev;
43686 +
43687 +       /** Start address of a PCI region */
43688 +       resource_size_t rsrc_start;
43689 +
43690 +       /** Length address of a PCI region */
43691 +       resource_size_t rsrc_len;
43692 +#elif  defined(PLATFORM_INTERFACE)
43693 +       struct platform_device *platformdev;
43694 +#endif
43695 +
43696 +} os_dependent_t;
43697 +
43698 +#ifdef __cplusplus
43699 +}
43700 +#endif
43701 +
43702 +
43703 +
43704 +/* Type for the our device on the chosen bus */
43705 +#if   defined(LM_INTERFACE)
43706 +typedef struct lm_device       dwc_bus_dev_t;
43707 +#elif defined(PCI_INTERFACE)
43708 +typedef struct pci_dev         dwc_bus_dev_t;
43709 +#elif defined(PLATFORM_INTERFACE)
43710 +typedef struct platform_device dwc_bus_dev_t;
43711 +#endif
43712 +
43713 +/* Helper macro to retrieve drvdata from the device on the chosen bus */
43714 +#if    defined(LM_INTERFACE)
43715 +#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)
43716 +#elif  defined(PCI_INTERFACE)
43717 +#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)
43718 +#elif  defined(PLATFORM_INTERFACE)
43719 +#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)
43720 +#endif
43721 +
43722 +/**
43723 + * Helper macro returning the otg_device structure of a given struct device
43724 + *
43725 + * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
43726 + */
43727 +#ifdef LM_INTERFACE
43728 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43729 +                struct lm_device *lm_dev = \
43730 +                        container_of(_dev, struct lm_device, dev); \
43731 +                _var = lm_get_drvdata(lm_dev); \
43732 +        } while (0)
43733 +
43734 +#elif defined(PCI_INTERFACE)
43735 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43736 +                _var = dev_get_drvdata(_dev); \
43737 +        } while (0)
43738 +
43739 +#elif defined(PLATFORM_INTERFACE)
43740 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43741 +                struct platform_device *platform_dev = \
43742 +                        container_of(_dev, struct platform_device, dev); \
43743 +                _var = platform_get_drvdata(platform_dev); \
43744 +        } while (0)
43745 +#endif
43746 +
43747 +
43748 +/**
43749 + * Helper macro returning the struct dev of the given struct os_dependent
43750 + *
43751 + * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)
43752 + */
43753 +#ifdef LM_INTERFACE
43754 +#define DWC_OTG_OS_GETDEV(_osdep) \
43755 +        ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)
43756 +#elif defined(PCI_INTERFACE)
43757 +#define DWC_OTG_OS_GETDEV(_osdep) \
43758 +        ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)
43759 +#elif defined(PLATFORM_INTERFACE)
43760 +#define DWC_OTG_OS_GETDEV(_osdep) \
43761 +        ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)
43762 +#endif
43763 +
43764 +
43765 +
43766 +
43767 +#endif /* _DWC_OS_DEP_H_ */
43768 --- /dev/null
43769 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
43770 @@ -0,0 +1,2712 @@
43771 +/* ==========================================================================
43772 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
43773 + * $Revision: #101 $
43774 + * $Date: 2012/08/10 $
43775 + * $Change: 2047372 $
43776 + *
43777 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
43778 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
43779 + * otherwise expressly agreed to in writing between Synopsys and you.
43780 + *
43781 + * The Software IS NOT an item of Licensed Software or Licensed Product under
43782 + * any End User Software License Agreement or Agreement for Licensed Product
43783 + * with Synopsys or any supplement thereto. You are permitted to use and
43784 + * redistribute this Software in source and binary forms, with or without
43785 + * modification, provided that redistributions of source code must retain this
43786 + * notice. You may not view, use, disclose, copy or distribute this file or
43787 + * any information contained herein except pursuant to this license grant from
43788 + * Synopsys. If you do not agree with this notice, including the disclaimer
43789 + * below, then you are not authorized to use the Software.
43790 + *
43791 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
43792 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43793 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43794 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
43795 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43796 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43797 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
43798 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43799 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43800 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
43801 + * DAMAGE.
43802 + * ========================================================================== */
43803 +#ifndef DWC_HOST_ONLY
43804 +
43805 +/** @file
43806 + * This file implements PCD Core. All code in this file is portable and doesn't
43807 + * use any OS specific functions.
43808 + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
43809 + * header file, which can be used to implement OS specific PCD interface.
43810 + *
43811 + * An important function of the PCD is managing interrupts generated
43812 + * by the DWC_otg controller. The implementation of the DWC_otg device
43813 + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
43814 + *
43815 + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
43816 + * @todo Does it work when the request size is greater than DEPTSIZ
43817 + * transfer size
43818 + *
43819 + */
43820 +
43821 +#include "dwc_otg_pcd.h"
43822 +
43823 +#ifdef DWC_UTE_CFI
43824 +#include "dwc_otg_cfi.h"
43825 +
43826 +extern int init_cfi(cfiobject_t * cfiobj);
43827 +#endif
43828 +
43829 +/**
43830 + * Choose endpoint from ep arrays using usb_ep structure.
43831 + */
43832 +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
43833 +{
43834 +       int i;
43835 +       if (pcd->ep0.priv == handle) {
43836 +               return &pcd->ep0;
43837 +       }
43838 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
43839 +               if (pcd->in_ep[i].priv == handle)
43840 +                       return &pcd->in_ep[i];
43841 +               if (pcd->out_ep[i].priv == handle)
43842 +                       return &pcd->out_ep[i];
43843 +       }
43844 +
43845 +       return NULL;
43846 +}
43847 +
43848 +/**
43849 + * This function completes a request.  It call's the request call back.
43850 + */
43851 +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
43852 +                         int32_t status)
43853 +{
43854 +       unsigned stopped = ep->stopped;
43855 +
43856 +       DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
43857 +       DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
43858 +
43859 +       /* don't modify queue heads during completion callback */
43860 +       ep->stopped = 1;
43861 +       /* spin_unlock/spin_lock now done in fops->complete() */
43862 +       ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
43863 +                               req->actual);
43864 +
43865 +       if (ep->pcd->request_pending > 0) {
43866 +               --ep->pcd->request_pending;
43867 +       }
43868 +
43869 +       ep->stopped = stopped;
43870 +       DWC_FREE(req);
43871 +}
43872 +
43873 +/**
43874 + * This function terminates all the requsts in the EP request queue.
43875 + */
43876 +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
43877 +{
43878 +       dwc_otg_pcd_request_t *req;
43879 +
43880 +       ep->stopped = 1;
43881 +
43882 +       /* called with irqs blocked?? */
43883 +       while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
43884 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
43885 +               dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
43886 +       }
43887 +}
43888 +
43889 +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
43890 +                      const struct dwc_otg_pcd_function_ops *fops)
43891 +{
43892 +       pcd->fops = fops;
43893 +}
43894 +
43895 +/**
43896 + * PCD Callback function for initializing the PCD when switching to
43897 + * device mode.
43898 + *
43899 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43900 + */
43901 +static int32_t dwc_otg_pcd_start_cb(void *p)
43902 +{
43903 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43904 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
43905 +
43906 +       /*
43907 +        * Initialized the Core for Device mode.
43908 +        */
43909 +       if (dwc_otg_is_device_mode(core_if)) {
43910 +               dwc_otg_core_dev_init(core_if);
43911 +               /* Set core_if's lock pointer to the pcd->lock */
43912 +               core_if->lock = pcd->lock;
43913 +       }
43914 +       return 1;
43915 +}
43916 +
43917 +/** CFI-specific buffer allocation function for EP */
43918 +#ifdef DWC_UTE_CFI
43919 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
43920 +                             size_t buflen, int flags)
43921 +{
43922 +       dwc_otg_pcd_ep_t *ep;
43923 +       ep = get_ep_from_handle(pcd, pep);
43924 +       if (!ep) {
43925 +               DWC_WARN("bad ep\n");
43926 +               return -DWC_E_INVALID;
43927 +       }
43928 +
43929 +       return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
43930 +                                         flags);
43931 +}
43932 +#else
43933 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
43934 +                             size_t buflen, int flags);
43935 +#endif
43936 +
43937 +/**
43938 + * PCD Callback function for notifying the PCD when resuming from
43939 + * suspend.
43940 + *
43941 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43942 + */
43943 +static int32_t dwc_otg_pcd_resume_cb(void *p)
43944 +{
43945 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43946 +
43947 +       if (pcd->fops->resume) {
43948 +               pcd->fops->resume(pcd);
43949 +       }
43950 +
43951 +       /* Stop the SRP timeout timer. */
43952 +       if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
43953 +           || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
43954 +               if (GET_CORE_IF(pcd)->srp_timer_started) {
43955 +                       GET_CORE_IF(pcd)->srp_timer_started = 0;
43956 +                       DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
43957 +               }
43958 +       }
43959 +       return 1;
43960 +}
43961 +
43962 +/**
43963 + * PCD Callback function for notifying the PCD device is suspended.
43964 + *
43965 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43966 + */
43967 +static int32_t dwc_otg_pcd_suspend_cb(void *p)
43968 +{
43969 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43970 +
43971 +       if (pcd->fops->suspend) {
43972 +               DWC_SPINUNLOCK(pcd->lock);
43973 +               pcd->fops->suspend(pcd);
43974 +               DWC_SPINLOCK(pcd->lock);
43975 +       }
43976 +
43977 +       return 1;
43978 +}
43979 +
43980 +/**
43981 + * PCD Callback function for stopping the PCD when switching to Host
43982 + * mode.
43983 + *
43984 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43985 + */
43986 +static int32_t dwc_otg_pcd_stop_cb(void *p)
43987 +{
43988 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43989 +       extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
43990 +
43991 +       dwc_otg_pcd_stop(pcd);
43992 +       return 1;
43993 +}
43994 +
43995 +/**
43996 + * PCD Callback structure for handling mode switching.
43997 + */
43998 +static dwc_otg_cil_callbacks_t pcd_callbacks = {
43999 +       .start = dwc_otg_pcd_start_cb,
44000 +       .stop = dwc_otg_pcd_stop_cb,
44001 +       .suspend = dwc_otg_pcd_suspend_cb,
44002 +       .resume_wakeup = dwc_otg_pcd_resume_cb,
44003 +       .p = 0,                 /* Set at registration */
44004 +};
44005 +
44006 +/**
44007 + * This function allocates a DMA Descriptor chain for the Endpoint
44008 + * buffer to be used for a transfer to/from the specified endpoint.
44009 + */
44010 +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
44011 +                                                   uint32_t count)
44012 +{
44013 +       return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t),
44014 +                                                       dma_desc_addr);
44015 +}
44016 +
44017 +/**
44018 + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
44019 + */
44020 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
44021 +                               uint32_t dma_desc_addr, uint32_t count)
44022 +{
44023 +       DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
44024 +                    dma_desc_addr);
44025 +}
44026 +
44027 +#ifdef DWC_EN_ISOC
44028 +
44029 +/**
44030 + * This function initializes a descriptor chain for Isochronous transfer
44031 + *
44032 + * @param core_if Programming view of DWC_otg controller.
44033 + * @param dwc_ep The EP to start the transfer on.
44034 + *
44035 + */
44036 +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
44037 +                                       dwc_ep_t * dwc_ep)
44038 +{
44039 +
44040 +       dsts_data_t dsts = {.d32 = 0 };
44041 +       depctl_data_t depctl = {.d32 = 0 };
44042 +       volatile uint32_t *addr;
44043 +       int i, j;
44044 +       uint32_t len;
44045 +
44046 +       if (dwc_ep->is_in)
44047 +               dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
44048 +       else
44049 +               dwc_ep->desc_cnt =
44050 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44051 +                   dwc_ep->bInterval;
44052 +
44053 +       /** Allocate descriptors for double buffering */
44054 +       dwc_ep->iso_desc_addr =
44055 +           dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
44056 +                                       dwc_ep->desc_cnt * 2);
44057 +       if (dwc_ep->desc_addr) {
44058 +               DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
44059 +               return;
44060 +       }
44061 +
44062 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44063 +
44064 +       /** ISO OUT EP */
44065 +       if (dwc_ep->is_in == 0) {
44066 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44067 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44068 +               dma_addr_t dma_ad;
44069 +               uint32_t data_per_desc;
44070 +               dwc_otg_dev_out_ep_regs_t *out_regs =
44071 +                   core_if->dev_if->out_ep_regs[dwc_ep->num];
44072 +               int offset;
44073 +
44074 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
44075 +               dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
44076 +
44077 +               /** Buffer 0 descriptors setup */
44078 +               dma_ad = dwc_ep->dma_addr0;
44079 +
44080 +               sts.b_iso_out.bs = BS_HOST_READY;
44081 +               sts.b_iso_out.rxsts = 0;
44082 +               sts.b_iso_out.l = 0;
44083 +               sts.b_iso_out.sp = 0;
44084 +               sts.b_iso_out.ioc = 0;
44085 +               sts.b_iso_out.pid = 0;
44086 +               sts.b_iso_out.framenum = 0;
44087 +
44088 +               offset = 0;
44089 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44090 +                    i += dwc_ep->pkt_per_frm) {
44091 +
44092 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44093 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44094 +                               if (len > dwc_ep->data_per_frame)
44095 +                                       data_per_desc =
44096 +                                           dwc_ep->data_per_frame -
44097 +                                           j * dwc_ep->maxpacket;
44098 +                               else
44099 +                                       data_per_desc = dwc_ep->maxpacket;
44100 +                               len = data_per_desc % 4;
44101 +                               if (len)
44102 +                                       data_per_desc += 4 - len;
44103 +
44104 +                               sts.b_iso_out.rxbytes = data_per_desc;
44105 +                               dma_desc->buf = dma_ad;
44106 +                               dma_desc->status.d32 = sts.d32;
44107 +
44108 +                               offset += data_per_desc;
44109 +                               dma_desc++;
44110 +                               dma_ad += data_per_desc;
44111 +                       }
44112 +               }
44113 +
44114 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44115 +                       uint32_t len = (j + 1) * dwc_ep->maxpacket;
44116 +                       if (len > dwc_ep->data_per_frame)
44117 +                               data_per_desc =
44118 +                                   dwc_ep->data_per_frame -
44119 +                                   j * dwc_ep->maxpacket;
44120 +                       else
44121 +                               data_per_desc = dwc_ep->maxpacket;
44122 +                       len = data_per_desc % 4;
44123 +                       if (len)
44124 +                               data_per_desc += 4 - len;
44125 +                       sts.b_iso_out.rxbytes = data_per_desc;
44126 +                       dma_desc->buf = dma_ad;
44127 +                       dma_desc->status.d32 = sts.d32;
44128 +
44129 +                       offset += data_per_desc;
44130 +                       dma_desc++;
44131 +                       dma_ad += data_per_desc;
44132 +               }
44133 +
44134 +               sts.b_iso_out.ioc = 1;
44135 +               len = (j + 1) * dwc_ep->maxpacket;
44136 +               if (len > dwc_ep->data_per_frame)
44137 +                       data_per_desc =
44138 +                           dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
44139 +               else
44140 +                       data_per_desc = dwc_ep->maxpacket;
44141 +               len = data_per_desc % 4;
44142 +               if (len)
44143 +                       data_per_desc += 4 - len;
44144 +               sts.b_iso_out.rxbytes = data_per_desc;
44145 +
44146 +               dma_desc->buf = dma_ad;
44147 +               dma_desc->status.d32 = sts.d32;
44148 +               dma_desc++;
44149 +
44150 +               /** Buffer 1 descriptors setup */
44151 +               sts.b_iso_out.ioc = 0;
44152 +               dma_ad = dwc_ep->dma_addr1;
44153 +
44154 +               offset = 0;
44155 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44156 +                    i += dwc_ep->pkt_per_frm) {
44157 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44158 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44159 +                               if (len > dwc_ep->data_per_frame)
44160 +                                       data_per_desc =
44161 +                                           dwc_ep->data_per_frame -
44162 +                                           j * dwc_ep->maxpacket;
44163 +                               else
44164 +                                       data_per_desc = dwc_ep->maxpacket;
44165 +                               len = data_per_desc % 4;
44166 +                               if (len)
44167 +                                       data_per_desc += 4 - len;
44168 +
44169 +                               data_per_desc =
44170 +                                   sts.b_iso_out.rxbytes = data_per_desc;
44171 +                               dma_desc->buf = dma_ad;
44172 +                               dma_desc->status.d32 = sts.d32;
44173 +
44174 +                               offset += data_per_desc;
44175 +                               dma_desc++;
44176 +                               dma_ad += data_per_desc;
44177 +                       }
44178 +               }
44179 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44180 +                       data_per_desc =
44181 +                           ((j + 1) * dwc_ep->maxpacket >
44182 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44183 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44184 +                       data_per_desc +=
44185 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44186 +                       sts.b_iso_out.rxbytes = data_per_desc;
44187 +                       dma_desc->buf = dma_ad;
44188 +                       dma_desc->status.d32 = sts.d32;
44189 +
44190 +                       offset += data_per_desc;
44191 +                       dma_desc++;
44192 +                       dma_ad += data_per_desc;
44193 +               }
44194 +
44195 +               sts.b_iso_out.ioc = 1;
44196 +               sts.b_iso_out.l = 1;
44197 +               data_per_desc =
44198 +                   ((j + 1) * dwc_ep->maxpacket >
44199 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44200 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44201 +               data_per_desc +=
44202 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44203 +               sts.b_iso_out.rxbytes = data_per_desc;
44204 +
44205 +               dma_desc->buf = dma_ad;
44206 +               dma_desc->status.d32 = sts.d32;
44207 +
44208 +               dwc_ep->next_frame = 0;
44209 +
44210 +               /** Write dma_ad into DOEPDMA register */
44211 +               DWC_WRITE_REG32(&(out_regs->doepdma),
44212 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44213 +
44214 +       }
44215 +       /** ISO IN EP */
44216 +       else {
44217 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44218 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44219 +               dma_addr_t dma_ad;
44220 +               dwc_otg_dev_in_ep_regs_t *in_regs =
44221 +                   core_if->dev_if->in_ep_regs[dwc_ep->num];
44222 +               unsigned int frmnumber;
44223 +               fifosize_data_t txfifosize, rxfifosize;
44224 +
44225 +               txfifosize.d32 =
44226 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
44227 +                                  dtxfsts);
44228 +               rxfifosize.d32 =
44229 +                   DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
44230 +
44231 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
44232 +
44233 +               dma_ad = dwc_ep->dma_addr0;
44234 +
44235 +               dsts.d32 =
44236 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44237 +
44238 +               sts.b_iso_in.bs = BS_HOST_READY;
44239 +               sts.b_iso_in.txsts = 0;
44240 +               sts.b_iso_in.sp =
44241 +                   (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
44242 +               sts.b_iso_in.ioc = 0;
44243 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
44244 +
44245 +               frmnumber = dwc_ep->next_frame;
44246 +
44247 +               sts.b_iso_in.framenum = frmnumber;
44248 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
44249 +               sts.b_iso_in.l = 0;
44250 +
44251 +               /** Buffer 0 descriptors setup */
44252 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
44253 +                       dma_desc->buf = dma_ad;
44254 +                       dma_desc->status.d32 = sts.d32;
44255 +                       dma_desc++;
44256 +
44257 +                       dma_ad += dwc_ep->data_per_frame;
44258 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44259 +               }
44260 +
44261 +               sts.b_iso_in.ioc = 1;
44262 +               dma_desc->buf = dma_ad;
44263 +               dma_desc->status.d32 = sts.d32;
44264 +               ++dma_desc;
44265 +
44266 +               /** Buffer 1 descriptors setup */
44267 +               sts.b_iso_in.ioc = 0;
44268 +               dma_ad = dwc_ep->dma_addr1;
44269 +
44270 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44271 +                    i += dwc_ep->pkt_per_frm) {
44272 +                       dma_desc->buf = dma_ad;
44273 +                       dma_desc->status.d32 = sts.d32;
44274 +                       dma_desc++;
44275 +
44276 +                       dma_ad += dwc_ep->data_per_frame;
44277 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44278 +
44279 +                       sts.b_iso_in.ioc = 0;
44280 +               }
44281 +               sts.b_iso_in.ioc = 1;
44282 +               sts.b_iso_in.l = 1;
44283 +
44284 +               dma_desc->buf = dma_ad;
44285 +               dma_desc->status.d32 = sts.d32;
44286 +
44287 +               dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
44288 +
44289 +               /** Write dma_ad into diepdma register */
44290 +               DWC_WRITE_REG32(&(in_regs->diepdma),
44291 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44292 +       }
44293 +       /** Enable endpoint, clear nak  */
44294 +       depctl.d32 = 0;
44295 +       depctl.b.epena = 1;
44296 +       depctl.b.usbactep = 1;
44297 +       depctl.b.cnak = 1;
44298 +
44299 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44300 +       depctl.d32 = DWC_READ_REG32(addr);
44301 +}
44302 +
44303 +/**
44304 + * This function initializes a descriptor chain for Isochronous transfer
44305 + *
44306 + * @param core_if Programming view of DWC_otg controller.
44307 + * @param ep The EP to start the transfer on.
44308 + *
44309 + */
44310 +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
44311 +                                      dwc_ep_t * ep)
44312 +{
44313 +       depctl_data_t depctl = {.d32 = 0 };
44314 +       volatile uint32_t *addr;
44315 +
44316 +       if (ep->is_in) {
44317 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44318 +       } else {
44319 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44320 +       }
44321 +
44322 +       if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
44323 +               return;
44324 +       } else {
44325 +               deptsiz_data_t deptsiz = {.d32 = 0 };
44326 +
44327 +               ep->xfer_len =
44328 +                   ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
44329 +               ep->pkt_cnt =
44330 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44331 +               ep->xfer_count = 0;
44332 +               ep->xfer_buff =
44333 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44334 +               ep->dma_addr =
44335 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44336 +
44337 +               if (ep->is_in) {
44338 +                       /* Program the transfer size and packet count
44339 +                        *      as follows: xfersize = N * maxpacket +
44340 +                        *      short_packet pktcnt = N + (short_packet
44341 +                        *      exist ? 1 : 0)
44342 +                        */
44343 +                       deptsiz.b.mc = ep->pkt_per_frm;
44344 +                       deptsiz.b.xfersize = ep->xfer_len;
44345 +                       deptsiz.b.pktcnt =
44346 +                           (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44347 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
44348 +                                       dieptsiz, deptsiz.d32);
44349 +
44350 +                       /* Write the DMA register */
44351 +                       DWC_WRITE_REG32(&
44352 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
44353 +                                        diepdma), (uint32_t) ep->dma_addr);
44354 +
44355 +               } else {
44356 +                       deptsiz.b.pktcnt =
44357 +                           (ep->xfer_len + (ep->maxpacket - 1)) /
44358 +                           ep->maxpacket;
44359 +                       deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
44360 +
44361 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
44362 +                                       doeptsiz, deptsiz.d32);
44363 +
44364 +                       /* Write the DMA register */
44365 +                       DWC_WRITE_REG32(&
44366 +                                       (core_if->dev_if->out_ep_regs[ep->num]->
44367 +                                        doepdma), (uint32_t) ep->dma_addr);
44368 +
44369 +               }
44370 +               /** Enable endpoint, clear nak  */
44371 +               depctl.d32 = 0;
44372 +               depctl.b.epena = 1;
44373 +               depctl.b.cnak = 1;
44374 +
44375 +               DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44376 +       }
44377 +}
44378 +
44379 +/**
44380 + * This function does the setup for a data transfer for an EP and
44381 + * starts the transfer. For an IN transfer, the packets will be
44382 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
44383 + * the packets are unloaded from the Rx FIFO in the ISR.
44384 + *
44385 + * @param core_if Programming view of DWC_otg controller.
44386 + * @param ep The EP to start the transfer on.
44387 + */
44388 +
44389 +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
44390 +                                         dwc_ep_t * ep)
44391 +{
44392 +       if (core_if->dma_enable) {
44393 +               if (core_if->dma_desc_enable) {
44394 +                       if (ep->is_in) {
44395 +                               ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
44396 +                       } else {
44397 +                               ep->desc_cnt = ep->pkt_cnt;
44398 +                       }
44399 +                       dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
44400 +               } else {
44401 +                       if (core_if->pti_enh_enable) {
44402 +                               dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
44403 +                       } else {
44404 +                               ep->cur_pkt_addr =
44405 +                                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
44406 +                                   xfer_buff0;
44407 +                               ep->cur_pkt_dma_addr =
44408 +                                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->
44409 +                                   dma_addr0;
44410 +                               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44411 +                       }
44412 +               }
44413 +       } else {
44414 +               ep->cur_pkt_addr =
44415 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44416 +               ep->cur_pkt_dma_addr =
44417 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44418 +               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44419 +       }
44420 +}
44421 +
44422 +/**
44423 + * This function stops transfer for an EP and
44424 + * resets the ep's variables.
44425 + *
44426 + * @param core_if Programming view of DWC_otg controller.
44427 + * @param ep The EP to start the transfer on.
44428 + */
44429 +
44430 +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
44431 +{
44432 +       depctl_data_t depctl = {.d32 = 0 };
44433 +       volatile uint32_t *addr;
44434 +
44435 +       if (ep->is_in == 1) {
44436 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44437 +       } else {
44438 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44439 +       }
44440 +
44441 +       /* disable the ep */
44442 +       depctl.d32 = DWC_READ_REG32(addr);
44443 +
44444 +       depctl.b.epdis = 1;
44445 +       depctl.b.snak = 1;
44446 +
44447 +       DWC_WRITE_REG32(addr, depctl.d32);
44448 +
44449 +       if (core_if->dma_desc_enable &&
44450 +           ep->iso_desc_addr && ep->iso_dma_desc_addr) {
44451 +               dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
44452 +                                          ep->iso_dma_desc_addr,
44453 +                                          ep->desc_cnt * 2);
44454 +       }
44455 +
44456 +       /* reset varibales */
44457 +       ep->dma_addr0 = 0;
44458 +       ep->dma_addr1 = 0;
44459 +       ep->xfer_buff0 = 0;
44460 +       ep->xfer_buff1 = 0;
44461 +       ep->data_per_frame = 0;
44462 +       ep->data_pattern_frame = 0;
44463 +       ep->sync_frame = 0;
44464 +       ep->buf_proc_intrvl = 0;
44465 +       ep->bInterval = 0;
44466 +       ep->proc_buf_num = 0;
44467 +       ep->pkt_per_frm = 0;
44468 +       ep->pkt_per_frm = 0;
44469 +       ep->desc_cnt = 0;
44470 +       ep->iso_desc_addr = 0;
44471 +       ep->iso_dma_desc_addr = 0;
44472 +}
44473 +
44474 +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
44475 +                            uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
44476 +                            dwc_dma_t dma1, int sync_frame, int dp_frame,
44477 +                            int data_per_frame, int start_frame,
44478 +                            int buf_proc_intrvl, void *req_handle,
44479 +                            int atomic_alloc)
44480 +{
44481 +       dwc_otg_pcd_ep_t *ep;
44482 +       dwc_irqflags_t flags = 0;
44483 +       dwc_ep_t *dwc_ep;
44484 +       int32_t frm_data;
44485 +       dsts_data_t dsts;
44486 +       dwc_otg_core_if_t *core_if;
44487 +
44488 +       ep = get_ep_from_handle(pcd, ep_handle);
44489 +
44490 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44491 +               DWC_WARN("bad ep\n");
44492 +               return -DWC_E_INVALID;
44493 +       }
44494 +
44495 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44496 +       core_if = GET_CORE_IF(pcd);
44497 +       dwc_ep = &ep->dwc_ep;
44498 +
44499 +       if (ep->iso_req_handle) {
44500 +               DWC_WARN("ISO request in progress\n");
44501 +       }
44502 +
44503 +       dwc_ep->dma_addr0 = dma0;
44504 +       dwc_ep->dma_addr1 = dma1;
44505 +
44506 +       dwc_ep->xfer_buff0 = buf0;
44507 +       dwc_ep->xfer_buff1 = buf1;
44508 +
44509 +       dwc_ep->data_per_frame = data_per_frame;
44510 +
44511 +       /** @todo - pattern data support is to be implemented in the future */
44512 +       dwc_ep->data_pattern_frame = dp_frame;
44513 +       dwc_ep->sync_frame = sync_frame;
44514 +
44515 +       dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
44516 +
44517 +       dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
44518 +
44519 +       dwc_ep->proc_buf_num = 0;
44520 +
44521 +       dwc_ep->pkt_per_frm = 0;
44522 +       frm_data = ep->dwc_ep.data_per_frame;
44523 +       while (frm_data > 0) {
44524 +               dwc_ep->pkt_per_frm++;
44525 +               frm_data -= ep->dwc_ep.maxpacket;
44526 +       }
44527 +
44528 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44529 +
44530 +       if (start_frame == -1) {
44531 +               dwc_ep->next_frame = dsts.b.soffn + 1;
44532 +               if (dwc_ep->bInterval != 1) {
44533 +                       dwc_ep->next_frame =
44534 +                           dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
44535 +                                                 dwc_ep->next_frame %
44536 +                                                 dwc_ep->bInterval);
44537 +               }
44538 +       } else {
44539 +               dwc_ep->next_frame = start_frame;
44540 +       }
44541 +
44542 +       if (!core_if->pti_enh_enable) {
44543 +               dwc_ep->pkt_cnt =
44544 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44545 +                   dwc_ep->bInterval;
44546 +       } else {
44547 +               dwc_ep->pkt_cnt =
44548 +                   (dwc_ep->data_per_frame *
44549 +                    (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
44550 +                    - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
44551 +       }
44552 +
44553 +       if (core_if->dma_desc_enable) {
44554 +               dwc_ep->desc_cnt =
44555 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44556 +                   dwc_ep->bInterval;
44557 +       }
44558 +
44559 +       if (atomic_alloc) {
44560 +               dwc_ep->pkt_info =
44561 +                   DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44562 +       } else {
44563 +               dwc_ep->pkt_info =
44564 +                   DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44565 +       }
44566 +       if (!dwc_ep->pkt_info) {
44567 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44568 +               return -DWC_E_NO_MEMORY;
44569 +       }
44570 +       if (core_if->pti_enh_enable) {
44571 +               dwc_memset(dwc_ep->pkt_info, 0,
44572 +                          sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44573 +       }
44574 +
44575 +       dwc_ep->cur_pkt = 0;
44576 +       ep->iso_req_handle = req_handle;
44577 +
44578 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44579 +       dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
44580 +       return 0;
44581 +}
44582 +
44583 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
44584 +                           void *req_handle)
44585 +{
44586 +       dwc_irqflags_t flags = 0;
44587 +       dwc_otg_pcd_ep_t *ep;
44588 +       dwc_ep_t *dwc_ep;
44589 +
44590 +       ep = get_ep_from_handle(pcd, ep_handle);
44591 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44592 +               DWC_WARN("bad ep\n");
44593 +               return -DWC_E_INVALID;
44594 +       }
44595 +       dwc_ep = &ep->dwc_ep;
44596 +
44597 +       dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
44598 +
44599 +       DWC_FREE(dwc_ep->pkt_info);
44600 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44601 +       if (ep->iso_req_handle != req_handle) {
44602 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44603 +               return -DWC_E_INVALID;
44604 +       }
44605 +
44606 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44607 +
44608 +       ep->iso_req_handle = 0;
44609 +       return 0;
44610 +}
44611 +
44612 +/**
44613 + * This function is used for perodical data exchnage between PCD and gadget drivers.
44614 + * for Isochronous EPs
44615 + *
44616 + *     - Every time a sync period completes this function is called to
44617 + *       perform data exchange between PCD and gadget
44618 + */
44619 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
44620 +                            void *req_handle)
44621 +{
44622 +       int i;
44623 +       dwc_ep_t *dwc_ep;
44624 +
44625 +       dwc_ep = &ep->dwc_ep;
44626 +
44627 +       DWC_SPINUNLOCK(ep->pcd->lock);
44628 +       pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
44629 +                                dwc_ep->proc_buf_num ^ 0x1);
44630 +       DWC_SPINLOCK(ep->pcd->lock);
44631 +
44632 +       for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
44633 +               dwc_ep->pkt_info[i].status = 0;
44634 +               dwc_ep->pkt_info[i].offset = 0;
44635 +               dwc_ep->pkt_info[i].length = 0;
44636 +       }
44637 +}
44638 +
44639 +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
44640 +                                    void *iso_req_handle)
44641 +{
44642 +       dwc_otg_pcd_ep_t *ep;
44643 +       dwc_ep_t *dwc_ep;
44644 +
44645 +       ep = get_ep_from_handle(pcd, ep_handle);
44646 +       if (!ep->desc || ep->dwc_ep.num == 0) {
44647 +               DWC_WARN("bad ep\n");
44648 +               return -DWC_E_INVALID;
44649 +       }
44650 +       dwc_ep = &ep->dwc_ep;
44651 +
44652 +       return dwc_ep->pkt_cnt;
44653 +}
44654 +
44655 +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
44656 +                                      void *iso_req_handle, int packet,
44657 +                                      int *status, int *actual, int *offset)
44658 +{
44659 +       dwc_otg_pcd_ep_t *ep;
44660 +       dwc_ep_t *dwc_ep;
44661 +
44662 +       ep = get_ep_from_handle(pcd, ep_handle);
44663 +       if (!ep)
44664 +               DWC_WARN("bad ep\n");
44665 +
44666 +       dwc_ep = &ep->dwc_ep;
44667 +
44668 +       *status = dwc_ep->pkt_info[packet].status;
44669 +       *actual = dwc_ep->pkt_info[packet].length;
44670 +       *offset = dwc_ep->pkt_info[packet].offset;
44671 +}
44672 +
44673 +#endif /* DWC_EN_ISOC */
44674 +
44675 +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
44676 +                               uint32_t is_in, uint32_t ep_num)
44677 +{
44678 +       /* Init EP structure */
44679 +       pcd_ep->desc = 0;
44680 +       pcd_ep->pcd = pcd;
44681 +       pcd_ep->stopped = 1;
44682 +       pcd_ep->queue_sof = 0;
44683 +
44684 +       /* Init DWC ep structure */
44685 +       pcd_ep->dwc_ep.is_in = is_in;
44686 +       pcd_ep->dwc_ep.num = ep_num;
44687 +       pcd_ep->dwc_ep.active = 0;
44688 +       pcd_ep->dwc_ep.tx_fifo_num = 0;
44689 +       /* Control until ep is actvated */
44690 +       pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44691 +       pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
44692 +       pcd_ep->dwc_ep.dma_addr = 0;
44693 +       pcd_ep->dwc_ep.start_xfer_buff = 0;
44694 +       pcd_ep->dwc_ep.xfer_buff = 0;
44695 +       pcd_ep->dwc_ep.xfer_len = 0;
44696 +       pcd_ep->dwc_ep.xfer_count = 0;
44697 +       pcd_ep->dwc_ep.sent_zlp = 0;
44698 +       pcd_ep->dwc_ep.total_len = 0;
44699 +       pcd_ep->dwc_ep.desc_addr = 0;
44700 +       pcd_ep->dwc_ep.dma_desc_addr = 0;
44701 +       DWC_CIRCLEQ_INIT(&pcd_ep->queue);
44702 +}
44703 +
44704 +/**
44705 + * Initialize ep's
44706 + */
44707 +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
44708 +{
44709 +       int i;
44710 +       uint32_t hwcfg1;
44711 +       dwc_otg_pcd_ep_t *ep;
44712 +       int in_ep_cntr, out_ep_cntr;
44713 +       uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
44714 +       uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
44715 +
44716 +       /**
44717 +        * Initialize the EP0 structure.
44718 +        */
44719 +       ep = &pcd->ep0;
44720 +       dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
44721 +
44722 +       in_ep_cntr = 0;
44723 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
44724 +       for (i = 1; in_ep_cntr < num_in_eps; i++) {
44725 +               if ((hwcfg1 & 0x1) == 0) {
44726 +                       dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
44727 +                       in_ep_cntr++;
44728 +                       /**
44729 +                        * @todo NGS: Add direction to EP, based on contents
44730 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44731 +                        * sprintf(";r
44732 +                        */
44733 +                       dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
44734 +
44735 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44736 +               }
44737 +               hwcfg1 >>= 2;
44738 +       }
44739 +
44740 +       out_ep_cntr = 0;
44741 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
44742 +       for (i = 1; out_ep_cntr < num_out_eps; i++) {
44743 +               if ((hwcfg1 & 0x1) == 0) {
44744 +                       dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
44745 +                       out_ep_cntr++;
44746 +                       /**
44747 +                        * @todo NGS: Add direction to EP, based on contents
44748 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44749 +                        * sprintf(";r
44750 +                        */
44751 +                       dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
44752 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44753 +               }
44754 +               hwcfg1 >>= 2;
44755 +       }
44756 +
44757 +       pcd->ep0state = EP0_DISCONNECT;
44758 +       pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
44759 +       pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44760 +}
44761 +
44762 +/**
44763 + * This function is called when the SRP timer expires. The SRP should
44764 + * complete within 6 seconds.
44765 + */
44766 +static void srp_timeout(void *ptr)
44767 +{
44768 +       gotgctl_data_t gotgctl;
44769 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
44770 +       volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
44771 +
44772 +       gotgctl.d32 = DWC_READ_REG32(addr);
44773 +
44774 +       core_if->srp_timer_started = 0;
44775 +
44776 +       if (core_if->adp_enable) {
44777 +               if (gotgctl.b.bsesvld == 0) {
44778 +                       gpwrdn_data_t gpwrdn = {.d32 = 0 };
44779 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
44780 +                       /* Power off the core */
44781 +                       if (core_if->power_down == 2) {
44782 +                               gpwrdn.b.pwrdnswtch = 1;
44783 +                               DWC_MODIFY_REG32(&core_if->
44784 +                                                core_global_regs->gpwrdn,
44785 +                                                gpwrdn.d32, 0);
44786 +                       }
44787 +
44788 +                       gpwrdn.d32 = 0;
44789 +                       gpwrdn.b.pmuintsel = 1;
44790 +                       gpwrdn.b.pmuactv = 1;
44791 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
44792 +                                        gpwrdn.d32);
44793 +                       dwc_otg_adp_probe_start(core_if);
44794 +               } else {
44795 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
44796 +                       core_if->op_state = B_PERIPHERAL;
44797 +                       dwc_otg_core_init(core_if);
44798 +                       dwc_otg_enable_global_interrupts(core_if);
44799 +                       cil_pcd_start(core_if);
44800 +               }
44801 +       }
44802 +
44803 +       if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
44804 +           (core_if->core_params->i2c_enable)) {
44805 +               DWC_PRINTF("SRP Timeout\n");
44806 +
44807 +               if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
44808 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
44809 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
44810 +                       }
44811 +
44812 +                       /* Clear Session Request */
44813 +                       gotgctl.d32 = 0;
44814 +                       gotgctl.b.sesreq = 1;
44815 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
44816 +                                        gotgctl.d32, 0);
44817 +
44818 +                       core_if->srp_success = 0;
44819 +               } else {
44820 +                       __DWC_ERROR("Device not connected/responding\n");
44821 +                       gotgctl.b.sesreq = 0;
44822 +                       DWC_WRITE_REG32(addr, gotgctl.d32);
44823 +               }
44824 +       } else if (gotgctl.b.sesreq) {
44825 +               DWC_PRINTF("SRP Timeout\n");
44826 +
44827 +               __DWC_ERROR("Device not connected/responding\n");
44828 +               gotgctl.b.sesreq = 0;
44829 +               DWC_WRITE_REG32(addr, gotgctl.d32);
44830 +       } else {
44831 +               DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
44832 +       }
44833 +}
44834 +
44835 +/**
44836 + * Tasklet
44837 + *
44838 + */
44839 +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
44840 +
44841 +static void start_xfer_tasklet_func(void *data)
44842 +{
44843 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
44844 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
44845 +
44846 +       int i;
44847 +       depctl_data_t diepctl;
44848 +
44849 +       DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
44850 +
44851 +       diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
44852 +
44853 +       if (pcd->ep0.queue_sof) {
44854 +               pcd->ep0.queue_sof = 0;
44855 +               start_next_request(&pcd->ep0);
44856 +               // break;
44857 +       }
44858 +
44859 +       for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
44860 +               depctl_data_t diepctl;
44861 +               diepctl.d32 =
44862 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
44863 +
44864 +               if (pcd->in_ep[i].queue_sof) {
44865 +                       pcd->in_ep[i].queue_sof = 0;
44866 +                       start_next_request(&pcd->in_ep[i]);
44867 +                       // break;
44868 +               }
44869 +       }
44870 +
44871 +       return;
44872 +}
44873 +
44874 +/**
44875 + * This function initialized the PCD portion of the driver.
44876 + *
44877 + */
44878 +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
44879 +{
44880 +       dwc_otg_pcd_t *pcd = NULL;
44881 +       dwc_otg_dev_if_t *dev_if;
44882 +       int i;
44883 +
44884 +       /*
44885 +        * Allocate PCD structure
44886 +        */
44887 +       pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
44888 +
44889 +       if (pcd == NULL) {
44890 +               return NULL;
44891 +       }
44892 +
44893 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
44894 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(pcd->lock);
44895 +#else
44896 +       pcd->lock = DWC_SPINLOCK_ALLOC();
44897 +#endif
44898 +        DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
44899 +                    pcd, core_if);//GRAYG
44900 +       if (!pcd->lock) {
44901 +               DWC_ERROR("Could not allocate lock for pcd");
44902 +               DWC_FREE(pcd);
44903 +               return NULL;
44904 +       }
44905 +       /* Set core_if's lock pointer to hcd->lock */
44906 +       core_if->lock = pcd->lock;
44907 +       pcd->core_if = core_if;
44908 +
44909 +       dev_if = core_if->dev_if;
44910 +       dev_if->isoc_ep = NULL;
44911 +
44912 +       if (core_if->hwcfg4.b.ded_fifo_en) {
44913 +               DWC_PRINTF("Dedicated Tx FIFOs mode\n");
44914 +       } else {
44915 +               DWC_PRINTF("Shared Tx FIFO mode\n");
44916 +       }
44917 +
44918 +       /*
44919 +        * Initialized the Core for Device mode here if there is nod ADP support.
44920 +        * Otherwise it will be done later in dwc_otg_adp_start routine.
44921 +        */
44922 +       if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
44923 +               dwc_otg_core_dev_init(core_if);
44924 +       }
44925 +
44926 +       /*
44927 +        * Register the PCD Callbacks.
44928 +        */
44929 +       dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
44930 +
44931 +       /*
44932 +        * Initialize the DMA buffer for SETUP packets
44933 +        */
44934 +       if (GET_CORE_IF(pcd)->dma_enable) {
44935 +               pcd->setup_pkt =
44936 +                   DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
44937 +                                 &pcd->setup_pkt_dma_handle);
44938 +               if (pcd->setup_pkt == NULL) {
44939 +                       DWC_FREE(pcd);
44940 +                       return NULL;
44941 +               }
44942 +
44943 +               pcd->status_buf =
44944 +                   DWC_DMA_ALLOC(sizeof(uint16_t),
44945 +                                 &pcd->status_buf_dma_handle);
44946 +               if (pcd->status_buf == NULL) {
44947 +                       DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
44948 +                                    pcd->setup_pkt, pcd->setup_pkt_dma_handle);
44949 +                       DWC_FREE(pcd);
44950 +                       return NULL;
44951 +               }
44952 +
44953 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
44954 +                       dev_if->setup_desc_addr[0] =
44955 +                           dwc_otg_ep_alloc_desc_chain
44956 +                           (&dev_if->dma_setup_desc_addr[0], 1);
44957 +                       dev_if->setup_desc_addr[1] =
44958 +                           dwc_otg_ep_alloc_desc_chain
44959 +                           (&dev_if->dma_setup_desc_addr[1], 1);
44960 +                       dev_if->in_desc_addr =
44961 +                           dwc_otg_ep_alloc_desc_chain
44962 +                           (&dev_if->dma_in_desc_addr, 1);
44963 +                       dev_if->out_desc_addr =
44964 +                           dwc_otg_ep_alloc_desc_chain
44965 +                           (&dev_if->dma_out_desc_addr, 1);
44966 +                       pcd->data_terminated = 0;
44967 +
44968 +                       if (dev_if->setup_desc_addr[0] == 0
44969 +                           || dev_if->setup_desc_addr[1] == 0
44970 +                           || dev_if->in_desc_addr == 0
44971 +                           || dev_if->out_desc_addr == 0) {
44972 +
44973 +                               if (dev_if->out_desc_addr)
44974 +                                       dwc_otg_ep_free_desc_chain
44975 +                                           (dev_if->out_desc_addr,
44976 +                                            dev_if->dma_out_desc_addr, 1);
44977 +                               if (dev_if->in_desc_addr)
44978 +                                       dwc_otg_ep_free_desc_chain
44979 +                                           (dev_if->in_desc_addr,
44980 +                                            dev_if->dma_in_desc_addr, 1);
44981 +                               if (dev_if->setup_desc_addr[1])
44982 +                                       dwc_otg_ep_free_desc_chain
44983 +                                           (dev_if->setup_desc_addr[1],
44984 +                                            dev_if->dma_setup_desc_addr[1], 1);
44985 +                               if (dev_if->setup_desc_addr[0])
44986 +                                       dwc_otg_ep_free_desc_chain
44987 +                                           (dev_if->setup_desc_addr[0],
44988 +                                            dev_if->dma_setup_desc_addr[0], 1);
44989 +
44990 +                               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
44991 +                                            pcd->setup_pkt,
44992 +                                            pcd->setup_pkt_dma_handle);
44993 +                               DWC_DMA_FREE(sizeof(*pcd->status_buf),
44994 +                                            pcd->status_buf,
44995 +                                            pcd->status_buf_dma_handle);
44996 +
44997 +                               DWC_FREE(pcd);
44998 +
44999 +                               return NULL;
45000 +                       }
45001 +               }
45002 +       } else {
45003 +               pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
45004 +               if (pcd->setup_pkt == NULL) {
45005 +                       DWC_FREE(pcd);
45006 +                       return NULL;
45007 +               }
45008 +
45009 +               pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
45010 +               if (pcd->status_buf == NULL) {
45011 +                       DWC_FREE(pcd->setup_pkt);
45012 +                       DWC_FREE(pcd);
45013 +                       return NULL;
45014 +               }
45015 +       }
45016 +
45017 +       dwc_otg_pcd_reinit(pcd);
45018 +
45019 +       /* Allocate the cfi object for the PCD */
45020 +#ifdef DWC_UTE_CFI
45021 +       pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
45022 +       if (NULL == pcd->cfi)
45023 +               goto fail;
45024 +       if (init_cfi(pcd->cfi)) {
45025 +               CFI_INFO("%s: Failed to init the CFI object\n", __func__);
45026 +               goto fail;
45027 +       }
45028 +#endif
45029 +
45030 +       /* Initialize tasklets */
45031 +       pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
45032 +                                                start_xfer_tasklet_func, pcd);
45033 +       pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
45034 +                                               do_test_mode, pcd);
45035 +
45036 +       /* Initialize SRP timer */
45037 +       core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
45038 +
45039 +       if (core_if->core_params->dev_out_nak) {
45040 +               /**
45041 +               * Initialize xfer timeout timer. Implemented for
45042 +               * 2.93a feature "Device DDMA OUT NAK Enhancement"
45043 +               */
45044 +               for(i = 0; i < MAX_EPS_CHANNELS; i++) {
45045 +                       pcd->core_if->ep_xfer_timer[i] =
45046 +                               DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
45047 +                               &pcd->core_if->ep_xfer_info[i]);
45048 +               }
45049 +       }
45050 +
45051 +       return pcd;
45052 +#ifdef DWC_UTE_CFI
45053 +fail:
45054 +#endif
45055 +       if (pcd->setup_pkt)
45056 +               DWC_FREE(pcd->setup_pkt);
45057 +       if (pcd->status_buf)
45058 +               DWC_FREE(pcd->status_buf);
45059 +#ifdef DWC_UTE_CFI
45060 +       if (pcd->cfi)
45061 +               DWC_FREE(pcd->cfi);
45062 +#endif
45063 +       if (pcd)
45064 +               DWC_FREE(pcd);
45065 +       return NULL;
45066 +
45067 +}
45068 +
45069 +/**
45070 + * Remove PCD specific data
45071 + */
45072 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
45073 +{
45074 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
45075 +       int i;
45076 +       if (pcd->core_if->core_params->dev_out_nak) {
45077 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45078 +                       DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
45079 +                       pcd->core_if->ep_xfer_info[i].state = 0;
45080 +               }
45081 +       }
45082 +
45083 +       if (GET_CORE_IF(pcd)->dma_enable) {
45084 +               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
45085 +                            pcd->setup_pkt_dma_handle);
45086 +               DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
45087 +                            pcd->status_buf_dma_handle);
45088 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
45089 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
45090 +                                                  dev_if->dma_setup_desc_addr
45091 +                                                  [0], 1);
45092 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
45093 +                                                  dev_if->dma_setup_desc_addr
45094 +                                                  [1], 1);
45095 +                       dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
45096 +                                                  dev_if->dma_in_desc_addr, 1);
45097 +                       dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
45098 +                                                  dev_if->dma_out_desc_addr,
45099 +                                                  1);
45100 +               }
45101 +       } else {
45102 +               DWC_FREE(pcd->setup_pkt);
45103 +               DWC_FREE(pcd->status_buf);
45104 +       }
45105 +       DWC_SPINLOCK_FREE(pcd->lock);
45106 +       /* Set core_if's lock pointer to NULL */
45107 +       pcd->core_if->lock = NULL;
45108 +
45109 +       DWC_TASK_FREE(pcd->start_xfer_tasklet);
45110 +       DWC_TASK_FREE(pcd->test_mode_tasklet);
45111 +       if (pcd->core_if->core_params->dev_out_nak) {
45112 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45113 +                       if (pcd->core_if->ep_xfer_timer[i]) {
45114 +                                       DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
45115 +                       }
45116 +               }
45117 +       }
45118 +
45119 +/* Release the CFI object's dynamic memory */
45120 +#ifdef DWC_UTE_CFI
45121 +       if (pcd->cfi->ops.release) {
45122 +               pcd->cfi->ops.release(pcd->cfi);
45123 +       }
45124 +#endif
45125 +
45126 +       DWC_FREE(pcd);
45127 +}
45128 +
45129 +/**
45130 + * Returns whether registered pcd is dual speed or not
45131 + */
45132 +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
45133 +{
45134 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45135 +
45136 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
45137 +           ((core_if->hwcfg2.b.hs_phy_type == 2) &&
45138 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
45139 +            (core_if->core_params->ulpi_fs_ls))) {
45140 +               return 0;
45141 +       }
45142 +
45143 +       return 1;
45144 +}
45145 +
45146 +/**
45147 + * Returns whether registered pcd is OTG capable or not
45148 + */
45149 +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
45150 +{
45151 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45152 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
45153 +
45154 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
45155 +       if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
45156 +               return 0;
45157 +       }
45158 +
45159 +       return 1;
45160 +}
45161 +
45162 +/**
45163 + * This function assigns periodic Tx FIFO to an periodic EP
45164 + * in shared Tx FIFO mode
45165 + */
45166 +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
45167 +{
45168 +       uint32_t TxMsk = 1;
45169 +       int i;
45170 +
45171 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
45172 +               if ((TxMsk & core_if->tx_msk) == 0) {
45173 +                       core_if->tx_msk |= TxMsk;
45174 +                       return i + 1;
45175 +               }
45176 +               TxMsk <<= 1;
45177 +       }
45178 +       return 0;
45179 +}
45180 +
45181 +/**
45182 + * This function assigns periodic Tx FIFO to an periodic EP
45183 + * in shared Tx FIFO mode
45184 + */
45185 +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
45186 +{
45187 +       uint32_t PerTxMsk = 1;
45188 +       int i;
45189 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
45190 +               if ((PerTxMsk & core_if->p_tx_msk) == 0) {
45191 +                       core_if->p_tx_msk |= PerTxMsk;
45192 +                       return i + 1;
45193 +               }
45194 +               PerTxMsk <<= 1;
45195 +       }
45196 +       return 0;
45197 +}
45198 +
45199 +/**
45200 + * This function releases periodic Tx FIFO
45201 + * in shared Tx FIFO mode
45202 + */
45203 +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
45204 +                                 uint32_t fifo_num)
45205 +{
45206 +       core_if->p_tx_msk =
45207 +           (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
45208 +}
45209 +
45210 +/**
45211 + * This function releases periodic Tx FIFO
45212 + * in shared Tx FIFO mode
45213 + */
45214 +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
45215 +{
45216 +       core_if->tx_msk =
45217 +           (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
45218 +}
45219 +
45220 +/**
45221 + * This function is being called from gadget
45222 + * to enable PCD endpoint.
45223 + */
45224 +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
45225 +                         const uint8_t * ep_desc, void *usb_ep)
45226 +{
45227 +       int num, dir;
45228 +       dwc_otg_pcd_ep_t *ep = NULL;
45229 +       const usb_endpoint_descriptor_t *desc;
45230 +       dwc_irqflags_t flags;
45231 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45232 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45233 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45234 +       int retval = 0;
45235 +       int i, epcount;
45236 +
45237 +       desc = (const usb_endpoint_descriptor_t *)ep_desc;
45238 +
45239 +       if (!desc) {
45240 +               pcd->ep0.priv = usb_ep;
45241 +               ep = &pcd->ep0;
45242 +               retval = -DWC_E_INVALID;
45243 +               goto out;
45244 +       }
45245 +
45246 +       num = UE_GET_ADDR(desc->bEndpointAddress);
45247 +       dir = UE_GET_DIR(desc->bEndpointAddress);
45248 +
45249 +       if (!desc->wMaxPacketSize) {
45250 +               DWC_WARN("bad maxpacketsize\n");
45251 +               retval = -DWC_E_INVALID;
45252 +               goto out;
45253 +       }
45254 +
45255 +       if (dir == UE_DIR_IN) {
45256 +               epcount = pcd->core_if->dev_if->num_in_eps;
45257 +               for (i = 0; i < epcount; i++) {
45258 +                       if (num == pcd->in_ep[i].dwc_ep.num) {
45259 +                               ep = &pcd->in_ep[i];
45260 +                               break;
45261 +                       }
45262 +               }
45263 +       } else {
45264 +               epcount = pcd->core_if->dev_if->num_out_eps;
45265 +               for (i = 0; i < epcount; i++) {
45266 +                       if (num == pcd->out_ep[i].dwc_ep.num) {
45267 +                               ep = &pcd->out_ep[i];
45268 +                               break;
45269 +                       }
45270 +               }
45271 +       }
45272 +
45273 +       if (!ep) {
45274 +               DWC_WARN("bad address\n");
45275 +               retval = -DWC_E_INVALID;
45276 +               goto out;
45277 +       }
45278 +
45279 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45280 +
45281 +       ep->desc = desc;
45282 +       ep->priv = usb_ep;
45283 +
45284 +       /*
45285 +        * Activate the EP
45286 +        */
45287 +       ep->stopped = 0;
45288 +
45289 +       ep->dwc_ep.is_in = (dir == UE_DIR_IN);
45290 +       ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
45291 +
45292 +       ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
45293 +
45294 +       if (ep->dwc_ep.is_in) {
45295 +               if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45296 +                       ep->dwc_ep.tx_fifo_num = 0;
45297 +
45298 +                       if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
45299 +                               /*
45300 +                                * if ISOC EP then assign a Periodic Tx FIFO.
45301 +                                */
45302 +                               ep->dwc_ep.tx_fifo_num =
45303 +                                   assign_perio_tx_fifo(GET_CORE_IF(pcd));
45304 +                       }
45305 +               } else {
45306 +                       /*
45307 +                        * if Dedicated FIFOs mode is on then assign a Tx FIFO.
45308 +                        */
45309 +                       ep->dwc_ep.tx_fifo_num =
45310 +                           assign_tx_fifo(GET_CORE_IF(pcd));
45311 +               }
45312 +
45313 +               /* Calculating EP info controller base address */
45314 +               if (ep->dwc_ep.tx_fifo_num
45315 +                   && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45316 +                       gdfifocfg.d32 =
45317 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
45318 +                                          core_global_regs->gdfifocfg);
45319 +                       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45320 +                       dptxfsiz.d32 =
45321 +                           (DWC_READ_REG32
45322 +                            (&GET_CORE_IF(pcd)->core_global_regs->
45323 +                             dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);
45324 +                       gdfifocfg.b.epinfobase =
45325 +                           gdfifocfgbase.d32 + dptxfsiz.d32;
45326 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45327 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45328 +                                               core_global_regs->gdfifocfg,
45329 +                                               gdfifocfg.d32);
45330 +                       }
45331 +               }
45332 +       }
45333 +       /* Set initial data PID. */
45334 +       if (ep->dwc_ep.type == UE_BULK) {
45335 +               ep->dwc_ep.data_pid_start = 0;
45336 +       }
45337 +
45338 +       /* Alloc DMA Descriptors */
45339 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45340 +#ifndef DWC_UTE_PER_IO
45341 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45342 +#endif
45343 +                       ep->dwc_ep.desc_addr =
45344 +                           dwc_otg_ep_alloc_desc_chain(&ep->
45345 +                                                       dwc_ep.dma_desc_addr,
45346 +                                                       MAX_DMA_DESC_CNT);
45347 +                       if (!ep->dwc_ep.desc_addr) {
45348 +                               DWC_WARN("%s, can't allocate DMA descriptor\n",
45349 +                                        __func__);
45350 +                               retval = -DWC_E_SHUTDOWN;
45351 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45352 +                               goto out;
45353 +                       }
45354 +#ifndef DWC_UTE_PER_IO
45355 +               }
45356 +#endif
45357 +       }
45358 +
45359 +       DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
45360 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"),
45361 +                   ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
45362 +#ifdef DWC_UTE_PER_IO
45363 +       ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
45364 +#endif
45365 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45366 +               ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
45367 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
45368 +       }
45369 +
45370 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
45371 +
45372 +#ifdef DWC_UTE_CFI
45373 +       if (pcd->cfi->ops.ep_enable) {
45374 +               pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
45375 +       }
45376 +#endif
45377 +
45378 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45379 +
45380 +out:
45381 +       return retval;
45382 +}
45383 +
45384 +/**
45385 + * This function is being called from gadget
45386 + * to disable PCD endpoint.
45387 + */
45388 +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
45389 +{
45390 +       dwc_otg_pcd_ep_t *ep;
45391 +       dwc_irqflags_t flags;
45392 +       dwc_otg_dev_dma_desc_t *desc_addr;
45393 +       dwc_dma_t dma_desc_addr;
45394 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45395 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45396 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45397 +
45398 +       ep = get_ep_from_handle(pcd, ep_handle);
45399 +
45400 +       if (!ep || !ep->desc) {
45401 +               DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
45402 +               return -DWC_E_INVALID;
45403 +       }
45404 +
45405 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45406 +
45407 +       dwc_otg_request_nuke(ep);
45408 +
45409 +       dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
45410 +       if (pcd->core_if->core_params->dev_out_nak) {
45411 +               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
45412 +               pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
45413 +       }
45414 +       ep->desc = NULL;
45415 +       ep->stopped = 1;
45416 +
45417 +       gdfifocfg.d32 =
45418 +           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
45419 +       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45420 +
45421 +       if (ep->dwc_ep.is_in) {
45422 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45423 +                       /* Flush the Tx FIFO */
45424 +                       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),
45425 +                                             ep->dwc_ep.tx_fifo_num);
45426 +               }
45427 +               release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45428 +               release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45429 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45430 +                       /* Decreasing EPinfo Base Addr */
45431 +                       dptxfsiz.d32 =
45432 +                           (DWC_READ_REG32
45433 +                            (&GET_CORE_IF(pcd)->
45434 +                               core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
45435 +                       gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
45436 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45437 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
45438 +                                       gdfifocfg.d32);
45439 +                       }
45440 +               }
45441 +       }
45442 +
45443 +       /* Free DMA Descriptors */
45444 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45445 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45446 +                       desc_addr = ep->dwc_ep.desc_addr;
45447 +                       dma_desc_addr = ep->dwc_ep.dma_desc_addr;
45448 +
45449 +                       /* Cannot call dma_free_coherent() with IRQs disabled */
45450 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45451 +                       dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
45452 +                                                  MAX_DMA_DESC_CNT);
45453 +
45454 +                       goto out_unlocked;
45455 +               }
45456 +       }
45457 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45458 +
45459 +out_unlocked:
45460 +       DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
45461 +                   ep->dwc_ep.is_in ? "IN" : "OUT");
45462 +       return 0;
45463 +
45464 +}
45465 +
45466 +/******************************************************************************/
45467 +#ifdef DWC_UTE_PER_IO
45468 +
45469 +/**
45470 + * Free the request and its extended parts
45471 + *
45472 + */
45473 +void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
45474 +{
45475 +       DWC_FREE(req->ext_req.per_io_frame_descs);
45476 +       DWC_FREE(req);
45477 +}
45478 +
45479 +/**
45480 + * Start the next request in the endpoint's queue.
45481 + *
45482 + */
45483 +int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
45484 +                                       dwc_otg_pcd_ep_t * ep)
45485 +{
45486 +       int i;
45487 +       dwc_otg_pcd_request_t *req = NULL;
45488 +       dwc_ep_t *dwcep = NULL;
45489 +       struct dwc_iso_xreq_port *ereq = NULL;
45490 +       struct dwc_iso_pkt_desc_port *ddesc_iso;
45491 +       uint16_t nat;
45492 +       depctl_data_t diepctl;
45493 +
45494 +       dwcep = &ep->dwc_ep;
45495 +
45496 +       if (dwcep->xiso_active_xfers > 0) {
45497 +#if 0  //Disable this to decrease s/w overhead that is crucial for Isoc transfers
45498 +               DWC_WARN("There are currently active transfers for EP%d \
45499 +                               (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers,
45500 +                               dwcep->xiso_queued_xfers);
45501 +#endif
45502 +               return 0;
45503 +       }
45504 +
45505 +       nat = UGETW(ep->desc->wMaxPacketSize);
45506 +       nat = (nat >> 11) & 0x03;
45507 +
45508 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45509 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45510 +               ereq = &req->ext_req;
45511 +               ep->stopped = 0;
45512 +
45513 +               /* Get the frame number */
45514 +               dwcep->xiso_frame_num =
45515 +                   dwc_otg_get_frame_number(GET_CORE_IF(pcd));
45516 +               DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
45517 +
45518 +               ddesc_iso = ereq->per_io_frame_descs;
45519 +
45520 +               if (dwcep->is_in) {
45521 +                       /* Setup DMA Descriptor chain for IN Isoc request */
45522 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45523 +                               //if ((i % (nat + 1)) == 0)
45524 +                               if ( i > 0 )
45525 +                                       dwcep->xiso_frame_num =
45526 +                                           (dwcep->xiso_bInterval +
45527 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45528 +                               dwcep->desc_addr[i].buf =
45529 +                                   req->dma + ddesc_iso[i].offset;
45530 +                               dwcep->desc_addr[i].status.b_iso_in.txbytes =
45531 +                                   ddesc_iso[i].length;
45532 +                               dwcep->desc_addr[i].status.b_iso_in.framenum =
45533 +                                   dwcep->xiso_frame_num;
45534 +                               dwcep->desc_addr[i].status.b_iso_in.bs =
45535 +                                   BS_HOST_READY;
45536 +                               dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
45537 +                               dwcep->desc_addr[i].status.b_iso_in.sp =
45538 +                                   (ddesc_iso[i].length %
45539 +                                    dwcep->maxpacket) ? 1 : 0;
45540 +                               dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
45541 +                               dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
45542 +                               dwcep->desc_addr[i].status.b_iso_in.l = 0;
45543 +
45544 +                               /* Process the last descriptor */
45545 +                               if (i == ereq->pio_pkt_count - 1) {
45546 +                                       dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
45547 +                                       dwcep->desc_addr[i].status.b_iso_in.l = 1;
45548 +                               }
45549 +                       }
45550 +
45551 +                       /* Setup and start the transfer for this endpoint */
45552 +                       dwcep->xiso_active_xfers++;
45553 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
45554 +                                       in_ep_regs[dwcep->num]->diepdma,
45555 +                                       dwcep->dma_desc_addr);
45556 +                       diepctl.d32 = 0;
45557 +                       diepctl.b.epena = 1;
45558 +                       diepctl.b.cnak = 1;
45559 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
45560 +                                        in_ep_regs[dwcep->num]->diepctl, 0,
45561 +                                        diepctl.d32);
45562 +               } else {
45563 +                       /* Setup DMA Descriptor chain for OUT Isoc request */
45564 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45565 +                               //if ((i % (nat + 1)) == 0)
45566 +                               dwcep->xiso_frame_num = (dwcep->xiso_bInterval +
45567 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45568 +                               dwcep->desc_addr[i].buf =
45569 +                                   req->dma + ddesc_iso[i].offset;
45570 +                               dwcep->desc_addr[i].status.b_iso_out.rxbytes =
45571 +                                   ddesc_iso[i].length;
45572 +                               dwcep->desc_addr[i].status.b_iso_out.framenum =
45573 +                                   dwcep->xiso_frame_num;
45574 +                               dwcep->desc_addr[i].status.b_iso_out.bs =
45575 +                                   BS_HOST_READY;
45576 +                               dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
45577 +                               dwcep->desc_addr[i].status.b_iso_out.sp =
45578 +                                   (ddesc_iso[i].length %
45579 +                                    dwcep->maxpacket) ? 1 : 0;
45580 +                               dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
45581 +                               dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
45582 +                               dwcep->desc_addr[i].status.b_iso_out.l = 0;
45583 +
45584 +                               /* Process the last descriptor */
45585 +                               if (i == ereq->pio_pkt_count - 1) {
45586 +                                       dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
45587 +                                       dwcep->desc_addr[i].status.b_iso_out.l = 1;
45588 +                               }
45589 +                       }
45590 +
45591 +                       /* Setup and start the transfer for this endpoint */
45592 +                       dwcep->xiso_active_xfers++;
45593 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45594 +                                       dev_if->out_ep_regs[dwcep->num]->
45595 +                                       doepdma, dwcep->dma_desc_addr);
45596 +                       diepctl.d32 = 0;
45597 +                       diepctl.b.epena = 1;
45598 +                       diepctl.b.cnak = 1;
45599 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
45600 +                                        dev_if->out_ep_regs[dwcep->num]->
45601 +                                        doepctl, 0, diepctl.d32);
45602 +               }
45603 +
45604 +       } else {
45605 +               ep->stopped = 1;
45606 +       }
45607 +
45608 +       return 0;
45609 +}
45610 +
45611 +/**
45612 + *     - Remove the request from the queue
45613 + */
45614 +void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
45615 +{
45616 +       dwc_otg_pcd_request_t *req = NULL;
45617 +       struct dwc_iso_xreq_port *ereq = NULL;
45618 +       struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
45619 +       dwc_ep_t *dwcep = NULL;
45620 +       int i;
45621 +
45622 +       //DWC_DEBUG();
45623 +       dwcep = &ep->dwc_ep;
45624 +
45625 +       /* Get the first pending request from the queue */
45626 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45627 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45628 +               if (!req) {
45629 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
45630 +                       return;
45631 +               }
45632 +               dwcep->xiso_active_xfers--;
45633 +               dwcep->xiso_queued_xfers--;
45634 +               /* Remove this request from the queue */
45635 +               DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
45636 +       } else {
45637 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
45638 +               return;
45639 +       }
45640 +
45641 +       ep->stopped = 1;
45642 +       ereq = &req->ext_req;
45643 +       ddesc_iso = ereq->per_io_frame_descs;
45644 +
45645 +       if (dwcep->xiso_active_xfers < 0) {
45646 +               DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
45647 +                        dwcep->xiso_active_xfers);
45648 +       }
45649 +
45650 +       /* Fill the Isoc descs of portable extended req from dma descriptors */
45651 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45652 +               if (dwcep->is_in) {     /* IN endpoints */
45653 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45654 +                           dwcep->desc_addr[i].status.b_iso_in.txbytes;
45655 +                       ddesc_iso[i].status =
45656 +                           dwcep->desc_addr[i].status.b_iso_in.txsts;
45657 +               } else {        /* OUT endpoints */
45658 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45659 +                           dwcep->desc_addr[i].status.b_iso_out.rxbytes;
45660 +                       ddesc_iso[i].status =
45661 +                           dwcep->desc_addr[i].status.b_iso_out.rxsts;
45662 +               }
45663 +       }
45664 +
45665 +       DWC_SPINUNLOCK(ep->pcd->lock);
45666 +
45667 +       /* Call the completion function in the non-portable logic */
45668 +       ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
45669 +                                     &req->ext_req);
45670 +
45671 +       DWC_SPINLOCK(ep->pcd->lock);
45672 +
45673 +       /* Free the request - specific freeing needed for extended request object */
45674 +       dwc_pcd_xiso_ereq_free(ep, req);
45675 +
45676 +       /* Start the next request */
45677 +       dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
45678 +
45679 +       return;
45680 +}
45681 +
45682 +/**
45683 + * Create and initialize the Isoc pkt descriptors of the extended request.
45684 + *
45685 + */
45686 +static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
45687 +                                            void *ereq_nonport,
45688 +                                            int atomic_alloc)
45689 +{
45690 +       struct dwc_iso_xreq_port *ereq = NULL;
45691 +       struct dwc_iso_xreq_port *req_mapped = NULL;
45692 +       struct dwc_iso_pkt_desc_port *ipds = NULL;      /* To be created in this function */
45693 +       uint32_t pkt_count;
45694 +       int i;
45695 +
45696 +       ereq = &req->ext_req;
45697 +       req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
45698 +       pkt_count = req_mapped->pio_pkt_count;
45699 +
45700 +       /* Create the isoc descs */
45701 +       if (atomic_alloc) {
45702 +               ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
45703 +       } else {
45704 +               ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
45705 +       }
45706 +
45707 +       if (!ipds) {
45708 +               DWC_ERROR("Failed to allocate isoc descriptors");
45709 +               return -DWC_E_NO_MEMORY;
45710 +       }
45711 +
45712 +       /* Initialize the extended request fields */
45713 +       ereq->per_io_frame_descs = ipds;
45714 +       ereq->error_count = 0;
45715 +       ereq->pio_alloc_pkt_count = pkt_count;
45716 +       ereq->pio_pkt_count = pkt_count;
45717 +       ereq->tr_sub_flags = req_mapped->tr_sub_flags;
45718 +
45719 +       /* Init the Isoc descriptors */
45720 +       for (i = 0; i < pkt_count; i++) {
45721 +               ipds[i].length = req_mapped->per_io_frame_descs[i].length;
45722 +               ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
45723 +               ipds[i].status = req_mapped->per_io_frame_descs[i].status;      /* 0 */
45724 +               ipds[i].actual_length =
45725 +                   req_mapped->per_io_frame_descs[i].actual_length;
45726 +       }
45727 +
45728 +       return 0;
45729 +}
45730 +
45731 +static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
45732 +{
45733 +       struct dwc_iso_pkt_desc_port *xfd = NULL;
45734 +       int i;
45735 +
45736 +       DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
45737 +       DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
45738 +       DWC_DEBUG("error_count=%d", ereq->error_count);
45739 +       DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
45740 +       DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
45741 +       DWC_DEBUG("res=%d", ereq->res);
45742 +
45743 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45744 +               xfd = &ereq->per_io_frame_descs[0];
45745 +               DWC_DEBUG("FD #%d", i);
45746 +
45747 +               DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
45748 +               DWC_DEBUG("xfd->length=%d", xfd->length);
45749 +               DWC_DEBUG("xfd->offset=%d", xfd->offset);
45750 +               DWC_DEBUG("xfd->status=%d", xfd->status);
45751 +       }
45752 +}
45753 +
45754 +/**
45755 + *
45756 + */
45757 +int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
45758 +                             uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
45759 +                             int zero, void *req_handle, int atomic_alloc,
45760 +                             void *ereq_nonport)
45761 +{
45762 +       dwc_otg_pcd_request_t *req = NULL;
45763 +       dwc_otg_pcd_ep_t *ep;
45764 +       dwc_irqflags_t flags;
45765 +       int res;
45766 +
45767 +       ep = get_ep_from_handle(pcd, ep_handle);
45768 +       if (!ep) {
45769 +               DWC_WARN("bad ep\n");
45770 +               return -DWC_E_INVALID;
45771 +       }
45772 +
45773 +       /* We support this extension only for DDMA mode */
45774 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
45775 +               if (!GET_CORE_IF(pcd)->dma_desc_enable)
45776 +                       return -DWC_E_INVALID;
45777 +
45778 +       /* Create a dwc_otg_pcd_request_t object */
45779 +       if (atomic_alloc) {
45780 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
45781 +       } else {
45782 +               req = DWC_ALLOC(sizeof(*req));
45783 +       }
45784 +
45785 +       if (!req) {
45786 +               return -DWC_E_NO_MEMORY;
45787 +       }
45788 +
45789 +       /* Create the Isoc descs for this request which shall be the exact match
45790 +        * of the structure sent to us from the non-portable logic */
45791 +       res =
45792 +           dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
45793 +       if (res) {
45794 +               DWC_WARN("Failed to init the Isoc descriptors");
45795 +               DWC_FREE(req);
45796 +               return res;
45797 +       }
45798 +
45799 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45800 +
45801 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
45802 +       req->buf = buf;
45803 +       req->dma = dma_buf;
45804 +       req->length = buflen;
45805 +       req->sent_zlp = zero;
45806 +       req->priv = req_handle;
45807 +
45808 +       //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45809 +       ep->dwc_ep.dma_addr = dma_buf;
45810 +       ep->dwc_ep.start_xfer_buff = buf;
45811 +       ep->dwc_ep.xfer_buff = buf;
45812 +       ep->dwc_ep.xfer_len = 0;
45813 +       ep->dwc_ep.xfer_count = 0;
45814 +       ep->dwc_ep.sent_zlp = 0;
45815 +       ep->dwc_ep.total_len = buflen;
45816 +
45817 +       /* Add this request to the tail */
45818 +       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
45819 +       ep->dwc_ep.xiso_queued_xfers++;
45820 +
45821 +//DWC_DEBUG("CP_0");
45822 +//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
45823 +//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
45824 +//prn_ext_request(&req->ext_req);
45825 +
45826 +       //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45827 +
45828 +       /* If the req->status == ASAP  then check if there is any active transfer
45829 +        * for this endpoint. If no active transfers, then get the first entry
45830 +        * from the queue and start that transfer
45831 +        */
45832 +       if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
45833 +               res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
45834 +               if (res) {
45835 +                       DWC_WARN("Failed to start the next Isoc transfer");
45836 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45837 +                       DWC_FREE(req);
45838 +                       return res;
45839 +               }
45840 +       }
45841 +
45842 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45843 +       return 0;
45844 +}
45845 +
45846 +#endif
45847 +/* END ifdef DWC_UTE_PER_IO ***************************************************/
45848 +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
45849 +                        uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
45850 +                        int zero, void *req_handle, int atomic_alloc)
45851 +{
45852 +       dwc_irqflags_t flags;
45853 +       dwc_otg_pcd_request_t *req;
45854 +       dwc_otg_pcd_ep_t *ep;
45855 +       uint32_t max_transfer;
45856 +
45857 +       ep = get_ep_from_handle(pcd, ep_handle);
45858 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
45859 +               DWC_WARN("bad ep\n");
45860 +               return -DWC_E_INVALID;
45861 +       }
45862 +
45863 +       if (atomic_alloc) {
45864 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
45865 +       } else {
45866 +               req = DWC_ALLOC(sizeof(*req));
45867 +       }
45868 +
45869 +       if (!req) {
45870 +               return -DWC_E_NO_MEMORY;
45871 +       }
45872 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
45873 +       if (!GET_CORE_IF(pcd)->core_params->opt) {
45874 +               if (ep->dwc_ep.num != 0) {
45875 +                       DWC_ERROR("queue req %p, len %d buf %p\n",
45876 +                                 req_handle, buflen, buf);
45877 +               }
45878 +       }
45879 +
45880 +       req->buf = buf;
45881 +       req->dma = dma_buf;
45882 +       req->length = buflen;
45883 +       req->sent_zlp = zero;
45884 +       req->priv = req_handle;
45885 +       req->dw_align_buf = NULL;
45886 +       if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
45887 +                       && !GET_CORE_IF(pcd)->dma_desc_enable)
45888 +               req->dw_align_buf = DWC_DMA_ALLOC(buflen,
45889 +                                &req->dw_align_buf_dma);
45890 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45891 +
45892 +       /*
45893 +        * After adding request to the queue for IN ISOC wait for In Token Received
45894 +        * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token
45895 +        * Received when EP is disabled interrupt to obtain starting microframe
45896 +        * (odd/even) start transfer
45897 +        */
45898 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45899 +               if (req != 0) {
45900 +                       depctl_data_t depctl = {.d32 =
45901 +                                   DWC_READ_REG32(&pcd->core_if->dev_if->
45902 +                                                  in_ep_regs[ep->dwc_ep.num]->
45903 +                                                  diepctl) };
45904 +                       ++pcd->request_pending;
45905 +
45906 +                       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
45907 +                       if (ep->dwc_ep.is_in) {
45908 +                               depctl.b.cnak = 1;
45909 +                               DWC_WRITE_REG32(&pcd->core_if->dev_if->
45910 +                                               in_ep_regs[ep->dwc_ep.num]->
45911 +                                               diepctl, depctl.d32);
45912 +                       }
45913 +
45914 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45915 +               }
45916 +               return 0;
45917 +       }
45918 +
45919 +       /*
45920 +        * For EP0 IN without premature status, zlp is required?
45921 +        */
45922 +       if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
45923 +               DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
45924 +               //_req->zero = 1;
45925 +       }
45926 +
45927 +       /* Start the transfer */
45928 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
45929 +               /* EP0 Transfer? */
45930 +               if (ep->dwc_ep.num == 0) {
45931 +                       switch (pcd->ep0state) {
45932 +                       case EP0_IN_DATA_PHASE:
45933 +                               DWC_DEBUGPL(DBG_PCD,
45934 +                                           "%s ep0: EP0_IN_DATA_PHASE\n",
45935 +                                           __func__);
45936 +                               break;
45937 +
45938 +                       case EP0_OUT_DATA_PHASE:
45939 +                               DWC_DEBUGPL(DBG_PCD,
45940 +                                           "%s ep0: EP0_OUT_DATA_PHASE\n",
45941 +                                           __func__);
45942 +                               if (pcd->request_config) {
45943 +                                       /* Complete STATUS PHASE */
45944 +                                       ep->dwc_ep.is_in = 1;
45945 +                                       pcd->ep0state = EP0_IN_STATUS_PHASE;
45946 +                               }
45947 +                               break;
45948 +
45949 +                       case EP0_IN_STATUS_PHASE:
45950 +                               DWC_DEBUGPL(DBG_PCD,
45951 +                                           "%s ep0: EP0_IN_STATUS_PHASE\n",
45952 +                                           __func__);
45953 +                               break;
45954 +
45955 +                       default:
45956 +                               DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
45957 +                                           pcd->ep0state);
45958 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45959 +                               return -DWC_E_SHUTDOWN;
45960 +                       }
45961 +
45962 +                       ep->dwc_ep.dma_addr = dma_buf;
45963 +                       ep->dwc_ep.start_xfer_buff = buf;
45964 +                       ep->dwc_ep.xfer_buff = buf;
45965 +                       ep->dwc_ep.xfer_len = buflen;
45966 +                       ep->dwc_ep.xfer_count = 0;
45967 +                       ep->dwc_ep.sent_zlp = 0;
45968 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
45969 +
45970 +                       if (zero) {
45971 +                               if ((ep->dwc_ep.xfer_len %
45972 +                                    ep->dwc_ep.maxpacket == 0)
45973 +                                   && (ep->dwc_ep.xfer_len != 0)) {
45974 +                                       ep->dwc_ep.sent_zlp = 1;
45975 +                               }
45976 +
45977 +                       }
45978 +
45979 +                       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
45980 +                                                  &ep->dwc_ep);
45981 +               }               // non-ep0 endpoints
45982 +               else {
45983 +#ifdef DWC_UTE_CFI
45984 +                       if (ep->dwc_ep.buff_mode != BM_STANDARD) {
45985 +                               /* store the request length */
45986 +                               ep->dwc_ep.cfi_req_len = buflen;
45987 +                               pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
45988 +                                                               ep, req);
45989 +                       } else {
45990 +#endif
45991 +                               max_transfer =
45992 +                                   GET_CORE_IF(ep->pcd)->core_params->
45993 +                                   max_transfer_size;
45994 +
45995 +                               /* Setup and start the Transfer */
45996 +                               if (req->dw_align_buf){
45997 +                                       if (ep->dwc_ep.is_in)
45998 +                                               dwc_memcpy(req->dw_align_buf,
45999 +                                                          buf, buflen);
46000 +                                       ep->dwc_ep.dma_addr =
46001 +                                           req->dw_align_buf_dma;
46002 +                                       ep->dwc_ep.start_xfer_buff =
46003 +                                           req->dw_align_buf;
46004 +                                       ep->dwc_ep.xfer_buff =
46005 +                                           req->dw_align_buf;
46006 +                               } else {
46007 +                                       ep->dwc_ep.dma_addr = dma_buf;
46008 +                                       ep->dwc_ep.start_xfer_buff = buf;
46009 +                                        ep->dwc_ep.xfer_buff = buf;
46010 +                               }
46011 +                               ep->dwc_ep.xfer_len = 0;
46012 +                               ep->dwc_ep.xfer_count = 0;
46013 +                               ep->dwc_ep.sent_zlp = 0;
46014 +                               ep->dwc_ep.total_len = buflen;
46015 +
46016 +                               ep->dwc_ep.maxxfer = max_transfer;
46017 +                               if (GET_CORE_IF(pcd)->dma_desc_enable) {
46018 +                                       uint32_t out_max_xfer =
46019 +                                           DDMA_MAX_TRANSFER_SIZE -
46020 +                                           (DDMA_MAX_TRANSFER_SIZE % 4);
46021 +                                       if (ep->dwc_ep.is_in) {
46022 +                                               if (ep->dwc_ep.maxxfer >
46023 +                                                   DDMA_MAX_TRANSFER_SIZE) {
46024 +                                                       ep->dwc_ep.maxxfer =
46025 +                                                           DDMA_MAX_TRANSFER_SIZE;
46026 +                                               }
46027 +                                       } else {
46028 +                                               if (ep->dwc_ep.maxxfer >
46029 +                                                   out_max_xfer) {
46030 +                                                       ep->dwc_ep.maxxfer =
46031 +                                                           out_max_xfer;
46032 +                                               }
46033 +                                       }
46034 +                               }
46035 +                               if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
46036 +                                       ep->dwc_ep.maxxfer -=
46037 +                                           (ep->dwc_ep.maxxfer %
46038 +                                            ep->dwc_ep.maxpacket);
46039 +                               }
46040 +
46041 +                               if (zero) {
46042 +                                       if ((ep->dwc_ep.total_len %
46043 +                                            ep->dwc_ep.maxpacket == 0)
46044 +                                           && (ep->dwc_ep.total_len != 0)) {
46045 +                                               ep->dwc_ep.sent_zlp = 1;
46046 +                                       }
46047 +                               }
46048 +#ifdef DWC_UTE_CFI
46049 +                       }
46050 +#endif
46051 +                       dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
46052 +                                                 &ep->dwc_ep);
46053 +               }
46054 +       }
46055 +
46056 +       if (req != 0) {
46057 +               ++pcd->request_pending;
46058 +               DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46059 +               if (ep->dwc_ep.is_in && ep->stopped
46060 +                   && !(GET_CORE_IF(pcd)->dma_enable)) {
46061 +                       /** @todo NGS Create a function for this. */
46062 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
46063 +                       diepmsk.b.intktxfemp = 1;
46064 +                       if (GET_CORE_IF(pcd)->multiproc_int_enable) {
46065 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46066 +                                                dev_if->dev_global_regs->diepeachintmsk
46067 +                                                [ep->dwc_ep.num], 0,
46068 +                                                diepmsk.d32);
46069 +                       } else {
46070 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46071 +                                                dev_if->dev_global_regs->
46072 +                                                diepmsk, 0, diepmsk.d32);
46073 +                       }
46074 +
46075 +               }
46076 +       }
46077 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46078 +
46079 +       return 0;
46080 +}
46081 +
46082 +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
46083 +                          void *req_handle)
46084 +{
46085 +       dwc_irqflags_t flags;
46086 +       dwc_otg_pcd_request_t *req;
46087 +       dwc_otg_pcd_ep_t *ep;
46088 +
46089 +       ep = get_ep_from_handle(pcd, ep_handle);
46090 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46091 +               DWC_WARN("bad argument\n");
46092 +               return -DWC_E_INVALID;
46093 +       }
46094 +
46095 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46096 +
46097 +       /* make sure it's actually queued on this endpoint */
46098 +       DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
46099 +               if (req->priv == (void *)req_handle) {
46100 +                       break;
46101 +               }
46102 +       }
46103 +
46104 +       if (req->priv != (void *)req_handle) {
46105 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46106 +               return -DWC_E_INVALID;
46107 +       }
46108 +
46109 +       if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
46110 +               dwc_otg_request_done(ep, req, -DWC_E_RESTART);
46111 +       } else {
46112 +               req = NULL;
46113 +       }
46114 +
46115 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46116 +
46117 +       return req ? 0 : -DWC_E_SHUTDOWN;
46118 +
46119 +}
46120 +
46121 +/**
46122 + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
46123 + *
46124 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
46125 + * requests. If the gadget driver clears the halt status, it will
46126 + * automatically unwedge the endpoint.
46127 + *
46128 + * Returns zero on success, else negative DWC error code.
46129 + */
46130 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
46131 +{
46132 +       dwc_otg_pcd_ep_t *ep;
46133 +       dwc_irqflags_t flags;
46134 +       int retval = 0;
46135 +
46136 +       ep = get_ep_from_handle(pcd, ep_handle);
46137 +
46138 +       if ((!ep->desc && ep != &pcd->ep0) ||
46139 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46140 +               DWC_WARN("%s, bad ep\n", __func__);
46141 +               return -DWC_E_INVALID;
46142 +       }
46143 +
46144 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46145 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46146 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46147 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46148 +               retval = -DWC_E_AGAIN;
46149 +       } else {
46150 +                /* This code needs to be reviewed */
46151 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46152 +                       dtxfsts_data_t txstatus;
46153 +                       fifosize_data_t txfifosize;
46154 +
46155 +                       txfifosize.d32 =
46156 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46157 +                                          core_global_regs->dtxfsiz[ep->dwc_ep.
46158 +                                                                    tx_fifo_num]);
46159 +                       txstatus.d32 =
46160 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46161 +                                          dev_if->in_ep_regs[ep->dwc_ep.num]->
46162 +                                          dtxfsts);
46163 +
46164 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46165 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46166 +                               retval = -DWC_E_AGAIN;
46167 +                       } else {
46168 +                               if (ep->dwc_ep.num == 0) {
46169 +                                       pcd->ep0state = EP0_STALL;
46170 +                               }
46171 +
46172 +                               ep->stopped = 1;
46173 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46174 +                                                    &ep->dwc_ep);
46175 +                       }
46176 +               } else {
46177 +                       if (ep->dwc_ep.num == 0) {
46178 +                               pcd->ep0state = EP0_STALL;
46179 +                       }
46180 +
46181 +                       ep->stopped = 1;
46182 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46183 +               }
46184 +       }
46185 +
46186 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46187 +
46188 +       return retval;
46189 +}
46190 +
46191 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
46192 +{
46193 +       dwc_otg_pcd_ep_t *ep;
46194 +       dwc_irqflags_t flags;
46195 +       int retval = 0;
46196 +
46197 +       ep = get_ep_from_handle(pcd, ep_handle);
46198 +
46199 +       if (!ep || (!ep->desc && ep != &pcd->ep0) ||
46200 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46201 +               DWC_WARN("%s, bad ep\n", __func__);
46202 +               return -DWC_E_INVALID;
46203 +       }
46204 +
46205 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46206 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46207 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46208 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46209 +               retval = -DWC_E_AGAIN;
46210 +       } else if (value == 0) {
46211 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46212 +       } else if (value == 1) {
46213 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46214 +                       dtxfsts_data_t txstatus;
46215 +                       fifosize_data_t txfifosize;
46216 +
46217 +                       txfifosize.d32 =
46218 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
46219 +                                          dtxfsiz[ep->dwc_ep.tx_fifo_num]);
46220 +                       txstatus.d32 =
46221 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
46222 +                                          in_ep_regs[ep->dwc_ep.num]->dtxfsts);
46223 +
46224 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46225 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46226 +                               retval = -DWC_E_AGAIN;
46227 +                       } else {
46228 +                               if (ep->dwc_ep.num == 0) {
46229 +                                       pcd->ep0state = EP0_STALL;
46230 +                               }
46231 +
46232 +                               ep->stopped = 1;
46233 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46234 +                                                    &ep->dwc_ep);
46235 +                       }
46236 +               } else {
46237 +                       if (ep->dwc_ep.num == 0) {
46238 +                               pcd->ep0state = EP0_STALL;
46239 +                       }
46240 +
46241 +                       ep->stopped = 1;
46242 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46243 +               }
46244 +       } else if (value == 2) {
46245 +               ep->dwc_ep.stall_clear_flag = 0;
46246 +       } else if (value == 3) {
46247 +               ep->dwc_ep.stall_clear_flag = 1;
46248 +       }
46249 +
46250 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46251 +
46252 +       return retval;
46253 +}
46254 +
46255 +/**
46256 + * This function initiates remote wakeup of the host from suspend state.
46257 + */
46258 +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
46259 +{
46260 +       dctl_data_t dctl = { 0 };
46261 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46262 +       dsts_data_t dsts;
46263 +
46264 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
46265 +       if (!dsts.b.suspsts) {
46266 +               DWC_WARN("Remote wakeup while is not in suspend state\n");
46267 +       }
46268 +       /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
46269 +       if (pcd->remote_wakeup_enable) {
46270 +               if (set) {
46271 +
46272 +                       if (core_if->adp_enable) {
46273 +                               gpwrdn_data_t gpwrdn;
46274 +
46275 +                               dwc_otg_adp_probe_stop(core_if);
46276 +
46277 +                               /* Mask SRP detected interrupt from Power Down Logic */
46278 +                               gpwrdn.d32 = 0;
46279 +                               gpwrdn.b.srp_det_msk = 1;
46280 +                               DWC_MODIFY_REG32(&core_if->
46281 +                                                core_global_regs->gpwrdn,
46282 +                                                gpwrdn.d32, 0);
46283 +
46284 +                               /* Disable Power Down Logic */
46285 +                               gpwrdn.d32 = 0;
46286 +                               gpwrdn.b.pmuactv = 1;
46287 +                               DWC_MODIFY_REG32(&core_if->
46288 +                                                core_global_regs->gpwrdn,
46289 +                                                gpwrdn.d32, 0);
46290 +
46291 +                               /*
46292 +                                * Initialize the Core for Device mode.
46293 +                                */
46294 +                               core_if->op_state = B_PERIPHERAL;
46295 +                               dwc_otg_core_init(core_if);
46296 +                               dwc_otg_enable_global_interrupts(core_if);
46297 +                               cil_pcd_start(core_if);
46298 +
46299 +                               dwc_otg_initiate_srp(core_if);
46300 +                       }
46301 +
46302 +                       dctl.b.rmtwkupsig = 1;
46303 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46304 +                                        dctl, 0, dctl.d32);
46305 +                       DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46306 +
46307 +                       dwc_mdelay(2);
46308 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46309 +                                        dctl, dctl.d32, 0);
46310 +                       DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
46311 +               }
46312 +       } else {
46313 +               DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
46314 +       }
46315 +}
46316 +
46317 +#ifdef CONFIG_USB_DWC_OTG_LPM
46318 +/**
46319 + * This function initiates remote wakeup of the host from L1 sleep state.
46320 + */
46321 +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
46322 +{
46323 +       glpmcfg_data_t lpmcfg;
46324 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46325 +
46326 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46327 +
46328 +       /* Check if we are in L1 state */
46329 +       if (!lpmcfg.b.prt_sleep_sts) {
46330 +               DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
46331 +               return;
46332 +       }
46333 +
46334 +       /* Check if host allows remote wakeup */
46335 +       if (!lpmcfg.b.rem_wkup_en) {
46336 +               DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
46337 +               return;
46338 +       }
46339 +
46340 +       /* Check if Resume OK */
46341 +       if (!lpmcfg.b.sleep_state_resumeok) {
46342 +               DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
46343 +               return;
46344 +       }
46345 +
46346 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46347 +       lpmcfg.b.en_utmi_sleep = 0;
46348 +       lpmcfg.b.hird_thres &= (~(1 << 4));
46349 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
46350 +
46351 +       if (set) {
46352 +               dctl_data_t dctl = {.d32 = 0 };
46353 +               dctl.b.rmtwkupsig = 1;
46354 +               /* Set RmtWkUpSig bit to start remote wakup signaling.
46355 +                * Hardware will automatically clear this bit.
46356 +                */
46357 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
46358 +                                0, dctl.d32);
46359 +               DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46360 +       }
46361 +
46362 +}
46363 +#endif
46364 +
46365 +/**
46366 + * Performs remote wakeup.
46367 + */
46368 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
46369 +{
46370 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46371 +       dwc_irqflags_t flags;
46372 +       if (dwc_otg_is_device_mode(core_if)) {
46373 +               DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46374 +#ifdef CONFIG_USB_DWC_OTG_LPM
46375 +               if (core_if->lx_state == DWC_OTG_L1) {
46376 +                       dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
46377 +               } else {
46378 +#endif
46379 +                       dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
46380 +#ifdef CONFIG_USB_DWC_OTG_LPM
46381 +               }
46382 +#endif
46383 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46384 +       }
46385 +       return;
46386 +}
46387 +
46388 +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
46389 +{
46390 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46391 +       dctl_data_t dctl = { 0 };
46392 +
46393 +       if (dwc_otg_is_device_mode(core_if)) {
46394 +               dctl.b.sftdiscon = 1;
46395 +               DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
46396 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
46397 +               dwc_udelay(no_of_usecs);
46398 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
46399 +
46400 +       } else{
46401 +               DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
46402 +       }
46403 +       return;
46404 +
46405 +}
46406 +
46407 +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
46408 +{
46409 +       dsts_data_t dsts;
46410 +       gotgctl_data_t gotgctl;
46411 +
46412 +       /*
46413 +        * This function starts the Protocol if no session is in progress. If
46414 +        * a session is already in progress, but the device is suspended,
46415 +        * remote wakeup signaling is started.
46416 +        */
46417 +
46418 +       /* Check if valid session */
46419 +       gotgctl.d32 =
46420 +           DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
46421 +       if (gotgctl.b.bsesvld) {
46422 +               /* Check if suspend state */
46423 +               dsts.d32 =
46424 +                   DWC_READ_REG32(&
46425 +                                  (GET_CORE_IF(pcd)->dev_if->
46426 +                                   dev_global_regs->dsts));
46427 +               if (dsts.b.suspsts) {
46428 +                       dwc_otg_pcd_remote_wakeup(pcd, 1);
46429 +               }
46430 +       } else {
46431 +               dwc_otg_pcd_initiate_srp(pcd);
46432 +       }
46433 +
46434 +       return 0;
46435 +
46436 +}
46437 +
46438 +/**
46439 + * Start the SRP timer to detect when the SRP does not complete within
46440 + * 6 seconds.
46441 + *
46442 + * @param pcd the pcd structure.
46443 + */
46444 +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
46445 +{
46446 +       dwc_irqflags_t flags;
46447 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46448 +       dwc_otg_initiate_srp(GET_CORE_IF(pcd));
46449 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46450 +}
46451 +
46452 +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
46453 +{
46454 +       return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
46455 +}
46456 +
46457 +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
46458 +{
46459 +       return GET_CORE_IF(pcd)->core_params->lpm_enable;
46460 +}
46461 +
46462 +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
46463 +{
46464 +       return pcd->b_hnp_enable;
46465 +}
46466 +
46467 +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
46468 +{
46469 +       return pcd->a_hnp_support;
46470 +}
46471 +
46472 +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
46473 +{
46474 +       return pcd->a_alt_hnp_support;
46475 +}
46476 +
46477 +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
46478 +{
46479 +       return pcd->remote_wakeup_enable;
46480 +}
46481 +
46482 +#endif /* DWC_HOST_ONLY */
46483 --- /dev/null
46484 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46485 @@ -0,0 +1,266 @@
46486 +/* ==========================================================================
46487 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
46488 + * $Revision: #48 $
46489 + * $Date: 2012/08/10 $
46490 + * $Change: 2047372 $
46491 + *
46492 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46493 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46494 + * otherwise expressly agreed to in writing between Synopsys and you.
46495 + *
46496 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46497 + * any End User Software License Agreement or Agreement for Licensed Product
46498 + * with Synopsys or any supplement thereto. You are permitted to use and
46499 + * redistribute this Software in source and binary forms, with or without
46500 + * modification, provided that redistributions of source code must retain this
46501 + * notice. You may not view, use, disclose, copy or distribute this file or
46502 + * any information contained herein except pursuant to this license grant from
46503 + * Synopsys. If you do not agree with this notice, including the disclaimer
46504 + * below, then you are not authorized to use the Software.
46505 + *
46506 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46507 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46508 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46509 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46510 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46511 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46512 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46513 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46514 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46515 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46516 + * DAMAGE.
46517 + * ========================================================================== */
46518 +#ifndef DWC_HOST_ONLY
46519 +#if !defined(__DWC_PCD_H__)
46520 +#define __DWC_PCD_H__
46521 +
46522 +#include "dwc_otg_os_dep.h"
46523 +#include "usb.h"
46524 +#include "dwc_otg_cil.h"
46525 +#include "dwc_otg_pcd_if.h"
46526 +struct cfiobject;
46527 +
46528 +/**
46529 + * @file
46530 + *
46531 + * This file contains the structures, constants, and interfaces for
46532 + * the Perpherial Contoller Driver (PCD).
46533 + *
46534 + * The Peripheral Controller Driver (PCD) for Linux will implement the
46535 + * Gadget API, so that the existing Gadget drivers can be used. For
46536 + * the Mass Storage Function driver the File-backed USB Storage Gadget
46537 + * (FBS) driver will be used.  The FBS driver supports the
46538 + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
46539 + * transports.
46540 + *
46541 + */
46542 +
46543 +/** Invalid DMA Address */
46544 +#define DWC_DMA_ADDR_INVALID   (~(dwc_dma_t)0)
46545 +
46546 +/** Max Transfer size for any EP */
46547 +#define DDMA_MAX_TRANSFER_SIZE 65535
46548 +
46549 +/**
46550 + * Get the pointer to the core_if from the pcd pointer.
46551 + */
46552 +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
46553 +
46554 +/**
46555 + * States of EP0.
46556 + */
46557 +typedef enum ep0_state {
46558 +       EP0_DISCONNECT,         /* no host */
46559 +       EP0_IDLE,
46560 +       EP0_IN_DATA_PHASE,
46561 +       EP0_OUT_DATA_PHASE,
46562 +       EP0_IN_STATUS_PHASE,
46563 +       EP0_OUT_STATUS_PHASE,
46564 +       EP0_STALL,
46565 +} ep0state_e;
46566 +
46567 +/** Fordward declaration.*/
46568 +struct dwc_otg_pcd;
46569 +
46570 +/** DWC_otg iso request structure.
46571 + *
46572 + */
46573 +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
46574 +
46575 +#ifdef DWC_UTE_PER_IO
46576 +
46577 +/**
46578 + * This shall be the exact analogy of the same type structure defined in the
46579 + * usb_gadget.h. Each descriptor contains
46580 + */
46581 +struct dwc_iso_pkt_desc_port {
46582 +       uint32_t offset;
46583 +       uint32_t length;        /* expected length */
46584 +       uint32_t actual_length;
46585 +       uint32_t status;
46586 +};
46587 +
46588 +struct dwc_iso_xreq_port {
46589 +       /** transfer/submission flag */
46590 +       uint32_t tr_sub_flags;
46591 +       /** Start the request ASAP */
46592 +#define DWC_EREQ_TF_ASAP               0x00000002
46593 +       /** Just enqueue the request w/o initiating a transfer */
46594 +#define DWC_EREQ_TF_ENQUEUE            0x00000004
46595 +
46596 +       /**
46597 +       * count of ISO packets attached to this request - shall
46598 +       * not exceed the pio_alloc_pkt_count
46599 +       */
46600 +       uint32_t pio_pkt_count;
46601 +       /** count of ISO packets allocated for this request */
46602 +       uint32_t pio_alloc_pkt_count;
46603 +       /** number of ISO packet errors */
46604 +       uint32_t error_count;
46605 +       /** reserved for future extension */
46606 +       uint32_t res;
46607 +       /** Will be allocated and freed in the UTE gadget and based on the CFC value */
46608 +       struct dwc_iso_pkt_desc_port *per_io_frame_descs;
46609 +};
46610 +#endif
46611 +/** DWC_otg request structure.
46612 + * This structure is a list of requests.
46613 + */
46614 +typedef struct dwc_otg_pcd_request {
46615 +       void *priv;
46616 +       void *buf;
46617 +       dwc_dma_t dma;
46618 +       uint32_t length;
46619 +       uint32_t actual;
46620 +       unsigned sent_zlp:1;
46621 +    /**
46622 +     * Used instead of original buffer if
46623 +     * it(physical address) is not dword-aligned.
46624 +     **/
46625 +     uint8_t *dw_align_buf;
46626 +     dwc_dma_t dw_align_buf_dma;
46627 +
46628 +        DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
46629 +#ifdef DWC_UTE_PER_IO
46630 +       struct dwc_iso_xreq_port ext_req;
46631 +       //void *priv_ereq_nport; /*  */
46632 +#endif
46633 +} dwc_otg_pcd_request_t;
46634 +
46635 +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
46636 +
46637 +/**      PCD EP structure.
46638 + * This structure describes an EP, there is an array of EPs in the PCD
46639 + * structure.
46640 + */
46641 +typedef struct dwc_otg_pcd_ep {
46642 +       /** USB EP Descriptor */
46643 +       const usb_endpoint_descriptor_t *desc;
46644 +
46645 +       /** queue of dwc_otg_pcd_requests. */
46646 +       struct req_list queue;
46647 +       unsigned stopped:1;
46648 +       unsigned disabling:1;
46649 +       unsigned dma:1;
46650 +       unsigned queue_sof:1;
46651 +
46652 +#ifdef DWC_EN_ISOC
46653 +       /** ISOC req handle passed */
46654 +       void *iso_req_handle;
46655 +#endif                         //_EN_ISOC_
46656 +
46657 +       /** DWC_otg ep data. */
46658 +       dwc_ep_t dwc_ep;
46659 +
46660 +       /** Pointer to PCD */
46661 +       struct dwc_otg_pcd *pcd;
46662 +
46663 +       void *priv;
46664 +} dwc_otg_pcd_ep_t;
46665 +
46666 +/** DWC_otg PCD Structure.
46667 + * This structure encapsulates the data for the dwc_otg PCD.
46668 + */
46669 +struct dwc_otg_pcd {
46670 +       const struct dwc_otg_pcd_function_ops *fops;
46671 +       /** The DWC otg device pointer */
46672 +       struct dwc_otg_device *otg_dev;
46673 +       /** Core Interface */
46674 +       dwc_otg_core_if_t *core_if;
46675 +       /** State of EP0 */
46676 +       ep0state_e ep0state;
46677 +       /** EP0 Request is pending */
46678 +       unsigned ep0_pending:1;
46679 +       /** Indicates when SET CONFIGURATION Request is in process */
46680 +       unsigned request_config:1;
46681 +       /** The state of the Remote Wakeup Enable. */
46682 +       unsigned remote_wakeup_enable:1;
46683 +       /** The state of the B-Device HNP Enable. */
46684 +       unsigned b_hnp_enable:1;
46685 +       /** The state of A-Device HNP Support. */
46686 +       unsigned a_hnp_support:1;
46687 +       /** The state of the A-Device Alt HNP support. */
46688 +       unsigned a_alt_hnp_support:1;
46689 +       /** Count of pending Requests */
46690 +       unsigned request_pending;
46691 +
46692 +       /** SETUP packet for EP0
46693 +        * This structure is allocated as a DMA buffer on PCD initialization
46694 +        * with enough space for up to 3 setup packets.
46695 +        */
46696 +       union {
46697 +               usb_device_request_t req;
46698 +               uint32_t d32[2];
46699 +       } *setup_pkt;
46700 +
46701 +       dwc_dma_t setup_pkt_dma_handle;
46702 +
46703 +       /* Additional buffer and flag for CTRL_WR premature case */
46704 +       uint8_t *backup_buf;
46705 +       unsigned data_terminated;
46706 +
46707 +       /** 2-byte dma buffer used to return status from GET_STATUS */
46708 +       uint16_t *status_buf;
46709 +       dwc_dma_t status_buf_dma_handle;
46710 +
46711 +       /** EP0 */
46712 +       dwc_otg_pcd_ep_t ep0;
46713 +
46714 +       /** Array of IN EPs. */
46715 +       dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
46716 +       /** Array of OUT EPs. */
46717 +       dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
46718 +       /** number of valid EPs in the above array. */
46719 +//        unsigned      num_eps : 4;
46720 +       dwc_spinlock_t *lock;
46721 +
46722 +       /** Tasklet to defer starting of TEST mode transmissions until
46723 +        *      Status Phase has been completed.
46724 +        */
46725 +       dwc_tasklet_t *test_mode_tasklet;
46726 +
46727 +       /** Tasklet to delay starting of xfer in DMA mode */
46728 +       dwc_tasklet_t *start_xfer_tasklet;
46729 +
46730 +       /** The test mode to enter when the tasklet is executed. */
46731 +       unsigned test_mode;
46732 +       /** The cfi_api structure that implements most of the CFI API
46733 +        * and OTG specific core configuration functionality
46734 +        */
46735 +#ifdef DWC_UTE_CFI
46736 +       struct cfiobject *cfi;
46737 +#endif
46738 +
46739 +};
46740 +
46741 +//FIXME this functions should be static, and this prototypes should be removed
46742 +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
46743 +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
46744 +                                dwc_otg_pcd_request_t * req, int32_t status);
46745 +
46746 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
46747 +                            void *req_handle);
46748 +
46749 +extern void do_test_mode(void *data);
46750 +#endif
46751 +#endif /* DWC_HOST_ONLY */
46752 --- /dev/null
46753 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
46754 @@ -0,0 +1,360 @@
46755 +/* ==========================================================================
46756 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
46757 + * $Revision: #11 $
46758 + * $Date: 2011/10/26 $
46759 + * $Change: 1873028 $
46760 + *
46761 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46762 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46763 + * otherwise expressly agreed to in writing between Synopsys and you.
46764 + *
46765 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46766 + * any End User Software License Agreement or Agreement for Licensed Product
46767 + * with Synopsys or any supplement thereto. You are permitted to use and
46768 + * redistribute this Software in source and binary forms, with or without
46769 + * modification, provided that redistributions of source code must retain this
46770 + * notice. You may not view, use, disclose, copy or distribute this file or
46771 + * any information contained herein except pursuant to this license grant from
46772 + * Synopsys. If you do not agree with this notice, including the disclaimer
46773 + * below, then you are not authorized to use the Software.
46774 + *
46775 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46776 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46777 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46778 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46779 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46780 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46781 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46782 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46783 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46784 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46785 + * DAMAGE.
46786 + * ========================================================================== */
46787 +#ifndef DWC_HOST_ONLY
46788 +
46789 +#if !defined(__DWC_PCD_IF_H__)
46790 +#define __DWC_PCD_IF_H__
46791 +
46792 +//#include "dwc_os.h"
46793 +#include "dwc_otg_core_if.h"
46794 +
46795 +/** @file
46796 + * This file defines DWC_OTG PCD Core API.
46797 + */
46798 +
46799 +struct dwc_otg_pcd;
46800 +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
46801 +
46802 +/** Maxpacket size for EP0 */
46803 +#define MAX_EP0_SIZE   64
46804 +/** Maxpacket size for any EP */
46805 +#define MAX_PACKET_SIZE 1024
46806 +
46807 +/** @name Function Driver Callbacks */
46808 +/** @{ */
46809 +
46810 +/** This function will be called whenever a previously queued request has
46811 + * completed.  The status value will be set to -DWC_E_SHUTDOWN to indicated a
46812 + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
46813 + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
46814 + * parameters. */
46815 +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46816 +                                   void *req_handle, int32_t status,
46817 +                                   uint32_t actual);
46818 +/**
46819 + * This function will be called whenever a previousle queued ISOC request has
46820 + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
46821 + * function.
46822 + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
46823 + * functions.
46824 + */
46825 +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46826 +                                        void *req_handle, int proc_buf_num);
46827 +/** This function should handle any SETUP request that cannot be handled by the
46828 + * PCD Core.  This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
46829 + * class-specific requests, etc.  The function must non-blocking.
46830 + *
46831 + * Returns 0 on success.
46832 + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
46833 + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
46834 + * Returns -DWC_E_SHUTDOWN on any other error. */
46835 +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
46836 +/** This is called whenever the device has been disconnected.  The function
46837 + * driver should take appropriate action to clean up all pending requests in the
46838 + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
46839 + * state. */
46840 +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
46841 +/** This function is called when device has been connected. */
46842 +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
46843 +/** This function is called when device has been suspended */
46844 +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
46845 +/** This function is called when device has received LPM tokens, i.e.
46846 + * device has been sent to sleep state. */
46847 +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
46848 +/** This function is called when device has been resumed
46849 + * from suspend(L2) or L1 sleep state. */
46850 +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
46851 +/** This function is called whenever hnp params has been changed.
46852 + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
46853 + * to get hnp parameters. */
46854 +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
46855 +/** This function is called whenever USB RESET is detected. */
46856 +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
46857 +
46858 +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
46859 +
46860 +/**
46861 + *
46862 + * @param ep_handle    Void pointer to the usb_ep structure
46863 + * @param ereq_port Pointer to the extended request structure created in the
46864 + *                                     portable part.
46865 + */
46866 +typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46867 +                                    void *req_handle, int32_t status,
46868 +                                    void *ereq_port);
46869 +/** Function Driver Ops Data Structure */
46870 +struct dwc_otg_pcd_function_ops {
46871 +       dwc_connect_cb_t connect;
46872 +       dwc_disconnect_cb_t disconnect;
46873 +       dwc_setup_cb_t setup;
46874 +       dwc_completion_cb_t complete;
46875 +       dwc_isoc_completion_cb_t isoc_complete;
46876 +       dwc_suspend_cb_t suspend;
46877 +       dwc_sleep_cb_t sleep;
46878 +       dwc_resume_cb_t resume;
46879 +       dwc_reset_cb_t reset;
46880 +       dwc_hnp_params_changed_cb_t hnp_changed;
46881 +       cfi_setup_cb_t cfi_setup;
46882 +#ifdef DWC_UTE_PER_IO
46883 +       xiso_completion_cb_t xisoc_complete;
46884 +#endif
46885 +};
46886 +/** @} */
46887 +
46888 +/** @name Function Driver Functions */
46889 +/** @{ */
46890 +
46891 +/** Call this function to get pointer on dwc_otg_pcd_t,
46892 + * this pointer will be used for all PCD API functions.
46893 + *
46894 + * @param core_if The DWC_OTG Core
46895 + */
46896 +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
46897 +
46898 +/** Frees PCD allocated by dwc_otg_pcd_init
46899 + *
46900 + * @param pcd The PCD
46901 + */
46902 +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
46903 +
46904 +/** Call this to bind the function driver to the PCD Core.
46905 + *
46906 + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
46907 + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
46908 + */
46909 +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
46910 +                             const struct dwc_otg_pcd_function_ops *fops);
46911 +
46912 +/** Enables an endpoint for use.  This function enables an endpoint in
46913 + * the PCD.  The endpoint is described by the ep_desc which has the
46914 + * same format as a USB ep descriptor.  The ep_handle parameter is used to refer
46915 + * to the endpoint from other API functions and in callbacks.  Normally this
46916 + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
46917 + * core for that interface.
46918 + *
46919 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46920 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46921 + * Returns 0 on success.
46922 + *
46923 + * @param pcd The PCD
46924 + * @param ep_desc Endpoint descriptor
46925 + * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
46926 + */
46927 +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
46928 +                                const uint8_t * ep_desc, void *usb_ep);
46929 +
46930 +/** Disable the endpoint referenced by ep_handle.
46931 + *
46932 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46933 + * Returns -DWC_E_SHUTDOWN if any other error occurred.
46934 + * Returns 0 on success. */
46935 +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
46936 +
46937 +/** Queue a data transfer request on the endpoint referenced by ep_handle.
46938 + * After the transfer is completes, the complete callback will be called with
46939 + * the request status.
46940 + *
46941 + * @param pcd The PCD
46942 + * @param ep_handle The handle of the endpoint
46943 + * @param buf The buffer for the data
46944 + * @param dma_buf The DMA buffer for the data
46945 + * @param buflen The length of the data transfer
46946 + * @param zero Specifies whether to send zero length last packet.
46947 + * @param req_handle Set this handle to any value to use to reference this
46948 + * request in the ep_dequeue function or from the complete callback
46949 + * @param atomic_alloc If driver need to perform atomic allocations
46950 + * for internal data structures.
46951 + *
46952 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46953 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46954 + * Returns 0 on success. */
46955 +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46956 +                               uint8_t * buf, dwc_dma_t dma_buf,
46957 +                               uint32_t buflen, int zero, void *req_handle,
46958 +                               int atomic_alloc);
46959 +#ifdef DWC_UTE_PER_IO
46960 +/**
46961 + *
46962 + * @param ereq_nonport Pointer to the extended request part of the
46963 + *                                             usb_request structure defined in usb_gadget.h file.
46964 + */
46965 +extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46966 +                                    uint8_t * buf, dwc_dma_t dma_buf,
46967 +                                    uint32_t buflen, int zero,
46968 +                                    void *req_handle, int atomic_alloc,
46969 +                                    void *ereq_nonport);
46970 +
46971 +#endif
46972 +
46973 +/** De-queue the specified data transfer that has not yet completed.
46974 + *
46975 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46976 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46977 + * Returns 0 on success. */
46978 +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
46979 +                                 void *req_handle);
46980 +
46981 +/** Halt (STALL) an endpoint or clear it.
46982 + *
46983 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46984 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46985 + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
46986 + * Returns 0 on success. */
46987 +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
46988 +
46989 +/** This function */
46990 +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
46991 +
46992 +/** This function should be called on every hardware interrupt */
46993 +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
46994 +
46995 +/** This function returns current frame number */
46996 +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
46997 +
46998 +/**
46999 + * Start isochronous transfers on the endpoint referenced by ep_handle.
47000 + * For isochronous transfers duble buffering is used.
47001 + * After processing each of buffers comlete callback will be called with
47002 + * status for each transaction.
47003 + *
47004 + * @param pcd The PCD
47005 + * @param ep_handle The handle of the endpoint
47006 + * @param buf0 The virtual address of first data buffer
47007 + * @param buf1 The virtual address of second data buffer
47008 + * @param dma0 The DMA address of first data buffer
47009 + * @param dma1 The DMA address of second data buffer
47010 + * @param sync_frame Data pattern frame number
47011 + * @param dp_frame Data size for pattern frame
47012 + * @param data_per_frame Data size for regular frame
47013 + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
47014 + * @param buf_proc_intrvl Interval of ISOC Buffer processing
47015 + * @param req_handle Handle of ISOC request
47016 + * @param atomic_alloc Specefies whether to perform atomic allocation for
47017 + *                     internal data structures.
47018 + *
47019 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
47020 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
47021 + * Returns -DW_E_SHUTDOWN for any other error.
47022 + * Returns 0 on success
47023 + */
47024 +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
47025 +                                   uint8_t * buf0, uint8_t * buf1,
47026 +                                   dwc_dma_t dma0, dwc_dma_t dma1,
47027 +                                   int sync_frame, int dp_frame,
47028 +                                   int data_per_frame, int start_frame,
47029 +                                   int buf_proc_intrvl, void *req_handle,
47030 +                                   int atomic_alloc);
47031 +
47032 +/** Stop ISOC transfers on endpoint referenced by ep_handle.
47033 + *
47034 + * @param pcd The PCD
47035 + * @param ep_handle The handle of the endpoint
47036 + * @param req_handle Handle of ISOC request
47037 + *
47038 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
47039 + * Returns 0 on success
47040 + */
47041 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
47042 +                           void *req_handle);
47043 +
47044 +/** Get ISOC packet status.
47045 + *
47046 + * @param pcd The PCD
47047 + * @param ep_handle The handle of the endpoint
47048 + * @param iso_req_handle Isochronoush request handle
47049 + * @param packet Number of packet
47050 + * @param status Out parameter for returning status
47051 + * @param actual Out parameter for returning actual length
47052 + * @param offset Out parameter for returning offset
47053 + *
47054 + */
47055 +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
47056 +                                             void *ep_handle,
47057 +                                             void *iso_req_handle, int packet,
47058 +                                             int *status, int *actual,
47059 +                                             int *offset);
47060 +
47061 +/** Get ISOC packet count.
47062 + *
47063 + * @param pcd The PCD
47064 + * @param ep_handle The handle of the endpoint
47065 + * @param iso_req_handle
47066 + */
47067 +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
47068 +                                           void *ep_handle,
47069 +                                           void *iso_req_handle);
47070 +
47071 +/** This function starts the SRP Protocol if no session is in progress. If
47072 + * a session is already in progress, but the device is suspended,
47073 + * remote wakeup signaling is started.
47074 + */
47075 +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
47076 +
47077 +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
47078 +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
47079 +
47080 +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
47081 +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
47082 +
47083 +/** Initiate SRP */
47084 +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
47085 +
47086 +/** Starts remote wakeup signaling. */
47087 +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
47088 +
47089 +/** Starts micorsecond soft disconnect. */
47090 +extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);
47091 +/** This function returns whether device is dualspeed.*/
47092 +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
47093 +
47094 +/** This function returns whether device is otg. */
47095 +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
47096 +
47097 +/** These functions allow to get hnp parameters */
47098 +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
47099 +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
47100 +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
47101 +
47102 +/** CFI specific Interface functions */
47103 +/** Allocate a cfi buffer */
47104 +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
47105 +                                    dwc_dma_t * addr, size_t buflen,
47106 +                                    int flags);
47107 +
47108 +/******************************************************************************/
47109 +
47110 +/** @} */
47111 +
47112 +#endif                         /* __DWC_PCD_IF_H__ */
47113 +
47114 +#endif                         /* DWC_HOST_ONLY */
47115 --- /dev/null
47116 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47117 @@ -0,0 +1,5147 @@
47118 +/* ==========================================================================
47119 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
47120 + * $Revision: #116 $
47121 + * $Date: 2012/08/10 $
47122 + * $Change: 2047372 $
47123 + *
47124 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
47125 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
47126 + * otherwise expressly agreed to in writing between Synopsys and you.
47127 + *
47128 + * The Software IS NOT an item of Licensed Software or Licensed Product under
47129 + * any End User Software License Agreement or Agreement for Licensed Product
47130 + * with Synopsys or any supplement thereto. You are permitted to use and
47131 + * redistribute this Software in source and binary forms, with or without
47132 + * modification, provided that redistributions of source code must retain this
47133 + * notice. You may not view, use, disclose, copy or distribute this file or
47134 + * any information contained herein except pursuant to this license grant from
47135 + * Synopsys. If you do not agree with this notice, including the disclaimer
47136 + * below, then you are not authorized to use the Software.
47137 + *
47138 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
47139 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47140 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47141 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
47142 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47143 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47144 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47145 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47146 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47147 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
47148 + * DAMAGE.
47149 + * ========================================================================== */
47150 +#ifndef DWC_HOST_ONLY
47151 +
47152 +#include "dwc_otg_pcd.h"
47153 +
47154 +#ifdef DWC_UTE_CFI
47155 +#include "dwc_otg_cfi.h"
47156 +#endif
47157 +
47158 +#ifdef DWC_UTE_PER_IO
47159 +extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
47160 +#endif
47161 +//#define PRINT_CFI_DMA_DESCS
47162 +
47163 +#define DEBUG_EP0
47164 +
47165 +/**
47166 + * This function updates OTG.
47167 + */
47168 +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
47169 +{
47170 +
47171 +       if (reset) {
47172 +               pcd->b_hnp_enable = 0;
47173 +               pcd->a_hnp_support = 0;
47174 +               pcd->a_alt_hnp_support = 0;
47175 +       }
47176 +
47177 +       if (pcd->fops->hnp_changed) {
47178 +               pcd->fops->hnp_changed(pcd);
47179 +       }
47180 +}
47181 +
47182 +/** @file
47183 + * This file contains the implementation of the PCD Interrupt handlers.
47184 + *
47185 + * The PCD handles the device interrupts.  Many conditions can cause a
47186 + * device interrupt. When an interrupt occurs, the device interrupt
47187 + * service routine determines the cause of the interrupt and
47188 + * dispatches handling to the appropriate function. These interrupt
47189 + * handling functions are described below.
47190 + * All interrupt registers are processed from LSB to MSB.
47191 + */
47192 +
47193 +/**
47194 + * This function prints the ep0 state for debug purposes.
47195 + */
47196 +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
47197 +{
47198 +#ifdef DEBUG
47199 +       char str[40];
47200 +
47201 +       switch (pcd->ep0state) {
47202 +       case EP0_DISCONNECT:
47203 +               dwc_strcpy(str, "EP0_DISCONNECT");
47204 +               break;
47205 +       case EP0_IDLE:
47206 +               dwc_strcpy(str, "EP0_IDLE");
47207 +               break;
47208 +       case EP0_IN_DATA_PHASE:
47209 +               dwc_strcpy(str, "EP0_IN_DATA_PHASE");
47210 +               break;
47211 +       case EP0_OUT_DATA_PHASE:
47212 +               dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
47213 +               break;
47214 +       case EP0_IN_STATUS_PHASE:
47215 +               dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
47216 +               break;
47217 +       case EP0_OUT_STATUS_PHASE:
47218 +               dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
47219 +               break;
47220 +       case EP0_STALL:
47221 +               dwc_strcpy(str, "EP0_STALL");
47222 +               break;
47223 +       default:
47224 +               dwc_strcpy(str, "EP0_INVALID");
47225 +       }
47226 +
47227 +       DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
47228 +#endif
47229 +}
47230 +
47231 +/**
47232 + * This function calculate the size of the payload in the memory
47233 + * for out endpoints and prints size for debug purposes(used in
47234 + * 2.93a DevOutNak feature).
47235 + */
47236 +static inline void print_memory_payload(dwc_otg_pcd_t * pcd,  dwc_ep_t * ep)
47237 +{
47238 +#ifdef DEBUG
47239 +       deptsiz_data_t deptsiz_init = {.d32 = 0 };
47240 +       deptsiz_data_t deptsiz_updt = {.d32 = 0 };
47241 +       int pack_num;
47242 +       unsigned payload;
47243 +
47244 +       deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
47245 +       deptsiz_updt.d32 =
47246 +               DWC_READ_REG32(&pcd->core_if->dev_if->
47247 +                                               out_ep_regs[ep->num]->doeptsiz);
47248 +       /* Payload will be */
47249 +       payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
47250 +       /* Packet count is decremented every time a packet
47251 +        * is written to the RxFIFO not in to the external memory
47252 +        * So, if payload == 0, then it means no packet was sent to ext memory*/
47253 +       pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
47254 +       DWC_DEBUGPL(DBG_PCDV,
47255 +               "Payload for EP%d-%s\n",
47256 +               ep->num, (ep->is_in ? "IN" : "OUT"));
47257 +       DWC_DEBUGPL(DBG_PCDV,
47258 +               "Number of transfered bytes = 0x%08x\n", payload);
47259 +       DWC_DEBUGPL(DBG_PCDV,
47260 +               "Number of transfered packets = %d\n", pack_num);
47261 +#endif
47262 +}
47263 +
47264 +
47265 +#ifdef DWC_UTE_CFI
47266 +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
47267 +                             const uint8_t * epname, int descnum)
47268 +{
47269 +       CFI_INFO
47270 +           ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
47271 +            epname, descnum, ddesc->buf, ddesc->status.b.bytes,
47272 +            ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
47273 +            ddesc->status.b.bs);
47274 +}
47275 +#endif
47276 +
47277 +/**
47278 + * This function returns pointer to in ep struct with number ep_num
47279 + */
47280 +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47281 +{
47282 +       int i;
47283 +       int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47284 +       if (ep_num == 0) {
47285 +               return &pcd->ep0;
47286 +       } else {
47287 +               for (i = 0; i < num_in_eps; ++i) {
47288 +                       if (pcd->in_ep[i].dwc_ep.num == ep_num)
47289 +                               return &pcd->in_ep[i];
47290 +               }
47291 +               return 0;
47292 +       }
47293 +}
47294 +
47295 +/**
47296 + * This function returns pointer to out ep struct with number ep_num
47297 + */
47298 +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47299 +{
47300 +       int i;
47301 +       int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47302 +       if (ep_num == 0) {
47303 +               return &pcd->ep0;
47304 +       } else {
47305 +               for (i = 0; i < num_out_eps; ++i) {
47306 +                       if (pcd->out_ep[i].dwc_ep.num == ep_num)
47307 +                               return &pcd->out_ep[i];
47308 +               }
47309 +               return 0;
47310 +       }
47311 +}
47312 +
47313 +/**
47314 + * This functions gets a pointer to an EP from the wIndex address
47315 + * value of the control request.
47316 + */
47317 +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
47318 +{
47319 +       dwc_otg_pcd_ep_t *ep;
47320 +       uint32_t ep_num = UE_GET_ADDR(wIndex);
47321 +
47322 +       if (ep_num == 0) {
47323 +               ep = &pcd->ep0;
47324 +       } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {   /* in ep */
47325 +               ep = &pcd->in_ep[ep_num - 1];
47326 +       } else {
47327 +               ep = &pcd->out_ep[ep_num - 1];
47328 +       }
47329 +
47330 +       return ep;
47331 +}
47332 +
47333 +/**
47334 + * This function checks the EP request queue, if the queue is not
47335 + * empty the next request is started.
47336 + */
47337 +void start_next_request(dwc_otg_pcd_ep_t * ep)
47338 +{
47339 +       dwc_otg_pcd_request_t *req = 0;
47340 +       uint32_t max_transfer =
47341 +           GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
47342 +
47343 +#ifdef DWC_UTE_CFI
47344 +       struct dwc_otg_pcd *pcd;
47345 +       pcd = ep->pcd;
47346 +#endif
47347 +
47348 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
47349 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
47350 +
47351 +#ifdef DWC_UTE_CFI
47352 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
47353 +                       ep->dwc_ep.cfi_req_len = req->length;
47354 +                       pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
47355 +               } else {
47356 +#endif
47357 +                       /* Setup and start the Transfer */
47358 +                       if (req->dw_align_buf) {
47359 +                               ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
47360 +                               ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
47361 +                               ep->dwc_ep.xfer_buff = req->dw_align_buf;
47362 +                       } else {
47363 +                               ep->dwc_ep.dma_addr = req->dma;
47364 +                               ep->dwc_ep.start_xfer_buff = req->buf;
47365 +                               ep->dwc_ep.xfer_buff = req->buf;
47366 +                       }
47367 +                       ep->dwc_ep.sent_zlp = 0;
47368 +                       ep->dwc_ep.total_len = req->length;
47369 +                       ep->dwc_ep.xfer_len = 0;
47370 +                       ep->dwc_ep.xfer_count = 0;
47371 +
47372 +                       ep->dwc_ep.maxxfer = max_transfer;
47373 +                       if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
47374 +                               uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
47375 +                                   - (DDMA_MAX_TRANSFER_SIZE % 4);
47376 +                               if (ep->dwc_ep.is_in) {
47377 +                                       if (ep->dwc_ep.maxxfer >
47378 +                                           DDMA_MAX_TRANSFER_SIZE) {
47379 +                                               ep->dwc_ep.maxxfer =
47380 +                                                   DDMA_MAX_TRANSFER_SIZE;
47381 +                                       }
47382 +                               } else {
47383 +                                       if (ep->dwc_ep.maxxfer > out_max_xfer) {
47384 +                                               ep->dwc_ep.maxxfer =
47385 +                                                   out_max_xfer;
47386 +                                       }
47387 +                               }
47388 +                       }
47389 +                       if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
47390 +                               ep->dwc_ep.maxxfer -=
47391 +                                   (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
47392 +                       }
47393 +                       if (req->sent_zlp) {
47394 +                               if ((ep->dwc_ep.total_len %
47395 +                                    ep->dwc_ep.maxpacket == 0)
47396 +                                   && (ep->dwc_ep.total_len != 0)) {
47397 +                                       ep->dwc_ep.sent_zlp = 1;
47398 +                               }
47399 +
47400 +                       }
47401 +#ifdef DWC_UTE_CFI
47402 +               }
47403 +#endif
47404 +               dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
47405 +       } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
47406 +               DWC_PRINTF("There are no more ISOC requests \n");
47407 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
47408 +       }
47409 +}
47410 +
47411 +/**
47412 + * This function handles the SOF Interrupts. At this time the SOF
47413 + * Interrupt is disabled.
47414 + */
47415 +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
47416 +{
47417 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47418 +
47419 +       gintsts_data_t gintsts;
47420 +
47421 +       DWC_DEBUGPL(DBG_PCD, "SOF\n");
47422 +
47423 +       /* Clear interrupt */
47424 +       gintsts.d32 = 0;
47425 +       gintsts.b.sofintr = 1;
47426 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
47427 +
47428 +       return 1;
47429 +}
47430 +
47431 +/**
47432 + * This function handles the Rx Status Queue Level Interrupt, which
47433 + * indicates that there is a least one packet in the Rx FIFO.  The
47434 + * packets are moved from the FIFO to memory, where they will be
47435 + * processed when the Endpoint Interrupt Register indicates Transfer
47436 + * Complete or SETUP Phase Done.
47437 + *
47438 + * Repeat the following until the Rx Status Queue is empty:
47439 + *      -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
47440 + *             info
47441 + *      -# If Receive FIFO is empty then skip to step Clear the interrupt
47442 + *             and exit
47443 + *      -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
47444 + *             SETUP data to the buffer
47445 + *      -# If OUT Data Packet call dwc_otg_read_packet to copy the data
47446 + *             to the destination buffer
47447 + */
47448 +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
47449 +{
47450 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47451 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47452 +       gintmsk_data_t gintmask = {.d32 = 0 };
47453 +       device_grxsts_data_t status;
47454 +       dwc_otg_pcd_ep_t *ep;
47455 +       gintsts_data_t gintsts;
47456 +#ifdef DEBUG
47457 +       static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
47458 +#endif
47459 +
47460 +       //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
47461 +       /* Disable the Rx Status Queue Level interrupt */
47462 +       gintmask.b.rxstsqlvl = 1;
47463 +       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
47464 +
47465 +       /* Get the Status from the top of the FIFO */
47466 +       status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
47467 +
47468 +       DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
47469 +                   "pktsts:%x Frame:%d(0x%0x)\n",
47470 +                   status.b.epnum, status.b.bcnt,
47471 +                   dpid_str[status.b.dpid],
47472 +                   status.b.pktsts, status.b.fn, status.b.fn);
47473 +       /* Get pointer to EP structure */
47474 +       ep = get_out_ep(pcd, status.b.epnum);
47475 +
47476 +       switch (status.b.pktsts) {
47477 +       case DWC_DSTS_GOUT_NAK:
47478 +               DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
47479 +               break;
47480 +       case DWC_STS_DATA_UPDT:
47481 +               DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
47482 +               if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
47483 +                       /** @todo NGS Check for buffer overflow? */
47484 +                       dwc_otg_read_packet(core_if,
47485 +                                           ep->dwc_ep.xfer_buff,
47486 +                                           status.b.bcnt);
47487 +                       ep->dwc_ep.xfer_count += status.b.bcnt;
47488 +                       ep->dwc_ep.xfer_buff += status.b.bcnt;
47489 +               }
47490 +               break;
47491 +       case DWC_STS_XFER_COMP:
47492 +               DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
47493 +               break;
47494 +       case DWC_DSTS_SETUP_COMP:
47495 +#ifdef DEBUG_EP0
47496 +               DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
47497 +#endif
47498 +               break;
47499 +       case DWC_DSTS_SETUP_UPDT:
47500 +               dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
47501 +#ifdef DEBUG_EP0
47502 +               DWC_DEBUGPL(DBG_PCD,
47503 +                           "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
47504 +                           pcd->setup_pkt->req.bmRequestType,
47505 +                           pcd->setup_pkt->req.bRequest,
47506 +                           UGETW(pcd->setup_pkt->req.wValue),
47507 +                           UGETW(pcd->setup_pkt->req.wIndex),
47508 +                           UGETW(pcd->setup_pkt->req.wLength));
47509 +#endif
47510 +               ep->dwc_ep.xfer_count += status.b.bcnt;
47511 +               break;
47512 +       default:
47513 +               DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
47514 +                           status.b.pktsts);
47515 +               break;
47516 +       }
47517 +
47518 +       /* Enable the Rx Status Queue Level interrupt */
47519 +       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
47520 +       /* Clear interrupt */
47521 +       gintsts.d32 = 0;
47522 +       gintsts.b.rxstsqlvl = 1;
47523 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47524 +
47525 +       //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
47526 +       return 1;
47527 +}
47528 +
47529 +/**
47530 + * This function examines the Device IN Token Learning Queue to
47531 + * determine the EP number of the last IN token received.  This
47532 + * implementation is for the Mass Storage device where there are only
47533 + * 2 IN EPs (Control-IN and BULK-IN).
47534 + *
47535 + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
47536 + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
47537 + *
47538 + * @param core_if Programming view of DWC_otg controller.
47539 + *
47540 + */
47541 +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
47542 +{
47543 +       dwc_otg_device_global_regs_t *dev_global_regs =
47544 +           core_if->dev_if->dev_global_regs;
47545 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
47546 +       /* Number of Token Queue Registers */
47547 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
47548 +       dtknq1_data_t dtknqr1;
47549 +       uint32_t in_tkn_epnums[4];
47550 +       int ndx = 0;
47551 +       int i = 0;
47552 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
47553 +       int epnum = 0;
47554 +
47555 +       //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
47556 +
47557 +       /* Read the DTKNQ Registers */
47558 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
47559 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
47560 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
47561 +                           in_tkn_epnums[i]);
47562 +               if (addr == &dev_global_regs->dvbusdis) {
47563 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
47564 +               } else {
47565 +                       ++addr;
47566 +               }
47567 +
47568 +       }
47569 +
47570 +       /* Copy the DTKNQR1 data to the bit field. */
47571 +       dtknqr1.d32 = in_tkn_epnums[0];
47572 +       /* Get the EP numbers */
47573 +       in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
47574 +       ndx = dtknqr1.b.intknwptr - 1;
47575 +
47576 +       //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
47577 +       if (ndx == -1) {
47578 +               /** @todo Find a simpler way to calculate the max
47579 +                * queue position.*/
47580 +               int cnt = TOKEN_Q_DEPTH;
47581 +               if (TOKEN_Q_DEPTH <= 6) {
47582 +                       cnt = TOKEN_Q_DEPTH - 1;
47583 +               } else if (TOKEN_Q_DEPTH <= 14) {
47584 +                       cnt = TOKEN_Q_DEPTH - 7;
47585 +               } else if (TOKEN_Q_DEPTH <= 22) {
47586 +                       cnt = TOKEN_Q_DEPTH - 15;
47587 +               } else {
47588 +                       cnt = TOKEN_Q_DEPTH - 23;
47589 +               }
47590 +               epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
47591 +       } else {
47592 +               if (ndx <= 5) {
47593 +                       epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
47594 +               } else if (ndx <= 13) {
47595 +                       ndx -= 6;
47596 +                       epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
47597 +               } else if (ndx <= 21) {
47598 +                       ndx -= 14;
47599 +                       epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
47600 +               } else if (ndx <= 29) {
47601 +                       ndx -= 22;
47602 +                       epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
47603 +               }
47604 +       }
47605 +       //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
47606 +       return epnum;
47607 +}
47608 +
47609 +/**
47610 + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
47611 + * The active request is checked for the next packet to be loaded into
47612 + * the non-periodic Tx FIFO.
47613 + */
47614 +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
47615 +{
47616 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47617 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47618 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47619 +       gnptxsts_data_t txstatus = {.d32 = 0 };
47620 +       gintsts_data_t gintsts;
47621 +
47622 +       int epnum = 0;
47623 +       dwc_otg_pcd_ep_t *ep = 0;
47624 +       uint32_t len = 0;
47625 +       int dwords;
47626 +
47627 +       /* Get the epnum from the IN Token Learning Queue. */
47628 +       epnum = get_ep_of_last_in_token(core_if);
47629 +       ep = get_in_ep(pcd, epnum);
47630 +
47631 +       DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
47632 +
47633 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47634 +
47635 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47636 +       if (len > ep->dwc_ep.maxpacket) {
47637 +               len = ep->dwc_ep.maxpacket;
47638 +       }
47639 +       dwords = (len + 3) / 4;
47640 +
47641 +       /* While there is space in the queue and space in the FIFO and
47642 +        * More data to tranfer, Write packets to the Tx FIFO */
47643 +       txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47644 +       DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
47645 +
47646 +       while (txstatus.b.nptxqspcavail > 0 &&
47647 +              txstatus.b.nptxfspcavail > dwords &&
47648 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
47649 +               /* Write the FIFO */
47650 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47651 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47652 +
47653 +               if (len > ep->dwc_ep.maxpacket) {
47654 +                       len = ep->dwc_ep.maxpacket;
47655 +               }
47656 +
47657 +               dwords = (len + 3) / 4;
47658 +               txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47659 +               DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
47660 +       }
47661 +
47662 +       DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
47663 +                   DWC_READ_REG32(&global_regs->gnptxsts));
47664 +
47665 +       /* Clear interrupt */
47666 +       gintsts.d32 = 0;
47667 +       gintsts.b.nptxfempty = 1;
47668 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47669 +
47670 +       return 1;
47671 +}
47672 +
47673 +/**
47674 + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
47675 + * The active request is checked for the next packet to be loaded into
47676 + * apropriate Tx FIFO.
47677 + */
47678 +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
47679 +{
47680 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47681 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47682 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47683 +       dtxfsts_data_t txstatus = {.d32 = 0 };
47684 +       dwc_otg_pcd_ep_t *ep = 0;
47685 +       uint32_t len = 0;
47686 +       int dwords;
47687 +
47688 +       ep = get_in_ep(pcd, epnum);
47689 +
47690 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
47691 +
47692 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47693 +
47694 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47695 +
47696 +       if (len > ep->dwc_ep.maxpacket) {
47697 +               len = ep->dwc_ep.maxpacket;
47698 +       }
47699 +
47700 +       dwords = (len + 3) / 4;
47701 +
47702 +       /* While there is space in the queue and space in the FIFO and
47703 +        * More data to tranfer, Write packets to the Tx FIFO */
47704 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47705 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
47706 +
47707 +       while (txstatus.b.txfspcavail > dwords &&
47708 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
47709 +              ep->dwc_ep.xfer_len != 0) {
47710 +               /* Write the FIFO */
47711 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47712 +
47713 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47714 +               if (len > ep->dwc_ep.maxpacket) {
47715 +                       len = ep->dwc_ep.maxpacket;
47716 +               }
47717 +
47718 +               dwords = (len + 3) / 4;
47719 +               txstatus.d32 =
47720 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47721 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
47722 +                           txstatus.d32);
47723 +       }
47724 +
47725 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
47726 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
47727 +
47728 +       return 1;
47729 +}
47730 +
47731 +/**
47732 + * This function is called when the Device is disconnected. It stops
47733 + * any active requests and informs the Gadget driver of the
47734 + * disconnect.
47735 + */
47736 +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
47737 +{
47738 +       int i, num_in_eps, num_out_eps;
47739 +       dwc_otg_pcd_ep_t *ep;
47740 +
47741 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47742 +
47743 +       DWC_SPINLOCK(pcd->lock);
47744 +
47745 +       num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47746 +       num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47747 +
47748 +       DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
47749 +       /* don't disconnect drivers more than once */
47750 +       if (pcd->ep0state == EP0_DISCONNECT) {
47751 +               DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
47752 +               DWC_SPINUNLOCK(pcd->lock);
47753 +               return;
47754 +       }
47755 +       pcd->ep0state = EP0_DISCONNECT;
47756 +
47757 +       /* Reset the OTG state. */
47758 +       dwc_otg_pcd_update_otg(pcd, 1);
47759 +
47760 +       /* Disable the NP Tx Fifo Empty Interrupt. */
47761 +       intr_mask.b.nptxfempty = 1;
47762 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47763 +                        intr_mask.d32, 0);
47764 +
47765 +       /* Flush the FIFOs */
47766 +       /**@todo NGS Flush Periodic FIFOs */
47767 +       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
47768 +       dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
47769 +
47770 +       /* prevent new request submissions, kill any outstanding requests  */
47771 +       ep = &pcd->ep0;
47772 +       dwc_otg_request_nuke(ep);
47773 +       /* prevent new request submissions, kill any outstanding requests  */
47774 +       for (i = 0; i < num_in_eps; i++) {
47775 +               dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
47776 +               dwc_otg_request_nuke(ep);
47777 +       }
47778 +       /* prevent new request submissions, kill any outstanding requests  */
47779 +       for (i = 0; i < num_out_eps; i++) {
47780 +               dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
47781 +               dwc_otg_request_nuke(ep);
47782 +       }
47783 +
47784 +       /* report disconnect; the driver is already quiesced */
47785 +       if (pcd->fops->disconnect) {
47786 +               DWC_SPINUNLOCK(pcd->lock);
47787 +               pcd->fops->disconnect(pcd);
47788 +               DWC_SPINLOCK(pcd->lock);
47789 +       }
47790 +       DWC_SPINUNLOCK(pcd->lock);
47791 +}
47792 +
47793 +/**
47794 + * This interrupt indicates that ...
47795 + */
47796 +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
47797 +{
47798 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47799 +       gintsts_data_t gintsts;
47800 +
47801 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
47802 +       intr_mask.b.i2cintr = 1;
47803 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47804 +                        intr_mask.d32, 0);
47805 +
47806 +       /* Clear interrupt */
47807 +       gintsts.d32 = 0;
47808 +       gintsts.b.i2cintr = 1;
47809 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
47810 +                       gintsts.d32);
47811 +       return 1;
47812 +}
47813 +
47814 +/**
47815 + * This interrupt indicates that ...
47816 + */
47817 +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
47818 +{
47819 +       gintsts_data_t gintsts;
47820 +#if defined(VERBOSE)
47821 +       DWC_PRINTF("Early Suspend Detected\n");
47822 +#endif
47823 +
47824 +       /* Clear interrupt */
47825 +       gintsts.d32 = 0;
47826 +       gintsts.b.erlysuspend = 1;
47827 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
47828 +                       gintsts.d32);
47829 +       return 1;
47830 +}
47831 +
47832 +/**
47833 + * This function configures EPO to receive SETUP packets.
47834 + *
47835 + * @todo NGS: Update the comments from the HW FS.
47836 + *
47837 + *     -# Program the following fields in the endpoint specific registers
47838 + *     for Control OUT EP 0, in order to receive a setup packet
47839 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
47840 + *       setup packets)
47841 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
47842 + *       to back setup packets)
47843 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
47844 + *               store any setup packets received
47845 + *
47846 + * @param core_if Programming view of DWC_otg controller.
47847 + * @param pcd    Programming view of the PCD.
47848 + */
47849 +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
47850 +                                dwc_otg_pcd_t * pcd)
47851 +{
47852 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47853 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
47854 +       dwc_otg_dev_dma_desc_t *dma_desc;
47855 +       depctl_data_t doepctl = {.d32 = 0 };
47856 +
47857 +#ifdef VERBOSE
47858 +       DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
47859 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
47860 +#endif
47861 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
47862 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
47863 +               if (doepctl.b.epena) {
47864 +                       return;
47865 +               }
47866 +       }
47867 +
47868 +       doeptsize0.b.supcnt = 3;
47869 +       doeptsize0.b.pktcnt = 1;
47870 +       doeptsize0.b.xfersize = 8 * 3;
47871 +
47872 +       if (core_if->dma_enable) {
47873 +               if (!core_if->dma_desc_enable) {
47874 +                       /** put here as for Hermes mode deptisz register should not be written */
47875 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
47876 +                                       doeptsize0.d32);
47877 +
47878 +                       /** @todo dma needs to handle multiple setup packets (up to 3) */
47879 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
47880 +                                       pcd->setup_pkt_dma_handle);
47881 +               } else {
47882 +                       dev_if->setup_desc_index =
47883 +                           (dev_if->setup_desc_index + 1) & 1;
47884 +                       dma_desc =
47885 +                           dev_if->setup_desc_addr[dev_if->setup_desc_index];
47886 +
47887 +                       /** DMA Descriptor Setup */
47888 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
47889 +                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
47890 +                               dma_desc->status.b.sr = 0;
47891 +                               dma_desc->status.b.mtrf = 0;
47892 +                       }
47893 +                       dma_desc->status.b.l = 1;
47894 +                       dma_desc->status.b.ioc = 1;
47895 +                       dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
47896 +                       dma_desc->buf = pcd->setup_pkt_dma_handle;
47897 +                       dma_desc->status.b.sts = 0;
47898 +                       dma_desc->status.b.bs = BS_HOST_READY;
47899 +
47900 +                       /** DOEPDMA0 Register write */
47901 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
47902 +                                       dev_if->dma_setup_desc_addr
47903 +                                       [dev_if->setup_desc_index]);
47904 +               }
47905 +
47906 +       } else {
47907 +               /** put here as for Hermes mode deptisz register should not be written */
47908 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
47909 +                               doeptsize0.d32);
47910 +       }
47911 +
47912 +       /** DOEPCTL0 Register write cnak will be set after setup interrupt */
47913 +       doepctl.d32 = 0;
47914 +       doepctl.b.epena = 1;
47915 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
47916 +       doepctl.b.cnak = 1;
47917 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
47918 +       } else {
47919 +               DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
47920 +       }
47921 +
47922 +#ifdef VERBOSE
47923 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
47924 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
47925 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
47926 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
47927 +#endif
47928 +}
47929 +
47930 +/**
47931 + * This interrupt occurs when a USB Reset is detected. When the USB
47932 + * Reset Interrupt occurs the device state is set to DEFAULT and the
47933 + * EP0 state is set to IDLE.
47934 + *     -#      Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
47935 + *     -#      Unmask the following interrupt bits
47936 + *             - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
47937 + *     - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
47938 + *     - DOEPMSK.SETUP = 1
47939 + *     - DOEPMSK.XferCompl = 1
47940 + *     - DIEPMSK.XferCompl = 1
47941 + *     - DIEPMSK.TimeOut = 1
47942 + *     -# Program the following fields in the endpoint specific registers
47943 + *     for Control OUT EP 0, in order to receive a setup packet
47944 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
47945 + *       setup packets)
47946 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
47947 + *       to back setup packets)
47948 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
47949 + *               store any setup packets received
47950 + * At this point, all the required initialization, except for enabling
47951 + * the control 0 OUT endpoint is done, for receiving SETUP packets.
47952 + */
47953 +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
47954 +{
47955 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47956 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47957 +       depctl_data_t doepctl = {.d32 = 0 };
47958 +       depctl_data_t diepctl = {.d32 = 0 };
47959 +       daint_data_t daintmsk = {.d32 = 0 };
47960 +       doepmsk_data_t doepmsk = {.d32 = 0 };
47961 +       diepmsk_data_t diepmsk = {.d32 = 0 };
47962 +       dcfg_data_t dcfg = {.d32 = 0 };
47963 +       grstctl_t resetctl = {.d32 = 0 };
47964 +       dctl_data_t dctl = {.d32 = 0 };
47965 +       int i = 0;
47966 +       gintsts_data_t gintsts;
47967 +       pcgcctl_data_t power = {.d32 = 0 };
47968 +
47969 +       power.d32 = DWC_READ_REG32(core_if->pcgcctl);
47970 +       if (power.b.stoppclk) {
47971 +               power.d32 = 0;
47972 +               power.b.stoppclk = 1;
47973 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
47974 +
47975 +               power.b.pwrclmp = 1;
47976 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
47977 +
47978 +               power.b.rstpdwnmodule = 1;
47979 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
47980 +       }
47981 +
47982 +       core_if->lx_state = DWC_OTG_L0;
47983 +
47984 +       DWC_PRINTF("USB RESET\n");
47985 +#ifdef DWC_EN_ISOC
47986 +       for (i = 1; i < 16; ++i) {
47987 +               dwc_otg_pcd_ep_t *ep;
47988 +               dwc_ep_t *dwc_ep;
47989 +               ep = get_in_ep(pcd, i);
47990 +               if (ep != 0) {
47991 +                       dwc_ep = &ep->dwc_ep;
47992 +                       dwc_ep->next_frame = 0xffffffff;
47993 +               }
47994 +       }
47995 +#endif /* DWC_EN_ISOC */
47996 +
47997 +       /* reset the HNP settings */
47998 +       dwc_otg_pcd_update_otg(pcd, 1);
47999 +
48000 +       /* Clear the Remote Wakeup Signalling */
48001 +       dctl.b.rmtwkupsig = 1;
48002 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
48003 +
48004 +       /* Set NAK for all OUT EPs */
48005 +       doepctl.b.snak = 1;
48006 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
48007 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
48008 +       }
48009 +
48010 +       /* Flush the NP Tx FIFO */
48011 +       dwc_otg_flush_tx_fifo(core_if, 0x10);
48012 +       /* Flush the Learning Queue */
48013 +       resetctl.b.intknqflsh = 1;
48014 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
48015 +
48016 +       if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
48017 +               core_if->start_predict = 0;
48018 +               for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
48019 +                       core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
48020 +               }
48021 +               core_if->nextep_seq[0] = 0;
48022 +               core_if->first_in_nextep_seq = 0;
48023 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
48024 +               diepctl.b.nextep = 0;
48025 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
48026 +
48027 +               /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
48028 +               dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48029 +               dcfg.b.epmscnt = 2;
48030 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48031 +
48032 +               DWC_DEBUGPL(DBG_PCDV,
48033 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
48034 +                       __func__, core_if->first_in_nextep_seq);
48035 +               for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
48036 +                       DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
48037 +               }
48038 +       }
48039 +
48040 +       if (core_if->multiproc_int_enable) {
48041 +               daintmsk.b.inep0 = 1;
48042 +               daintmsk.b.outep0 = 1;
48043 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
48044 +                               daintmsk.d32);
48045 +
48046 +               doepmsk.b.setup = 1;
48047 +               doepmsk.b.xfercompl = 1;
48048 +               doepmsk.b.ahberr = 1;
48049 +               doepmsk.b.epdisabled = 1;
48050 +
48051 +               if ((core_if->dma_desc_enable) ||
48052 +                   (core_if->dma_enable
48053 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48054 +                       doepmsk.b.stsphsercvd = 1;
48055 +               }
48056 +               if (core_if->dma_desc_enable)
48057 +                       doepmsk.b.bna = 1;
48058 +/*
48059 +               doepmsk.b.babble = 1;
48060 +               doepmsk.b.nyet = 1;
48061 +
48062 +               if (core_if->dma_enable) {
48063 +                       doepmsk.b.nak = 1;
48064 +               }
48065 +*/
48066 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
48067 +                               doepmsk.d32);
48068 +
48069 +               diepmsk.b.xfercompl = 1;
48070 +               diepmsk.b.timeout = 1;
48071 +               diepmsk.b.epdisabled = 1;
48072 +               diepmsk.b.ahberr = 1;
48073 +               diepmsk.b.intknepmis = 1;
48074 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48075 +                       diepmsk.b.intknepmis = 0;
48076 +
48077 +/*             if (core_if->dma_desc_enable) {
48078 +                       diepmsk.b.bna = 1;
48079 +               }
48080 +*/
48081 +/*
48082 +               if (core_if->dma_enable) {
48083 +                       diepmsk.b.nak = 1;
48084 +               }
48085 +*/
48086 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
48087 +                               diepmsk.d32);
48088 +       } else {
48089 +               daintmsk.b.inep0 = 1;
48090 +               daintmsk.b.outep0 = 1;
48091 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
48092 +                               daintmsk.d32);
48093 +
48094 +               doepmsk.b.setup = 1;
48095 +               doepmsk.b.xfercompl = 1;
48096 +               doepmsk.b.ahberr = 1;
48097 +               doepmsk.b.epdisabled = 1;
48098 +
48099 +               if ((core_if->dma_desc_enable) ||
48100 +                   (core_if->dma_enable
48101 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48102 +                       doepmsk.b.stsphsercvd = 1;
48103 +               }
48104 +               if (core_if->dma_desc_enable)
48105 +                       doepmsk.b.bna = 1;
48106 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
48107 +
48108 +               diepmsk.b.xfercompl = 1;
48109 +               diepmsk.b.timeout = 1;
48110 +               diepmsk.b.epdisabled = 1;
48111 +               diepmsk.b.ahberr = 1;
48112 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48113 +                       diepmsk.b.intknepmis = 0;
48114 +/*
48115 +               if (core_if->dma_desc_enable) {
48116 +                       diepmsk.b.bna = 1;
48117 +               }
48118 +*/
48119 +
48120 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
48121 +       }
48122 +
48123 +       /* Reset Device Address */
48124 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48125 +       dcfg.b.devaddr = 0;
48126 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48127 +
48128 +       /* setup EP0 to receive SETUP packets */
48129 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a)
48130 +               ep0_out_start(core_if, pcd);
48131 +
48132 +       /* Clear interrupt */
48133 +       gintsts.d32 = 0;
48134 +       gintsts.b.usbreset = 1;
48135 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48136 +
48137 +       return 1;
48138 +}
48139 +
48140 +/**
48141 + * Get the device speed from the device status register and convert it
48142 + * to USB speed constant.
48143 + *
48144 + * @param core_if Programming view of DWC_otg controller.
48145 + */
48146 +static int get_device_speed(dwc_otg_core_if_t * core_if)
48147 +{
48148 +       dsts_data_t dsts;
48149 +       int speed = 0;
48150 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
48151 +
48152 +       switch (dsts.b.enumspd) {
48153 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
48154 +               speed = USB_SPEED_HIGH;
48155 +               break;
48156 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
48157 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
48158 +               speed = USB_SPEED_FULL;
48159 +               break;
48160 +
48161 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
48162 +               speed = USB_SPEED_LOW;
48163 +               break;
48164 +       }
48165 +
48166 +       return speed;
48167 +}
48168 +
48169 +/**
48170 + * Read the device status register and set the device speed in the
48171 + * data structure.
48172 + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
48173 + */
48174 +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
48175 +{
48176 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48177 +       gintsts_data_t gintsts;
48178 +       gusbcfg_data_t gusbcfg;
48179 +       dwc_otg_core_global_regs_t *global_regs =
48180 +           GET_CORE_IF(pcd)->core_global_regs;
48181 +       uint8_t utmi16b, utmi8b;
48182 +       int speed;
48183 +       DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
48184 +
48185 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
48186 +               utmi16b = 6;    //vahrama old value was 6;
48187 +               utmi8b = 9;
48188 +       } else {
48189 +               utmi16b = 4;
48190 +               utmi8b = 8;
48191 +       }
48192 +       dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
48193 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
48194 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48195 +       }
48196 +
48197 +#ifdef DEBUG_EP0
48198 +       print_ep0_state(pcd);
48199 +#endif
48200 +
48201 +       if (pcd->ep0state == EP0_DISCONNECT) {
48202 +               pcd->ep0state = EP0_IDLE;
48203 +       } else if (pcd->ep0state == EP0_STALL) {
48204 +               pcd->ep0state = EP0_IDLE;
48205 +       }
48206 +
48207 +       pcd->ep0state = EP0_IDLE;
48208 +
48209 +       ep0->stopped = 0;
48210 +
48211 +       speed = get_device_speed(GET_CORE_IF(pcd));
48212 +       pcd->fops->connect(pcd, speed);
48213 +
48214 +       /* Set USB turnaround time based on device speed and PHY interface. */
48215 +       gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
48216 +       if (speed == USB_SPEED_HIGH) {
48217 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48218 +                   DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
48219 +                       /* ULPI interface */
48220 +                       gusbcfg.b.usbtrdtim = 9;
48221 +               }
48222 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48223 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
48224 +                       /* UTMI+ interface */
48225 +                       if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
48226 +                               gusbcfg.b.usbtrdtim = utmi8b;
48227 +                       } else if (GET_CORE_IF(pcd)->hwcfg4.
48228 +                                  b.utmi_phy_data_width == 1) {
48229 +                               gusbcfg.b.usbtrdtim = utmi16b;
48230 +                       } else if (GET_CORE_IF(pcd)->
48231 +                                  core_params->phy_utmi_width == 8) {
48232 +                               gusbcfg.b.usbtrdtim = utmi8b;
48233 +                       } else {
48234 +                               gusbcfg.b.usbtrdtim = utmi16b;
48235 +                       }
48236 +               }
48237 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48238 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
48239 +                       /* UTMI+  OR  ULPI interface */
48240 +                       if (gusbcfg.b.ulpi_utmi_sel == 1) {
48241 +                               /* ULPI interface */
48242 +                               gusbcfg.b.usbtrdtim = 9;
48243 +                       } else {
48244 +                               /* UTMI+ interface */
48245 +                               if (GET_CORE_IF(pcd)->
48246 +                                   core_params->phy_utmi_width == 16) {
48247 +                                       gusbcfg.b.usbtrdtim = utmi16b;
48248 +                               } else {
48249 +                                       gusbcfg.b.usbtrdtim = utmi8b;
48250 +                               }
48251 +                       }
48252 +               }
48253 +       } else {
48254 +               /* Full or low speed */
48255 +               gusbcfg.b.usbtrdtim = 9;
48256 +       }
48257 +       DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
48258 +
48259 +       /* Clear interrupt */
48260 +       gintsts.d32 = 0;
48261 +       gintsts.b.enumdone = 1;
48262 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48263 +                       gintsts.d32);
48264 +       return 1;
48265 +}
48266 +
48267 +/**
48268 + * This interrupt indicates that the ISO OUT Packet was dropped due to
48269 + * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs
48270 + * read all the data from the Rx FIFO.
48271 + */
48272 +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
48273 +{
48274 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48275 +       gintsts_data_t gintsts;
48276 +
48277 +       DWC_WARN("INTERRUPT Handler not implemented for %s\n",
48278 +                "ISOC Out Dropped");
48279 +
48280 +       intr_mask.b.isooutdrop = 1;
48281 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48282 +                        intr_mask.d32, 0);
48283 +
48284 +       /* Clear interrupt */
48285 +       gintsts.d32 = 0;
48286 +       gintsts.b.isooutdrop = 1;
48287 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48288 +                       gintsts.d32);
48289 +
48290 +       return 1;
48291 +}
48292 +
48293 +/**
48294 + * This interrupt indicates the end of the portion of the micro-frame
48295 + * for periodic transactions.  If there is a periodic transaction for
48296 + * the next frame, load the packets into the EP periodic Tx FIFO.
48297 + */
48298 +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
48299 +{
48300 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48301 +       gintsts_data_t gintsts;
48302 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
48303 +
48304 +       intr_mask.b.eopframe = 1;
48305 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48306 +                        intr_mask.d32, 0);
48307 +
48308 +       /* Clear interrupt */
48309 +       gintsts.d32 = 0;
48310 +       gintsts.b.eopframe = 1;
48311 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48312 +                       gintsts.d32);
48313 +
48314 +       return 1;
48315 +}
48316 +
48317 +/**
48318 + * This interrupt indicates that EP of the packet on the top of the
48319 + * non-periodic Tx FIFO does not match EP of the IN Token received.
48320 + *
48321 + * The "Device IN Token Queue" Registers are read to determine the
48322 + * order the IN Tokens have been received. The non-periodic Tx FIFO
48323 + * is flushed, so it can be reloaded in the order seen in the IN Token
48324 + * Queue.
48325 + */
48326 +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
48327 +{
48328 +       gintsts_data_t gintsts;
48329 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48330 +       dctl_data_t dctl;
48331 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48332 +
48333 +       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
48334 +               core_if->start_predict = 1;
48335 +
48336 +               DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48337 +
48338 +               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
48339 +               if (!gintsts.b.ginnakeff) {
48340 +                       /* Disable EP Mismatch interrupt */
48341 +                       intr_mask.d32 = 0;
48342 +                       intr_mask.b.epmismatch = 1;
48343 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
48344 +                       /* Enable the Global IN NAK Effective Interrupt */
48345 +                       intr_mask.d32 = 0;
48346 +                       intr_mask.b.ginnakeff = 1;
48347 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
48348 +                       /* Set the global non-periodic IN NAK handshake */
48349 +                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48350 +                       dctl.b.sgnpinnak = 1;
48351 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48352 +               } else {
48353 +                       DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
48354 +               }
48355 +               /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
48356 +                * handler after Global IN NAK Effective interrupt will be asserted */
48357 +       }
48358 +       /* Clear interrupt */
48359 +       gintsts.d32 = 0;
48360 +       gintsts.b.epmismatch = 1;
48361 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48362 +
48363 +       return 1;
48364 +}
48365 +
48366 +/**
48367 + * This interrupt is valid only in DMA mode. This interrupt indicates that the
48368 + * core has stopped fetching data for IN endpoints due to the unavailability of
48369 + * TxFIFO space or Request Queue space. This interrupt is used by the
48370 + * application for an endpoint mismatch algorithm.
48371 + *
48372 + * @param pcd The PCD
48373 + */
48374 +int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
48375 +{
48376 +       gintsts_data_t gintsts;
48377 +       gintmsk_data_t gintmsk_data;
48378 +       dctl_data_t dctl;
48379 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48380 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48381 +
48382 +       /* Clear the global non-periodic IN NAK handshake */
48383 +       dctl.d32 = 0;
48384 +       dctl.b.cgnpinnak = 1;
48385 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
48386 +
48387 +       /* Mask GINTSTS.FETSUSP interrupt */
48388 +       gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
48389 +       gintmsk_data.b.fetsusp = 0;
48390 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
48391 +
48392 +       /* Clear interrupt */
48393 +       gintsts.d32 = 0;
48394 +       gintsts.b.fetsusp = 1;
48395 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48396 +
48397 +       return 1;
48398 +}
48399 +/**
48400 + * This funcion stalls EP0.
48401 + */
48402 +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
48403 +{
48404 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48405 +       usb_device_request_t *ctrl = &pcd->setup_pkt->req;
48406 +       DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
48407 +                ctrl->bmRequestType, ctrl->bRequest, err_val);
48408 +
48409 +       ep0->dwc_ep.is_in = 1;
48410 +       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
48411 +       pcd->ep0.stopped = 1;
48412 +       pcd->ep0state = EP0_IDLE;
48413 +       ep0_out_start(GET_CORE_IF(pcd), pcd);
48414 +}
48415 +
48416 +/**
48417 + * This functions delegates the setup command to the gadget driver.
48418 + */
48419 +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
48420 +                                  usb_device_request_t * ctrl)
48421 +{
48422 +       int ret = 0;
48423 +       DWC_SPINUNLOCK(pcd->lock);
48424 +       ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
48425 +       DWC_SPINLOCK(pcd->lock);
48426 +       if (ret < 0) {
48427 +               ep0_do_stall(pcd, ret);
48428 +       }
48429 +
48430 +       /** @todo This is a g_file_storage gadget driver specific
48431 +        * workaround: a DELAYED_STATUS result from the fsg_setup
48432 +        * routine will result in the gadget queueing a EP0 IN status
48433 +        * phase for a two-stage control transfer. Exactly the same as
48434 +        * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
48435 +        * specific request.  Need a generic way to know when the gadget
48436 +        * driver will queue the status phase. Can we assume when we
48437 +        * call the gadget driver setup() function that it will always
48438 +        * queue and require the following flag? Need to look into
48439 +        * this.
48440 +        */
48441 +
48442 +       if (ret == 256 + 999) {
48443 +               pcd->request_config = 1;
48444 +       }
48445 +}
48446 +
48447 +#ifdef DWC_UTE_CFI
48448 +/**
48449 + * This functions delegates the CFI setup commands to the gadget driver.
48450 + * This function will return a negative value to indicate a failure.
48451 + */
48452 +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
48453 +                                  struct cfi_usb_ctrlrequest *ctrl_req)
48454 +{
48455 +       int ret = 0;
48456 +
48457 +       if (pcd->fops && pcd->fops->cfi_setup) {
48458 +               DWC_SPINUNLOCK(pcd->lock);
48459 +               ret = pcd->fops->cfi_setup(pcd, ctrl_req);
48460 +               DWC_SPINLOCK(pcd->lock);
48461 +               if (ret < 0) {
48462 +                       ep0_do_stall(pcd, ret);
48463 +                       return ret;
48464 +               }
48465 +       }
48466 +
48467 +       return ret;
48468 +}
48469 +#endif
48470 +
48471 +/**
48472 + * This function starts the Zero-Length Packet for the IN status phase
48473 + * of a 2 stage control transfer.
48474 + */
48475 +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
48476 +{
48477 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48478 +       if (pcd->ep0state == EP0_STALL) {
48479 +               return;
48480 +       }
48481 +
48482 +       pcd->ep0state = EP0_IN_STATUS_PHASE;
48483 +
48484 +       /* Prepare for more SETUP Packets */
48485 +       DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
48486 +       if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
48487 +           && (pcd->core_if->dma_desc_enable)
48488 +           && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
48489 +               DWC_DEBUGPL(DBG_PCDV,
48490 +                           "Data terminated wait next packet in out_desc_addr\n");
48491 +               pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
48492 +               pcd->data_terminated = 1;
48493 +       }
48494 +       ep0->dwc_ep.xfer_len = 0;
48495 +       ep0->dwc_ep.xfer_count = 0;
48496 +       ep0->dwc_ep.is_in = 1;
48497 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48498 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48499 +
48500 +       /* Prepare for more SETUP Packets */
48501 +       //ep0_out_start(GET_CORE_IF(pcd), pcd);
48502 +}
48503 +
48504 +/**
48505 + * This function starts the Zero-Length Packet for the OUT status phase
48506 + * of a 2 stage control transfer.
48507 + */
48508 +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
48509 +{
48510 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48511 +       if (pcd->ep0state == EP0_STALL) {
48512 +               DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
48513 +               return;
48514 +       }
48515 +       pcd->ep0state = EP0_OUT_STATUS_PHASE;
48516 +
48517 +       DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
48518 +       ep0->dwc_ep.xfer_len = 0;
48519 +       ep0->dwc_ep.xfer_count = 0;
48520 +       ep0->dwc_ep.is_in = 0;
48521 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48522 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48523 +
48524 +       /* Prepare for more SETUP Packets */
48525 +       if (GET_CORE_IF(pcd)->dma_enable == 0) {
48526 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48527 +       }
48528 +}
48529 +
48530 +/**
48531 + * Clear the EP halt (STALL) and if pending requests start the
48532 + * transfer.
48533 + */
48534 +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
48535 +{
48536 +       if (ep->dwc_ep.stall_clear_flag == 0)
48537 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
48538 +
48539 +       /* Reactive the EP */
48540 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
48541 +       if (ep->stopped) {
48542 +               ep->stopped = 0;
48543 +               /* If there is a request in the EP queue start it */
48544 +
48545 +               /** @todo FIXME: this causes an EP mismatch in DMA mode.
48546 +                * epmismatch not yet implemented. */
48547 +
48548 +               /*
48549 +                * Above fixme is solved by implmenting a tasklet to call the
48550 +                * start_next_request(), outside of interrupt context at some
48551 +                * time after the current time, after a clear-halt setup packet.
48552 +                * Still need to implement ep mismatch in the future if a gadget
48553 +                * ever uses more than one endpoint at once
48554 +                */
48555 +               ep->queue_sof = 1;
48556 +               DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
48557 +       }
48558 +       /* Start Control Status Phase */
48559 +       do_setup_in_status_phase(pcd);
48560 +}
48561 +
48562 +/**
48563 + * This function is called when the SET_FEATURE TEST_MODE Setup packet
48564 + * is sent from the host.  The Device Control register is written with
48565 + * the Test Mode bits set to the specified Test Mode.  This is done as
48566 + * a tasklet so that the "Status" phase of the control transfer
48567 + * completes before transmitting the TEST packets.
48568 + *
48569 + * @todo This has not been tested since the tasklet struct was put
48570 + * into the PCD struct!
48571 + *
48572 + */
48573 +void do_test_mode(void *data)
48574 +{
48575 +       dctl_data_t dctl;
48576 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
48577 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48578 +       int test_mode = pcd->test_mode;
48579 +
48580 +//        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
48581 +
48582 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48583 +       switch (test_mode) {
48584 +       case 1:         // TEST_J
48585 +               dctl.b.tstctl = 1;
48586 +               break;
48587 +
48588 +       case 2:         // TEST_K
48589 +               dctl.b.tstctl = 2;
48590 +               break;
48591 +
48592 +       case 3:         // TEST_SE0_NAK
48593 +               dctl.b.tstctl = 3;
48594 +               break;
48595 +
48596 +       case 4:         // TEST_PACKET
48597 +               dctl.b.tstctl = 4;
48598 +               break;
48599 +
48600 +       case 5:         // TEST_FORCE_ENABLE
48601 +               dctl.b.tstctl = 5;
48602 +               break;
48603 +       }
48604 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48605 +}
48606 +
48607 +/**
48608 + * This function process the GET_STATUS Setup Commands.
48609 + */
48610 +static inline void do_get_status(dwc_otg_pcd_t * pcd)
48611 +{
48612 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48613 +       dwc_otg_pcd_ep_t *ep;
48614 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48615 +       uint16_t *status = pcd->status_buf;
48616 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48617 +
48618 +#ifdef DEBUG_EP0
48619 +       DWC_DEBUGPL(DBG_PCD,
48620 +                   "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
48621 +                   ctrl.bmRequestType, ctrl.bRequest,
48622 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48623 +                   UGETW(ctrl.wLength));
48624 +#endif
48625 +
48626 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48627 +       case UT_DEVICE:
48628 +               if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
48629 +                       DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
48630 +                       DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
48631 +                       DWC_PRINTF("OTG CAP - %d, %d\n",
48632 +                                  core_if->core_params->otg_cap,
48633 +                                               DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
48634 +                       if (core_if->otg_ver == 1
48635 +                           && core_if->core_params->otg_cap ==
48636 +                           DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48637 +                               uint8_t *otgsts = (uint8_t*)pcd->status_buf;
48638 +                               *otgsts = (core_if->otg_sts & 0x1);
48639 +                               pcd->ep0_pending = 1;
48640 +                               ep0->dwc_ep.start_xfer_buff =
48641 +                                   (uint8_t *) otgsts;
48642 +                               ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
48643 +                               ep0->dwc_ep.dma_addr =
48644 +                                   pcd->status_buf_dma_handle;
48645 +                               ep0->dwc_ep.xfer_len = 1;
48646 +                               ep0->dwc_ep.xfer_count = 0;
48647 +                               ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48648 +                               dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
48649 +                                                          &ep0->dwc_ep);
48650 +                               return;
48651 +                       } else {
48652 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48653 +                               return;
48654 +                       }
48655 +                       break;
48656 +               } else {
48657 +                       *status = 0x1;  /* Self powered */
48658 +                       *status |= pcd->remote_wakeup_enable << 1;
48659 +                       break;
48660 +               }
48661 +       case UT_INTERFACE:
48662 +               *status = 0;
48663 +               break;
48664 +
48665 +       case UT_ENDPOINT:
48666 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48667 +               if (ep == 0 || UGETW(ctrl.wLength) > 2) {
48668 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48669 +                       return;
48670 +               }
48671 +               /** @todo check for EP stall */
48672 +               *status = ep->stopped;
48673 +               break;
48674 +       }
48675 +       pcd->ep0_pending = 1;
48676 +       ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
48677 +       ep0->dwc_ep.xfer_buff = (uint8_t *) status;
48678 +       ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
48679 +       ep0->dwc_ep.xfer_len = 2;
48680 +       ep0->dwc_ep.xfer_count = 0;
48681 +       ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48682 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48683 +}
48684 +
48685 +/**
48686 + * This function process the SET_FEATURE Setup Commands.
48687 + */
48688 +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
48689 +{
48690 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48691 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
48692 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48693 +       dwc_otg_pcd_ep_t *ep = 0;
48694 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
48695 +       gotgctl_data_t gotgctl = {.d32 = 0 };
48696 +
48697 +       DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48698 +                   ctrl.bmRequestType, ctrl.bRequest,
48699 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48700 +                   UGETW(ctrl.wLength));
48701 +       DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
48702 +
48703 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48704 +       case UT_DEVICE:
48705 +               switch (UGETW(ctrl.wValue)) {
48706 +               case UF_DEVICE_REMOTE_WAKEUP:
48707 +                       pcd->remote_wakeup_enable = 1;
48708 +                       break;
48709 +
48710 +               case UF_TEST_MODE:
48711 +                       /* Setup the Test Mode tasklet to do the Test
48712 +                        * Packet generation after the SETUP Status
48713 +                        * phase has completed. */
48714 +
48715 +                       /** @todo This has not been tested since the
48716 +                        * tasklet struct was put into the PCD
48717 +                        * struct! */
48718 +                       pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
48719 +                       DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
48720 +                       break;
48721 +
48722 +               case UF_DEVICE_B_HNP_ENABLE:
48723 +                       DWC_DEBUGPL(DBG_PCDV,
48724 +                                   "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
48725 +
48726 +                       /* dev may initiate HNP */
48727 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48728 +                               pcd->b_hnp_enable = 1;
48729 +                               dwc_otg_pcd_update_otg(pcd, 0);
48730 +                               DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
48731 +                               /**@todo Is the gotgctl.devhnpen cleared
48732 +                                * by a USB Reset? */
48733 +                               gotgctl.b.devhnpen = 1;
48734 +                               gotgctl.b.hnpreq = 1;
48735 +                               DWC_WRITE_REG32(&global_regs->gotgctl,
48736 +                                               gotgctl.d32);
48737 +                       } else {
48738 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48739 +                               return;
48740 +                       }
48741 +                       break;
48742 +
48743 +               case UF_DEVICE_A_HNP_SUPPORT:
48744 +                       /* RH port supports HNP */
48745 +                       DWC_DEBUGPL(DBG_PCDV,
48746 +                                   "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
48747 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48748 +                               pcd->a_hnp_support = 1;
48749 +                               dwc_otg_pcd_update_otg(pcd, 0);
48750 +                       } else {
48751 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48752 +                               return;
48753 +                       }
48754 +                       break;
48755 +
48756 +               case UF_DEVICE_A_ALT_HNP_SUPPORT:
48757 +                       /* other RH port does */
48758 +                       DWC_DEBUGPL(DBG_PCDV,
48759 +                                   "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
48760 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48761 +                               pcd->a_alt_hnp_support = 1;
48762 +                               dwc_otg_pcd_update_otg(pcd, 0);
48763 +                       } else {
48764 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48765 +                               return;
48766 +                       }
48767 +                       break;
48768 +
48769 +               default:
48770 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48771 +                       return;
48772 +
48773 +               }
48774 +               do_setup_in_status_phase(pcd);
48775 +               break;
48776 +
48777 +       case UT_INTERFACE:
48778 +               do_gadget_setup(pcd, &ctrl);
48779 +               break;
48780 +
48781 +       case UT_ENDPOINT:
48782 +               if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
48783 +                       ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48784 +                       if (ep == 0) {
48785 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48786 +                               return;
48787 +                       }
48788 +                       ep->stopped = 1;
48789 +                       dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
48790 +               }
48791 +               do_setup_in_status_phase(pcd);
48792 +               break;
48793 +       }
48794 +}
48795 +
48796 +/**
48797 + * This function process the CLEAR_FEATURE Setup Commands.
48798 + */
48799 +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
48800 +{
48801 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48802 +       dwc_otg_pcd_ep_t *ep = 0;
48803 +
48804 +       DWC_DEBUGPL(DBG_PCD,
48805 +                   "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48806 +                   ctrl.bmRequestType, ctrl.bRequest,
48807 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48808 +                   UGETW(ctrl.wLength));
48809 +
48810 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48811 +       case UT_DEVICE:
48812 +               switch (UGETW(ctrl.wValue)) {
48813 +               case UF_DEVICE_REMOTE_WAKEUP:
48814 +                       pcd->remote_wakeup_enable = 0;
48815 +                       break;
48816 +
48817 +               case UF_TEST_MODE:
48818 +                       /** @todo Add CLEAR_FEATURE for TEST modes. */
48819 +                       break;
48820 +
48821 +               default:
48822 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48823 +                       return;
48824 +               }
48825 +               do_setup_in_status_phase(pcd);
48826 +               break;
48827 +
48828 +       case UT_ENDPOINT:
48829 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48830 +               if (ep == 0) {
48831 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48832 +                       return;
48833 +               }
48834 +
48835 +               pcd_clear_halt(pcd, ep);
48836 +
48837 +               break;
48838 +       }
48839 +}
48840 +
48841 +/**
48842 + * This function process the SET_ADDRESS Setup Commands.
48843 + */
48844 +static inline void do_set_address(dwc_otg_pcd_t * pcd)
48845 +{
48846 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
48847 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48848 +
48849 +       if (ctrl.bmRequestType == UT_DEVICE) {
48850 +               dcfg_data_t dcfg = {.d32 = 0 };
48851 +
48852 +#ifdef DEBUG_EP0
48853 +//                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
48854 +#endif
48855 +               dcfg.b.devaddr = UGETW(ctrl.wValue);
48856 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
48857 +               do_setup_in_status_phase(pcd);
48858 +       }
48859 +}
48860 +
48861 +/**
48862 + *     This function processes SETUP commands. In Linux, the USB Command
48863 + *     processing is done in two places - the first being the PCD and the
48864 + *     second in the Gadget Driver (for example, the File-Backed Storage
48865 + *     Gadget Driver).
48866 + *
48867 + * <table>
48868 + * <tr><td>Command     </td><td>Driver </td><td>Description</td></tr>
48869 + *
48870 + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
48871 + * defined in chapter 9 of the USB 2.0 Specification chapter 9
48872 + * </td></tr>
48873 + *
48874 + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
48875 + * requests are the ENDPOINT_HALT feature is procesed, all others the
48876 + * interface requests are ignored.</td></tr>
48877 + *
48878 + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
48879 + * requests are processed by the PCD.  Interface requests are passed
48880 + * to the Gadget Driver.</td></tr>
48881 + *
48882 + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
48883 + * with device address received </td></tr>
48884 + *
48885 + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
48886 + * requested descriptor</td></tr>
48887 + *
48888 + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
48889 + * not implemented by any of the existing Gadget Drivers.</td></tr>
48890 + *
48891 + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
48892 + * all EPs and enable EPs for new configuration.</td></tr>
48893 + *
48894 + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
48895 + * the current configuration</td></tr>
48896 + *
48897 + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
48898 + * EPs and enable EPs for new configuration.</td></tr>
48899 + *
48900 + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
48901 + * current interface.</td></tr>
48902 + *
48903 + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
48904 + * message.</td></tr>
48905 + * </table>
48906 + *
48907 + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
48908 + * processed by pcd_setup. Calling the Function Driver's setup function from
48909 + * pcd_setup processes the gadget SETUP commands.
48910 + */
48911 +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
48912 +{
48913 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48914 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48915 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48916 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48917 +
48918 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
48919 +
48920 +#ifdef DWC_UTE_CFI
48921 +       int retval = 0;
48922 +       struct cfi_usb_ctrlrequest cfi_req;
48923 +#endif
48924 +
48925 +       doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
48926 +
48927 +       /** In BDMA more then 1 setup packet is not supported till 3.00a */
48928 +       if (core_if->dma_enable && core_if->dma_desc_enable == 0
48929 +           && (doeptsize0.b.supcnt < 2)
48930 +           && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
48931 +               DWC_ERROR
48932 +                   ("\n\n-----------    CANNOT handle > 1 setup packet in DMA mode\n\n");
48933 +       }
48934 +       if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
48935 +           && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
48936 +               ctrl =
48937 +                   (pcd->setup_pkt +
48938 +                    (3 - doeptsize0.b.supcnt - 1 +
48939 +                     ep0->dwc_ep.stp_rollover))->req;
48940 +       }
48941 +#ifdef DEBUG_EP0
48942 +       DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
48943 +                   ctrl.bmRequestType, ctrl.bRequest,
48944 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48945 +                   UGETW(ctrl.wLength));
48946 +#endif
48947 +
48948 +       /* Clean up the request queue */
48949 +       dwc_otg_request_nuke(ep0);
48950 +       ep0->stopped = 0;
48951 +
48952 +       if (ctrl.bmRequestType & UE_DIR_IN) {
48953 +               ep0->dwc_ep.is_in = 1;
48954 +               pcd->ep0state = EP0_IN_DATA_PHASE;
48955 +       } else {
48956 +               ep0->dwc_ep.is_in = 0;
48957 +               pcd->ep0state = EP0_OUT_DATA_PHASE;
48958 +       }
48959 +
48960 +       if (UGETW(ctrl.wLength) == 0) {
48961 +               ep0->dwc_ep.is_in = 1;
48962 +               pcd->ep0state = EP0_IN_STATUS_PHASE;
48963 +       }
48964 +
48965 +       if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
48966 +
48967 +#ifdef DWC_UTE_CFI
48968 +               DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
48969 +
48970 +               //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",
48971 +                               ctrl.bRequestType, ctrl.bRequest);
48972 +               if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
48973 +                       if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
48974 +                               retval = cfi_setup(pcd, &cfi_req);
48975 +                               if (retval < 0) {
48976 +                                       ep0_do_stall(pcd, retval);
48977 +                                       pcd->ep0_pending = 0;
48978 +                                       return;
48979 +                               }
48980 +
48981 +                               /* if need gadget setup then call it and check the retval */
48982 +                               if (pcd->cfi->need_gadget_att) {
48983 +                                       retval =
48984 +                                           cfi_gadget_setup(pcd,
48985 +                                                            &pcd->
48986 +                                                            cfi->ctrl_req);
48987 +                                       if (retval < 0) {
48988 +                                               pcd->ep0_pending = 0;
48989 +                                               return;
48990 +                                       }
48991 +                               }
48992 +
48993 +                               if (pcd->cfi->need_status_in_complete) {
48994 +                                       do_setup_in_status_phase(pcd);
48995 +                               }
48996 +                               return;
48997 +                       }
48998 +               }
48999 +#endif
49000 +
49001 +               /* handle non-standard (class/vendor) requests in the gadget driver */
49002 +               do_gadget_setup(pcd, &ctrl);
49003 +               return;
49004 +       }
49005 +
49006 +       /** @todo NGS: Handle bad setup packet? */
49007 +
49008 +///////////////////////////////////////////
49009 +//// --- Standard Request handling --- ////
49010 +
49011 +       switch (ctrl.bRequest) {
49012 +       case UR_GET_STATUS:
49013 +               do_get_status(pcd);
49014 +               break;
49015 +
49016 +       case UR_CLEAR_FEATURE:
49017 +               do_clear_feature(pcd);
49018 +               break;
49019 +
49020 +       case UR_SET_FEATURE:
49021 +               do_set_feature(pcd);
49022 +               break;
49023 +
49024 +       case UR_SET_ADDRESS:
49025 +               do_set_address(pcd);
49026 +               break;
49027 +
49028 +       case UR_SET_INTERFACE:
49029 +       case UR_SET_CONFIG:
49030 +//              _pcd->request_config = 1;       /* Configuration changed */
49031 +               do_gadget_setup(pcd, &ctrl);
49032 +               break;
49033 +
49034 +       case UR_SYNCH_FRAME:
49035 +               do_gadget_setup(pcd, &ctrl);
49036 +               break;
49037 +
49038 +       default:
49039 +               /* Call the Gadget Driver's setup functions */
49040 +               do_gadget_setup(pcd, &ctrl);
49041 +               break;
49042 +       }
49043 +}
49044 +
49045 +/**
49046 + * This function completes the ep0 control transfer.
49047 + */
49048 +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
49049 +{
49050 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49051 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49052 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49053 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49054 +#ifdef DEBUG_EP0
49055 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49056 +           dev_if->out_ep_regs[ep->dwc_ep.num];
49057 +#endif
49058 +       deptsiz0_data_t deptsiz;
49059 +       dev_dma_desc_sts_t desc_sts;
49060 +       dwc_otg_pcd_request_t *req;
49061 +       int is_last = 0;
49062 +       dwc_otg_pcd_t *pcd = ep->pcd;
49063 +
49064 +#ifdef DWC_UTE_CFI
49065 +       struct cfi_usb_ctrlrequest *ctrlreq;
49066 +       int retval = -DWC_E_NOT_SUPPORTED;
49067 +#endif
49068 +
49069 +        desc_sts.b.bytes = 0;
49070 +
49071 +       if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49072 +               if (ep->dwc_ep.is_in) {
49073 +#ifdef DEBUG_EP0
49074 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
49075 +#endif
49076 +                       do_setup_out_status_phase(pcd);
49077 +               } else {
49078 +#ifdef DEBUG_EP0
49079 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
49080 +#endif
49081 +
49082 +#ifdef DWC_UTE_CFI
49083 +                       ctrlreq = &pcd->cfi->ctrl_req;
49084 +
49085 +                       if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
49086 +                               if (ctrlreq->bRequest > 0xB0
49087 +                                   && ctrlreq->bRequest < 0xBF) {
49088 +
49089 +                                       /* Return if the PCD failed to handle the request */
49090 +                                       if ((retval =
49091 +                                            pcd->cfi->ops.
49092 +                                            ctrl_write_complete(pcd->cfi,
49093 +                                                                pcd)) < 0) {
49094 +                                               CFI_INFO
49095 +                                                   ("ERROR setting a new value in the PCD(%d)\n",
49096 +                                                    retval);
49097 +                                               ep0_do_stall(pcd, retval);
49098 +                                               pcd->ep0_pending = 0;
49099 +                                               return 0;
49100 +                                       }
49101 +
49102 +                                       /* If the gadget needs to be notified on the request */
49103 +                                       if (pcd->cfi->need_gadget_att == 1) {
49104 +                                               //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
49105 +                                               retval =
49106 +                                                   cfi_gadget_setup(pcd,
49107 +                                                                    &pcd->cfi->
49108 +                                                                    ctrl_req);
49109 +
49110 +                                               /* Return from the function if the gadget failed to process
49111 +                                                * the request properly - this should never happen !!!
49112 +                                                */
49113 +                                               if (retval < 0) {
49114 +                                                       CFI_INFO
49115 +                                                           ("ERROR setting a new value in the gadget(%d)\n",
49116 +                                                            retval);
49117 +                                                       pcd->ep0_pending = 0;
49118 +                                                       return 0;
49119 +                                               }
49120 +                                       }
49121 +
49122 +                                       CFI_INFO("%s: RETVAL=%d\n", __func__,
49123 +                                                retval);
49124 +                                       /* If we hit here then the PCD and the gadget has properly
49125 +                                        * handled the request - so send the ZLP IN to the host.
49126 +                                        */
49127 +                                       /* @todo: MAS - decide whether we need to start the setup
49128 +                                        * stage based on the need_setup value of the cfi object
49129 +                                        */
49130 +                                       do_setup_in_status_phase(pcd);
49131 +                                       pcd->ep0_pending = 0;
49132 +                                       return 1;
49133 +                               }
49134 +                       }
49135 +#endif
49136 +
49137 +                       do_setup_in_status_phase(pcd);
49138 +               }
49139 +               pcd->ep0_pending = 0;
49140 +               return 1;
49141 +       }
49142 +
49143 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49144 +               return 0;
49145 +       }
49146 +       req = DWC_CIRCLEQ_FIRST(&ep->queue);
49147 +
49148 +       if (pcd->ep0state == EP0_OUT_STATUS_PHASE
49149 +           || pcd->ep0state == EP0_IN_STATUS_PHASE) {
49150 +               is_last = 1;
49151 +       } else if (ep->dwc_ep.is_in) {
49152 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49153 +               if (core_if->dma_desc_enable != 0)
49154 +                       desc_sts = dev_if->in_desc_addr->status;
49155 +#ifdef DEBUG_EP0
49156 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",
49157 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49158 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49159 +#endif
49160 +
49161 +               if (((core_if->dma_desc_enable == 0)
49162 +                    && (deptsiz.b.xfersize == 0))
49163 +                   || ((core_if->dma_desc_enable != 0)
49164 +                       && (desc_sts.b.bytes == 0))) {
49165 +                       req->actual = ep->dwc_ep.xfer_count;
49166 +                       /* Is a Zero Len Packet needed? */
49167 +                       if (req->sent_zlp) {
49168 +#ifdef DEBUG_EP0
49169 +                               DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
49170 +#endif
49171 +                               req->sent_zlp = 0;
49172 +                       }
49173 +                       do_setup_out_status_phase(pcd);
49174 +               }
49175 +       } else {
49176 +               /* ep0-OUT */
49177 +#ifdef DEBUG_EP0
49178 +               deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
49179 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
49180 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49181 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49182 +#endif
49183 +               req->actual = ep->dwc_ep.xfer_count;
49184 +
49185 +               /* Is a Zero Len Packet needed? */
49186 +               if (req->sent_zlp) {
49187 +#ifdef DEBUG_EP0
49188 +                       DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
49189 +#endif
49190 +                       req->sent_zlp = 0;
49191 +               }
49192 +               /* For older cores do setup in status phase in Slave/BDMA modes,
49193 +                * starting from 3.00 do that only in slave, and for DMA modes
49194 +                * just re-enable ep 0 OUT here*/
49195 +               if (core_if->dma_enable == 0
49196 +                   || (core_if->dma_desc_enable == 0
49197 +                       && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
49198 +                       do_setup_in_status_phase(pcd);
49199 +               } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
49200 +                       DWC_DEBUGPL(DBG_PCDV,
49201 +                                   "Enable out ep before in status phase\n");
49202 +                       ep0_out_start(core_if, pcd);
49203 +               }
49204 +       }
49205 +
49206 +       /* Complete the request */
49207 +       if (is_last) {
49208 +               dwc_otg_request_done(ep, req, 0);
49209 +               ep->dwc_ep.start_xfer_buff = 0;
49210 +               ep->dwc_ep.xfer_buff = 0;
49211 +               ep->dwc_ep.xfer_len = 0;
49212 +               return 1;
49213 +       }
49214 +       return 0;
49215 +}
49216 +
49217 +#ifdef DWC_UTE_CFI
49218 +/**
49219 + * This function calculates traverses all the CFI DMA descriptors and
49220 + * and accumulates the bytes that are left to be transfered.
49221 + *
49222 + * @return The total bytes left to transfered, or a negative value as failure
49223 + */
49224 +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
49225 +{
49226 +       int32_t ret = 0;
49227 +       int i;
49228 +       struct dwc_otg_dma_desc *ddesc = NULL;
49229 +       struct cfi_ep *cfiep;
49230 +
49231 +       /* See if the pcd_ep has its respective cfi_ep mapped */
49232 +       cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
49233 +       if (!cfiep) {
49234 +               CFI_INFO("%s: Failed to find ep\n", __func__);
49235 +               return -1;
49236 +       }
49237 +
49238 +       ddesc = ep->dwc_ep.descs;
49239 +
49240 +       for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
49241 +
49242 +#if defined(PRINT_CFI_DMA_DESCS)
49243 +               print_desc(ddesc, ep->ep.name, i);
49244 +#endif
49245 +               ret += ddesc->status.b.bytes;
49246 +               ddesc++;
49247 +       }
49248 +
49249 +       if (ret)
49250 +               CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
49251 +                        ret);
49252 +
49253 +       return ret;
49254 +}
49255 +#endif
49256 +
49257 +/**
49258 + * This function completes the request for the EP. If there are
49259 + * additional requests for the EP in the queue they will be started.
49260 + */
49261 +static void complete_ep(dwc_otg_pcd_ep_t * ep)
49262 +{
49263 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49264 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49265 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49266 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49267 +       deptsiz_data_t deptsiz;
49268 +       dev_dma_desc_sts_t desc_sts;
49269 +       dwc_otg_pcd_request_t *req = 0;
49270 +       dwc_otg_dev_dma_desc_t *dma_desc;
49271 +       uint32_t byte_count = 0;
49272 +       int is_last = 0;
49273 +       int i;
49274 +
49275 +       DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
49276 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"));
49277 +
49278 +       /* Get any pending requests */
49279 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49280 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
49281 +               if (!req) {
49282 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
49283 +                       return;
49284 +               }
49285 +       } else {
49286 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
49287 +               return;
49288 +       }
49289 +
49290 +       DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
49291 +
49292 +       if (ep->dwc_ep.is_in) {
49293 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49294 +
49295 +               if (core_if->dma_enable) {
49296 +                       if (core_if->dma_desc_enable == 0) {
49297 +                               if (deptsiz.b.xfersize == 0
49298 +                                   && deptsiz.b.pktcnt == 0) {
49299 +                                       byte_count =
49300 +                                           ep->dwc_ep.xfer_len -
49301 +                                           ep->dwc_ep.xfer_count;
49302 +
49303 +                                       ep->dwc_ep.xfer_buff += byte_count;
49304 +                                       ep->dwc_ep.dma_addr += byte_count;
49305 +                                       ep->dwc_ep.xfer_count += byte_count;
49306 +
49307 +                                       DWC_DEBUGPL(DBG_PCDV,
49308 +                                                   "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49309 +                                                   ep->dwc_ep.num,
49310 +                                                   (ep->dwc_ep.
49311 +                                                    is_in ? "IN" : "OUT"),
49312 +                                                   ep->dwc_ep.xfer_len,
49313 +                                                   deptsiz.b.xfersize,
49314 +                                                   deptsiz.b.pktcnt);
49315 +
49316 +                                       if (ep->dwc_ep.xfer_len <
49317 +                                           ep->dwc_ep.total_len) {
49318 +                                               dwc_otg_ep_start_transfer
49319 +                                                   (core_if, &ep->dwc_ep);
49320 +                                       } else if (ep->dwc_ep.sent_zlp) {
49321 +                                               /*
49322 +                                                * This fragment of code should initiate 0
49323 +                                                * length transfer in case if it is queued
49324 +                                                * a transfer with size divisible to EPs max
49325 +                                                * packet size and with usb_request zero field
49326 +                                                * is set, which means that after data is transfered,
49327 +                                                * it is also should be transfered
49328 +                                                * a 0 length packet at the end. For Slave and
49329 +                                                * Buffer DMA modes in this case SW has
49330 +                                                * to initiate 2 transfers one with transfer size,
49331 +                                                * and the second with 0 size. For Descriptor
49332 +                                                * DMA mode SW is able to initiate a transfer,
49333 +                                                * which will handle all the packets including
49334 +                                                * the last  0 length.
49335 +                                                */
49336 +                                               ep->dwc_ep.sent_zlp = 0;
49337 +                                               dwc_otg_ep_start_zl_transfer
49338 +                                                   (core_if, &ep->dwc_ep);
49339 +                                       } else {
49340 +                                               is_last = 1;
49341 +                                       }
49342 +                               } else {
49343 +                                       if (ep->dwc_ep.type ==
49344 +                                           DWC_OTG_EP_TYPE_ISOC) {
49345 +                                               req->actual = 0;
49346 +                                               dwc_otg_request_done(ep, req, 0);
49347 +
49348 +                                               ep->dwc_ep.start_xfer_buff = 0;
49349 +                                               ep->dwc_ep.xfer_buff = 0;
49350 +                                               ep->dwc_ep.xfer_len = 0;
49351 +
49352 +                                               /* If there is a request in the queue start it. */
49353 +                                               start_next_request(ep);
49354 +                                       } else
49355 +                                               DWC_WARN
49356 +                                               ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
49357 +                                               ep->dwc_ep.num,
49358 +                                               (ep->dwc_ep.is_in ? "IN" : "OUT"),
49359 +                                               deptsiz.b.xfersize,
49360 +                                               deptsiz.b.pktcnt);
49361 +                               }
49362 +                       } else {
49363 +                               dma_desc = ep->dwc_ep.desc_addr;
49364 +                               byte_count = 0;
49365 +                               ep->dwc_ep.sent_zlp = 0;
49366 +
49367 +#ifdef DWC_UTE_CFI
49368 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49369 +                                        ep->dwc_ep.buff_mode);
49370 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49371 +                                       int residue;
49372 +
49373 +                                       residue = cfi_calc_desc_residue(ep);
49374 +                                       if (residue < 0)
49375 +                                               return;
49376 +
49377 +                                       byte_count = residue;
49378 +                               } else {
49379 +#endif
49380 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49381 +                                            ++i) {
49382 +                                       desc_sts = dma_desc->status;
49383 +                                       byte_count += desc_sts.b.bytes;
49384 +                                       dma_desc++;
49385 +                               }
49386 +#ifdef DWC_UTE_CFI
49387 +                               }
49388 +#endif
49389 +                               if (byte_count == 0) {
49390 +                                       ep->dwc_ep.xfer_count =
49391 +                                           ep->dwc_ep.total_len;
49392 +                                       is_last = 1;
49393 +                               } else {
49394 +                                       DWC_WARN("Incomplete transfer\n");
49395 +                               }
49396 +                       }
49397 +               } else {
49398 +                       if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
49399 +                               DWC_DEBUGPL(DBG_PCDV,
49400 +                                           "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49401 +                                           ep->dwc_ep.num,
49402 +                                           ep->dwc_ep.is_in ? "IN" : "OUT",
49403 +                                           ep->dwc_ep.xfer_len,
49404 +                                           deptsiz.b.xfersize,
49405 +                                           deptsiz.b.pktcnt);
49406 +
49407 +                               /*      Check if the whole transfer was completed,
49408 +                                *      if no, setup transfer for next portion of data
49409 +                                */
49410 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49411 +                                       dwc_otg_ep_start_transfer(core_if,
49412 +                                                                 &ep->dwc_ep);
49413 +                               } else if (ep->dwc_ep.sent_zlp) {
49414 +                                       /*
49415 +                                        * This fragment of code should initiate 0
49416 +                                        * length trasfer in case if it is queued
49417 +                                        * a trasfer with size divisible to EPs max
49418 +                                        * packet size and with usb_request zero field
49419 +                                        * is set, which means that after data is transfered,
49420 +                                        * it is also should be transfered
49421 +                                        * a 0 length packet at the end. For Slave and
49422 +                                        * Buffer DMA modes in this case SW has
49423 +                                        * to initiate 2 transfers one with transfer size,
49424 +                                        * and the second with 0 size. For Desriptor
49425 +                                        * DMA mode SW is able to initiate a transfer,
49426 +                                        * which will handle all the packets including
49427 +                                        * the last  0 legth.
49428 +                                        */
49429 +                                       ep->dwc_ep.sent_zlp = 0;
49430 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49431 +                                                                    &ep->dwc_ep);
49432 +                               } else {
49433 +                                       is_last = 1;
49434 +                               }
49435 +                       } else {
49436 +                               DWC_WARN
49437 +                                   ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
49438 +                                    ep->dwc_ep.num,
49439 +                                    (ep->dwc_ep.is_in ? "IN" : "OUT"),
49440 +                                    deptsiz.b.xfersize, deptsiz.b.pktcnt);
49441 +                       }
49442 +               }
49443 +       } else {
49444 +               dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49445 +                   dev_if->out_ep_regs[ep->dwc_ep.num];
49446 +               desc_sts.d32 = 0;
49447 +               if (core_if->dma_enable) {
49448 +                       if (core_if->dma_desc_enable) {
49449 +                               dma_desc = ep->dwc_ep.desc_addr;
49450 +                               byte_count = 0;
49451 +                               ep->dwc_ep.sent_zlp = 0;
49452 +
49453 +#ifdef DWC_UTE_CFI
49454 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49455 +                                        ep->dwc_ep.buff_mode);
49456 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49457 +                                       int residue;
49458 +                                       residue = cfi_calc_desc_residue(ep);
49459 +                                       if (residue < 0)
49460 +                                               return;
49461 +                                       byte_count = residue;
49462 +                               } else {
49463 +#endif
49464 +
49465 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49466 +                                            ++i) {
49467 +                                               desc_sts = dma_desc->status;
49468 +                                               byte_count += desc_sts.b.bytes;
49469 +                                               dma_desc++;
49470 +                                       }
49471 +
49472 +#ifdef DWC_UTE_CFI
49473 +                               }
49474 +#endif
49475 +                               /* Checking for interrupt Out transfers with not
49476 +                                * dword aligned mps sizes
49477 +                                */
49478 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
49479 +                                                       (ep->dwc_ep.maxpacket%4)) {
49480 +                                       ep->dwc_ep.xfer_count =
49481 +                                           ep->dwc_ep.total_len - byte_count;
49482 +                                       if ((ep->dwc_ep.xfer_len %
49483 +                                            ep->dwc_ep.maxpacket)
49484 +                                           && (ep->dwc_ep.xfer_len /
49485 +                                               ep->dwc_ep.maxpacket <
49486 +                                               MAX_DMA_DESC_CNT))
49487 +                                               ep->dwc_ep.xfer_len -=
49488 +                                                   (ep->dwc_ep.desc_cnt -
49489 +                                                    1) * ep->dwc_ep.maxpacket +
49490 +                                                   ep->dwc_ep.xfer_len %
49491 +                                                   ep->dwc_ep.maxpacket;
49492 +                                       else
49493 +                                               ep->dwc_ep.xfer_len -=
49494 +                                                   ep->dwc_ep.desc_cnt *
49495 +                                                   ep->dwc_ep.maxpacket;
49496 +                                       if (ep->dwc_ep.xfer_len > 0) {
49497 +                                               dwc_otg_ep_start_transfer
49498 +                                                   (core_if, &ep->dwc_ep);
49499 +                                       } else {
49500 +                                               is_last = 1;
49501 +                                       }
49502 +                               } else {
49503 +                                       ep->dwc_ep.xfer_count =
49504 +                                           ep->dwc_ep.total_len - byte_count +
49505 +                                           ((4 -
49506 +                                             (ep->dwc_ep.
49507 +                                              total_len & 0x3)) & 0x3);
49508 +                                       is_last = 1;
49509 +                               }
49510 +                       } else {
49511 +                               deptsiz.d32 = 0;
49512 +                               deptsiz.d32 =
49513 +                                   DWC_READ_REG32(&out_ep_regs->doeptsiz);
49514 +
49515 +                               byte_count = (ep->dwc_ep.xfer_len -
49516 +                                             ep->dwc_ep.xfer_count -
49517 +                                             deptsiz.b.xfersize);
49518 +                               ep->dwc_ep.xfer_buff += byte_count;
49519 +                               ep->dwc_ep.dma_addr += byte_count;
49520 +                               ep->dwc_ep.xfer_count += byte_count;
49521 +
49522 +                               /*      Check if the whole transfer was completed,
49523 +                                *      if no, setup transfer for next portion of data
49524 +                                */
49525 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49526 +                                       dwc_otg_ep_start_transfer(core_if,
49527 +                                                                 &ep->dwc_ep);
49528 +                               } else if (ep->dwc_ep.sent_zlp) {
49529 +                                       /*
49530 +                                        * This fragment of code should initiate 0
49531 +                                        * length trasfer in case if it is queued
49532 +                                        * a trasfer with size divisible to EPs max
49533 +                                        * packet size and with usb_request zero field
49534 +                                        * is set, which means that after data is transfered,
49535 +                                        * it is also should be transfered
49536 +                                        * a 0 length packet at the end. For Slave and
49537 +                                        * Buffer DMA modes in this case SW has
49538 +                                        * to initiate 2 transfers one with transfer size,
49539 +                                        * and the second with 0 size. For Desriptor
49540 +                                        * DMA mode SW is able to initiate a transfer,
49541 +                                        * which will handle all the packets including
49542 +                                        * the last  0 legth.
49543 +                                        */
49544 +                                       ep->dwc_ep.sent_zlp = 0;
49545 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49546 +                                                                    &ep->dwc_ep);
49547 +                               } else {
49548 +                                       is_last = 1;
49549 +                               }
49550 +                       }
49551 +               } else {
49552 +                       /*      Check if the whole transfer was completed,
49553 +                        *      if no, setup transfer for next portion of data
49554 +                        */
49555 +                       if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49556 +                               dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
49557 +                       } else if (ep->dwc_ep.sent_zlp) {
49558 +                               /*
49559 +                                * This fragment of code should initiate 0
49560 +                                * length transfer in case if it is queued
49561 +                                * a transfer with size divisible to EPs max
49562 +                                * packet size and with usb_request zero field
49563 +                                * is set, which means that after data is transfered,
49564 +                                * it is also should be transfered
49565 +                                * a 0 length packet at the end. For Slave and
49566 +                                * Buffer DMA modes in this case SW has
49567 +                                * to initiate 2 transfers one with transfer size,
49568 +                                * and the second with 0 size. For Descriptor
49569 +                                * DMA mode SW is able to initiate a transfer,
49570 +                                * which will handle all the packets including
49571 +                                * the last  0 length.
49572 +                                */
49573 +                               ep->dwc_ep.sent_zlp = 0;
49574 +                               dwc_otg_ep_start_zl_transfer(core_if,
49575 +                                                            &ep->dwc_ep);
49576 +                       } else {
49577 +                               is_last = 1;
49578 +                       }
49579 +               }
49580 +
49581 +               DWC_DEBUGPL(DBG_PCDV,
49582 +                           "addr %p,    %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
49583 +                           &out_ep_regs->doeptsiz, ep->dwc_ep.num,
49584 +                           ep->dwc_ep.is_in ? "IN" : "OUT",
49585 +                           ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
49586 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49587 +       }
49588 +
49589 +       /* Complete the request */
49590 +       if (is_last) {
49591 +#ifdef DWC_UTE_CFI
49592 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49593 +                       req->actual = ep->dwc_ep.cfi_req_len - byte_count;
49594 +               } else {
49595 +#endif
49596 +                       req->actual = ep->dwc_ep.xfer_count;
49597 +#ifdef DWC_UTE_CFI
49598 +               }
49599 +#endif
49600 +               if (req->dw_align_buf) {
49601 +                       if (!ep->dwc_ep.is_in) {
49602 +                               dwc_memcpy(req->buf, req->dw_align_buf, req->length);
49603 +                       }
49604 +                       DWC_DMA_FREE(req->length, req->dw_align_buf,
49605 +                                    req->dw_align_buf_dma);
49606 +               }
49607 +
49608 +               dwc_otg_request_done(ep, req, 0);
49609 +
49610 +               ep->dwc_ep.start_xfer_buff = 0;
49611 +               ep->dwc_ep.xfer_buff = 0;
49612 +               ep->dwc_ep.xfer_len = 0;
49613 +
49614 +               /* If there is a request in the queue start it. */
49615 +               start_next_request(ep);
49616 +       }
49617 +}
49618 +
49619 +#ifdef DWC_EN_ISOC
49620 +
49621 +/**
49622 + * This function BNA interrupt for Isochronous EPs
49623 + *
49624 + */
49625 +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
49626 +{
49627 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
49628 +       volatile uint32_t *addr;
49629 +       depctl_data_t depctl = {.d32 = 0 };
49630 +       dwc_otg_pcd_t *pcd = ep->pcd;
49631 +       dwc_otg_dev_dma_desc_t *dma_desc;
49632 +       int i;
49633 +
49634 +       dma_desc =
49635 +           dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
49636 +
49637 +       if (dwc_ep->is_in) {
49638 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49639 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49640 +                       sts.d32 = dma_desc->status.d32;
49641 +                       sts.b_iso_in.bs = BS_HOST_READY;
49642 +                       dma_desc->status.d32 = sts.d32;
49643 +               }
49644 +       } else {
49645 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49646 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49647 +                       sts.d32 = dma_desc->status.d32;
49648 +                       sts.b_iso_out.bs = BS_HOST_READY;
49649 +                       dma_desc->status.d32 = sts.d32;
49650 +               }
49651 +       }
49652 +
49653 +       if (dwc_ep->is_in == 0) {
49654 +               addr =
49655 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
49656 +                                                          num]->doepctl;
49657 +       } else {
49658 +               addr =
49659 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
49660 +       }
49661 +       depctl.b.epena = 1;
49662 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
49663 +}
49664 +
49665 +/**
49666 + * This function sets latest iso packet information(non-PTI mode)
49667 + *
49668 + * @param core_if Programming view of DWC_otg controller.
49669 + * @param ep The EP to start the transfer on.
49670 + *
49671 + */
49672 +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
49673 +{
49674 +       deptsiz_data_t deptsiz = {.d32 = 0 };
49675 +       dma_addr_t dma_addr;
49676 +       uint32_t offset;
49677 +
49678 +       if (ep->proc_buf_num)
49679 +               dma_addr = ep->dma_addr1;
49680 +       else
49681 +               dma_addr = ep->dma_addr0;
49682 +
49683 +       if (ep->is_in) {
49684 +               deptsiz.d32 =
49685 +                   DWC_READ_REG32(&core_if->dev_if->
49686 +                                  in_ep_regs[ep->num]->dieptsiz);
49687 +               offset = ep->data_per_frame;
49688 +       } else {
49689 +               deptsiz.d32 =
49690 +                   DWC_READ_REG32(&core_if->dev_if->
49691 +                                  out_ep_regs[ep->num]->doeptsiz);
49692 +               offset =
49693 +                   ep->data_per_frame +
49694 +                   (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
49695 +       }
49696 +
49697 +       if (!deptsiz.b.xfersize) {
49698 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49699 +               ep->pkt_info[ep->cur_pkt].offset =
49700 +                   ep->cur_pkt_dma_addr - dma_addr;
49701 +               ep->pkt_info[ep->cur_pkt].status = 0;
49702 +       } else {
49703 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49704 +               ep->pkt_info[ep->cur_pkt].offset =
49705 +                   ep->cur_pkt_dma_addr - dma_addr;
49706 +               ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
49707 +       }
49708 +       ep->cur_pkt_addr += offset;
49709 +       ep->cur_pkt_dma_addr += offset;
49710 +       ep->cur_pkt++;
49711 +}
49712 +
49713 +/**
49714 + * This function sets latest iso packet information(DDMA mode)
49715 + *
49716 + * @param core_if Programming view of DWC_otg controller.
49717 + * @param dwc_ep The EP to start the transfer on.
49718 + *
49719 + */
49720 +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
49721 +                                  dwc_ep_t * dwc_ep)
49722 +{
49723 +       dwc_otg_dev_dma_desc_t *dma_desc;
49724 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
49725 +       iso_pkt_info_t *iso_packet;
49726 +       uint32_t data_per_desc;
49727 +       uint32_t offset;
49728 +       int i, j;
49729 +
49730 +       iso_packet = dwc_ep->pkt_info;
49731 +
49732 +       /** Reinit closed DMA Descriptors*/
49733 +       /** ISO OUT EP */
49734 +       if (dwc_ep->is_in == 0) {
49735 +               dma_desc =
49736 +                   dwc_ep->iso_desc_addr +
49737 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49738 +               offset = 0;
49739 +
49740 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
49741 +                    i += dwc_ep->pkt_per_frm) {
49742 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
49743 +                               data_per_desc =
49744 +                                   ((j + 1) * dwc_ep->maxpacket >
49745 +                                    dwc_ep->
49746 +                                    data_per_frame) ? dwc_ep->data_per_frame -
49747 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49748 +                               data_per_desc +=
49749 +                                   (data_per_desc % 4) ? (4 -
49750 +                                                          data_per_desc %
49751 +                                                          4) : 0;
49752 +
49753 +                               sts.d32 = dma_desc->status.d32;
49754 +
49755 +                               /* Write status in iso_packet_decsriptor  */
49756 +                               iso_packet->status =
49757 +                                   sts.b_iso_out.rxsts +
49758 +                                   (sts.b_iso_out.bs ^ BS_DMA_DONE);
49759 +                               if (iso_packet->status) {
49760 +                                       iso_packet->status = -DWC_E_NO_DATA;
49761 +                               }
49762 +
49763 +                               /* Received data length */
49764 +                               if (!sts.b_iso_out.rxbytes) {
49765 +                                       iso_packet->length =
49766 +                                           data_per_desc -
49767 +                                           sts.b_iso_out.rxbytes;
49768 +                               } else {
49769 +                                       iso_packet->length =
49770 +                                           data_per_desc -
49771 +                                           sts.b_iso_out.rxbytes + (4 -
49772 +                                                                    dwc_ep->data_per_frame
49773 +                                                                    % 4);
49774 +                               }
49775 +
49776 +                               iso_packet->offset = offset;
49777 +
49778 +                               offset += data_per_desc;
49779 +                               dma_desc++;
49780 +                               iso_packet++;
49781 +                       }
49782 +               }
49783 +
49784 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
49785 +                       data_per_desc =
49786 +                           ((j + 1) * dwc_ep->maxpacket >
49787 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49788 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49789 +                       data_per_desc +=
49790 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49791 +
49792 +                       sts.d32 = dma_desc->status.d32;
49793 +
49794 +                       /* Write status in iso_packet_decsriptor  */
49795 +                       iso_packet->status =
49796 +                           sts.b_iso_out.rxsts +
49797 +                           (sts.b_iso_out.bs ^ BS_DMA_DONE);
49798 +                       if (iso_packet->status) {
49799 +                               iso_packet->status = -DWC_E_NO_DATA;
49800 +                       }
49801 +
49802 +                       /* Received data length */
49803 +                       iso_packet->length =
49804 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49805 +
49806 +                       iso_packet->offset = offset;
49807 +
49808 +                       offset += data_per_desc;
49809 +                       iso_packet++;
49810 +                       dma_desc++;
49811 +               }
49812 +
49813 +               sts.d32 = dma_desc->status.d32;
49814 +
49815 +               /* Write status in iso_packet_decsriptor  */
49816 +               iso_packet->status =
49817 +                   sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
49818 +               if (iso_packet->status) {
49819 +                       iso_packet->status = -DWC_E_NO_DATA;
49820 +               }
49821 +               /* Received data length */
49822 +               if (!sts.b_iso_out.rxbytes) {
49823 +                       iso_packet->length =
49824 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49825 +               } else {
49826 +                       iso_packet->length =
49827 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
49828 +                           (4 - dwc_ep->data_per_frame % 4);
49829 +               }
49830 +
49831 +               iso_packet->offset = offset;
49832 +       } else {
49833 +/** ISO IN EP */
49834 +
49835 +               dma_desc =
49836 +                   dwc_ep->iso_desc_addr +
49837 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49838 +
49839 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
49840 +                       sts.d32 = dma_desc->status.d32;
49841 +
49842 +                       /* Write status in iso packet descriptor */
49843 +                       iso_packet->status =
49844 +                           sts.b_iso_in.txsts +
49845 +                           (sts.b_iso_in.bs ^ BS_DMA_DONE);
49846 +                       if (iso_packet->status != 0) {
49847 +                               iso_packet->status = -DWC_E_NO_DATA;
49848 +
49849 +                       }
49850 +                       /* Bytes has been transfered */
49851 +                       iso_packet->length =
49852 +                           dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
49853 +
49854 +                       dma_desc++;
49855 +                       iso_packet++;
49856 +               }
49857 +
49858 +               sts.d32 = dma_desc->status.d32;
49859 +               while (sts.b_iso_in.bs == BS_DMA_BUSY) {
49860 +                       sts.d32 = dma_desc->status.d32;
49861 +               }
49862 +
49863 +               /* Write status in iso packet descriptor ??? do be done with ERROR codes */
49864 +               iso_packet->status =
49865 +                   sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
49866 +               if (iso_packet->status != 0) {
49867 +                       iso_packet->status = -DWC_E_NO_DATA;
49868 +               }
49869 +
49870 +               /* Bytes has been transfered */
49871 +               iso_packet->length =
49872 +                   dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
49873 +       }
49874 +}
49875 +
49876 +/**
49877 + * This function reinitialize DMA Descriptors for Isochronous transfer
49878 + *
49879 + * @param core_if Programming view of DWC_otg controller.
49880 + * @param dwc_ep The EP to start the transfer on.
49881 + *
49882 + */
49883 +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
49884 +{
49885 +       int i, j;
49886 +       dwc_otg_dev_dma_desc_t *dma_desc;
49887 +       dma_addr_t dma_ad;
49888 +       volatile uint32_t *addr;
49889 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
49890 +       uint32_t data_per_desc;
49891 +
49892 +       if (dwc_ep->is_in == 0) {
49893 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
49894 +       } else {
49895 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
49896 +       }
49897 +
49898 +       if (dwc_ep->proc_buf_num == 0) {
49899 +               /** Buffer 0 descriptors setup */
49900 +               dma_ad = dwc_ep->dma_addr0;
49901 +       } else {
49902 +               /** Buffer 1 descriptors setup */
49903 +               dma_ad = dwc_ep->dma_addr1;
49904 +       }
49905 +
49906 +       /** Reinit closed DMA Descriptors*/
49907 +       /** ISO OUT EP */
49908 +       if (dwc_ep->is_in == 0) {
49909 +               dma_desc =
49910 +                   dwc_ep->iso_desc_addr +
49911 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49912 +
49913 +               sts.b_iso_out.bs = BS_HOST_READY;
49914 +               sts.b_iso_out.rxsts = 0;
49915 +               sts.b_iso_out.l = 0;
49916 +               sts.b_iso_out.sp = 0;
49917 +               sts.b_iso_out.ioc = 0;
49918 +               sts.b_iso_out.pid = 0;
49919 +               sts.b_iso_out.framenum = 0;
49920 +
49921 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
49922 +                    i += dwc_ep->pkt_per_frm) {
49923 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
49924 +                               data_per_desc =
49925 +                                   ((j + 1) * dwc_ep->maxpacket >
49926 +                                    dwc_ep->
49927 +                                    data_per_frame) ? dwc_ep->data_per_frame -
49928 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49929 +                               data_per_desc +=
49930 +                                   (data_per_desc % 4) ? (4 -
49931 +                                                          data_per_desc %
49932 +                                                          4) : 0;
49933 +                               sts.b_iso_out.rxbytes = data_per_desc;
49934 +                               dma_desc->buf = dma_ad;
49935 +                               dma_desc->status.d32 = sts.d32;
49936 +
49937 +                               dma_ad += data_per_desc;
49938 +                               dma_desc++;
49939 +                       }
49940 +               }
49941 +
49942 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
49943 +
49944 +                       data_per_desc =
49945 +                           ((j + 1) * dwc_ep->maxpacket >
49946 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49947 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49948 +                       data_per_desc +=
49949 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49950 +                       sts.b_iso_out.rxbytes = data_per_desc;
49951 +
49952 +                       dma_desc->buf = dma_ad;
49953 +                       dma_desc->status.d32 = sts.d32;
49954 +
49955 +                       dma_desc++;
49956 +                       dma_ad += data_per_desc;
49957 +               }
49958 +
49959 +               sts.b_iso_out.ioc = 1;
49960 +               sts.b_iso_out.l = dwc_ep->proc_buf_num;
49961 +
49962 +               data_per_desc =
49963 +                   ((j + 1) * dwc_ep->maxpacket >
49964 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49965 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49966 +               data_per_desc +=
49967 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49968 +               sts.b_iso_out.rxbytes = data_per_desc;
49969 +
49970 +               dma_desc->buf = dma_ad;
49971 +               dma_desc->status.d32 = sts.d32;
49972 +       } else {
49973 +/** ISO IN EP */
49974 +
49975 +               dma_desc =
49976 +                   dwc_ep->iso_desc_addr +
49977 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49978 +
49979 +               sts.b_iso_in.bs = BS_HOST_READY;
49980 +               sts.b_iso_in.txsts = 0;
49981 +               sts.b_iso_in.sp = 0;
49982 +               sts.b_iso_in.ioc = 0;
49983 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
49984 +               sts.b_iso_in.framenum = dwc_ep->next_frame;
49985 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
49986 +               sts.b_iso_in.l = 0;
49987 +
49988 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
49989 +                       dma_desc->buf = dma_ad;
49990 +                       dma_desc->status.d32 = sts.d32;
49991 +
49992 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
49993 +                       dma_ad += dwc_ep->data_per_frame;
49994 +                       dma_desc++;
49995 +               }
49996 +
49997 +               sts.b_iso_in.ioc = 1;
49998 +               sts.b_iso_in.l = dwc_ep->proc_buf_num;
49999 +
50000 +               dma_desc->buf = dma_ad;
50001 +               dma_desc->status.d32 = sts.d32;
50002 +
50003 +               dwc_ep->next_frame =
50004 +                   sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
50005 +       }
50006 +       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50007 +}
50008 +
50009 +/**
50010 + * This function is to handle Iso EP transfer complete interrupt
50011 + * in case Iso out packet was dropped
50012 + *
50013 + * @param core_if Programming view of DWC_otg controller.
50014 + * @param dwc_ep The EP for wihich transfer complete was asserted
50015 + *
50016 + */
50017 +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
50018 +                                          dwc_ep_t * dwc_ep)
50019 +{
50020 +       uint32_t dma_addr;
50021 +       uint32_t drp_pkt;
50022 +       uint32_t drp_pkt_cnt;
50023 +       deptsiz_data_t deptsiz = {.d32 = 0 };
50024 +       depctl_data_t depctl = {.d32 = 0 };
50025 +       int i;
50026 +
50027 +       deptsiz.d32 =
50028 +           DWC_READ_REG32(&core_if->dev_if->
50029 +                          out_ep_regs[dwc_ep->num]->doeptsiz);
50030 +
50031 +       drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
50032 +       drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
50033 +
50034 +       /* Setting dropped packets status */
50035 +       for (i = 0; i < drp_pkt_cnt; ++i) {
50036 +               dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
50037 +               drp_pkt++;
50038 +               deptsiz.b.pktcnt--;
50039 +       }
50040 +
50041 +       if (deptsiz.b.pktcnt > 0) {
50042 +               deptsiz.b.xfersize =
50043 +                   dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
50044 +                                       deptsiz.b.pktcnt) * dwc_ep->maxpacket;
50045 +       } else {
50046 +               deptsiz.b.xfersize = 0;
50047 +               deptsiz.b.pktcnt = 0;
50048 +       }
50049 +
50050 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
50051 +                       deptsiz.d32);
50052 +
50053 +       if (deptsiz.b.pktcnt > 0) {
50054 +               if (dwc_ep->proc_buf_num) {
50055 +                       dma_addr =
50056 +                           dwc_ep->dma_addr1 + dwc_ep->xfer_len -
50057 +                           deptsiz.b.xfersize;
50058 +               } else {
50059 +                       dma_addr =
50060 +                           dwc_ep->dma_addr0 + dwc_ep->xfer_len -
50061 +                           deptsiz.b.xfersize;;
50062 +               }
50063 +
50064 +               DWC_WRITE_REG32(&core_if->dev_if->
50065 +                               out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
50066 +
50067 +               /** Re-enable endpoint, clear nak  */
50068 +               depctl.d32 = 0;
50069 +               depctl.b.epena = 1;
50070 +               depctl.b.cnak = 1;
50071 +
50072 +               DWC_MODIFY_REG32(&core_if->dev_if->
50073 +                                out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
50074 +                                depctl.d32);
50075 +               return 0;
50076 +       } else {
50077 +               return 1;
50078 +       }
50079 +}
50080 +
50081 +/**
50082 + * This function sets iso packets information(PTI mode)
50083 + *
50084 + * @param core_if Programming view of DWC_otg controller.
50085 + * @param ep The EP to start the transfer on.
50086 + *
50087 + */
50088 +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
50089 +{
50090 +       int i, j;
50091 +       dma_addr_t dma_ad;
50092 +       iso_pkt_info_t *packet_info = ep->pkt_info;
50093 +       uint32_t offset;
50094 +       uint32_t frame_data;
50095 +       deptsiz_data_t deptsiz;
50096 +
50097 +       if (ep->proc_buf_num == 0) {
50098 +               /** Buffer 0 descriptors setup */
50099 +               dma_ad = ep->dma_addr0;
50100 +       } else {
50101 +               /** Buffer 1 descriptors setup */
50102 +               dma_ad = ep->dma_addr1;
50103 +       }
50104 +
50105 +       if (ep->is_in) {
50106 +               deptsiz.d32 =
50107 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
50108 +                                  dieptsiz);
50109 +       } else {
50110 +               deptsiz.d32 =
50111 +                   DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
50112 +                                  doeptsiz);
50113 +       }
50114 +
50115 +       if (!deptsiz.b.xfersize) {
50116 +               offset = 0;
50117 +               for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
50118 +                       frame_data = ep->data_per_frame;
50119 +                       for (j = 0; j < ep->pkt_per_frm; ++j) {
50120 +
50121 +                               /* Packet status - is not set as initially
50122 +                                * it is set to 0 and if packet was sent
50123 +                                successfully, status field will remain 0*/
50124 +
50125 +                               /* Bytes has been transfered */
50126 +                               packet_info->length =
50127 +                                   (ep->maxpacket <
50128 +                                    frame_data) ? ep->maxpacket : frame_data;
50129 +
50130 +                               /* Received packet offset */
50131 +                               packet_info->offset = offset;
50132 +                               offset += packet_info->length;
50133 +                               frame_data -= packet_info->length;
50134 +
50135 +                               packet_info++;
50136 +                       }
50137 +               }
50138 +               return 1;
50139 +       } else {
50140 +               /* This is a workaround for in case of Transfer Complete with
50141 +                * PktDrpSts interrupts merging - in this case Transfer complete
50142 +                * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
50143 +                * set and with DOEPTSIZ register non zero. Investigations showed,
50144 +                * that this happens when Out packet is dropped, but because of
50145 +                * interrupts merging during first interrupt handling PktDrpSts
50146 +                * bit is cleared and for next merged interrupts it is not reset.
50147 +                * In this case SW hadles the interrupt as if PktDrpSts bit is set.
50148 +                */
50149 +               if (ep->is_in) {
50150 +                       return 1;
50151 +               } else {
50152 +                       return handle_iso_out_pkt_dropped(core_if, ep);
50153 +               }
50154 +       }
50155 +}
50156 +
50157 +/**
50158 + * This function is to handle Iso EP transfer complete interrupt
50159 + *
50160 + * @param pcd The PCD
50161 + * @param ep The EP for which transfer complete was asserted
50162 + *
50163 + */
50164 +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
50165 +{
50166 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
50167 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50168 +       uint8_t is_last = 0;
50169 +
50170 +       if (ep->dwc_ep.next_frame == 0xffffffff) {
50171 +               DWC_WARN("Next frame is not set!\n");
50172 +               return;
50173 +       }
50174 +
50175 +       if (core_if->dma_enable) {
50176 +               if (core_if->dma_desc_enable) {
50177 +                       set_ddma_iso_pkts_info(core_if, dwc_ep);
50178 +                       reinit_ddma_iso_xfer(core_if, dwc_ep);
50179 +                       is_last = 1;
50180 +               } else {
50181 +                       if (core_if->pti_enh_enable) {
50182 +                               if (set_iso_pkts_info(core_if, dwc_ep)) {
50183 +                                       dwc_ep->proc_buf_num =
50184 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50185 +                                       dwc_otg_iso_ep_start_buf_transfer
50186 +                                           (core_if, dwc_ep);
50187 +                                       is_last = 1;
50188 +                               }
50189 +                       } else {
50190 +                               set_current_pkt_info(core_if, dwc_ep);
50191 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50192 +                                       is_last = 1;
50193 +                                       dwc_ep->cur_pkt = 0;
50194 +                                       dwc_ep->proc_buf_num =
50195 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50196 +                                       if (dwc_ep->proc_buf_num) {
50197 +                                               dwc_ep->cur_pkt_addr =
50198 +                                                   dwc_ep->xfer_buff1;
50199 +                                               dwc_ep->cur_pkt_dma_addr =
50200 +                                                   dwc_ep->dma_addr1;
50201 +                                       } else {
50202 +                                               dwc_ep->cur_pkt_addr =
50203 +                                                   dwc_ep->xfer_buff0;
50204 +                                               dwc_ep->cur_pkt_dma_addr =
50205 +                                                   dwc_ep->dma_addr0;
50206 +                                       }
50207 +
50208 +                               }
50209 +                               dwc_otg_iso_ep_start_frm_transfer(core_if,
50210 +                                                                 dwc_ep);
50211 +                       }
50212 +               }
50213 +       } else {
50214 +               set_current_pkt_info(core_if, dwc_ep);
50215 +               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50216 +                       is_last = 1;
50217 +                       dwc_ep->cur_pkt = 0;
50218 +                       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50219 +                       if (dwc_ep->proc_buf_num) {
50220 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
50221 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
50222 +                       } else {
50223 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
50224 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
50225 +                       }
50226 +
50227 +               }
50228 +               dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
50229 +       }
50230 +       if (is_last)
50231 +               dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
50232 +}
50233 +#endif /* DWC_EN_ISOC */
50234 +
50235 +/**
50236 + * This function handle BNA interrupt for Non Isochronous EPs
50237 + *
50238 + */
50239 +static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
50240 +{
50241 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50242 +       volatile uint32_t *addr;
50243 +       depctl_data_t depctl = {.d32 = 0 };
50244 +       dwc_otg_pcd_t *pcd = ep->pcd;
50245 +       dwc_otg_dev_dma_desc_t *dma_desc;
50246 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
50247 +       dwc_otg_core_if_t *core_if = ep->pcd->core_if;
50248 +       int i, start;
50249 +
50250 +       if (!dwc_ep->desc_cnt)
50251 +               DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
50252 +                        (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
50253 +
50254 +       if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
50255 +                                                       && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
50256 +               uint32_t doepdma;
50257 +               dwc_otg_dev_out_ep_regs_t *out_regs =
50258 +                       core_if->dev_if->out_ep_regs[dwc_ep->num];
50259 +               doepdma = DWC_READ_REG32(&(out_regs->doepdma));
50260 +               start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
50261 +               dma_desc = &(dwc_ep->desc_addr[start]);
50262 +       } else {
50263 +               start = 0;
50264 +               dma_desc = dwc_ep->desc_addr;
50265 +       }
50266 +
50267 +
50268 +       for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
50269 +               sts.d32 = dma_desc->status.d32;
50270 +               sts.b.bs = BS_HOST_READY;
50271 +               dma_desc->status.d32 = sts.d32;
50272 +       }
50273 +
50274 +       if (dwc_ep->is_in == 0) {
50275 +               addr =
50276 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
50277 +                   doepctl;
50278 +       } else {
50279 +               addr =
50280 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50281 +       }
50282 +       depctl.b.epena = 1;
50283 +       depctl.b.cnak = 1;
50284 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
50285 +}
50286 +
50287 +/**
50288 + * This function handles EP0 Control transfers.
50289 + *
50290 + * The state of the control transfers are tracked in
50291 + * <code>ep0state</code>.
50292 + */
50293 +static void handle_ep0(dwc_otg_pcd_t * pcd)
50294 +{
50295 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50296 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
50297 +       dev_dma_desc_sts_t desc_sts;
50298 +       deptsiz0_data_t deptsiz;
50299 +       uint32_t byte_count;
50300 +
50301 +#ifdef DEBUG_EP0
50302 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
50303 +       print_ep0_state(pcd);
50304 +#endif
50305 +
50306 +//      DWC_PRINTF("HANDLE EP0\n");
50307 +
50308 +       switch (pcd->ep0state) {
50309 +       case EP0_DISCONNECT:
50310 +               break;
50311 +
50312 +       case EP0_IDLE:
50313 +               pcd->request_config = 0;
50314 +
50315 +               pcd_setup(pcd);
50316 +               break;
50317 +
50318 +       case EP0_IN_DATA_PHASE:
50319 +#ifdef DEBUG_EP0
50320 +               DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
50321 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50322 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50323 +#endif
50324 +
50325 +               if (core_if->dma_enable != 0) {
50326 +                       /*
50327 +                        * For EP0 we can only program 1 packet at a time so we
50328 +                        * need to do the make calculations after each complete.
50329 +                        * Call write_packet to make the calculations, as in
50330 +                        * slave mode, and use those values to determine if we
50331 +                        * can complete.
50332 +                        */
50333 +                       if (core_if->dma_desc_enable == 0) {
50334 +                               deptsiz.d32 =
50335 +                                   DWC_READ_REG32(&core_if->
50336 +                                                  dev_if->in_ep_regs[0]->
50337 +                                                  dieptsiz);
50338 +                               byte_count =
50339 +                                   ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
50340 +                       } else {
50341 +                               desc_sts =
50342 +                                   core_if->dev_if->in_desc_addr->status;
50343 +                               byte_count =
50344 +                                   ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
50345 +                       }
50346 +                       ep0->dwc_ep.xfer_count += byte_count;
50347 +                       ep0->dwc_ep.xfer_buff += byte_count;
50348 +                       ep0->dwc_ep.dma_addr += byte_count;
50349 +               }
50350 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50351 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50352 +                                                     &ep0->dwc_ep);
50353 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50354 +               } else if (ep0->dwc_ep.sent_zlp) {
50355 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50356 +                                                     &ep0->dwc_ep);
50357 +                       ep0->dwc_ep.sent_zlp = 0;
50358 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50359 +               } else {
50360 +                       ep0_complete_request(ep0);
50361 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50362 +               }
50363 +               break;
50364 +       case EP0_OUT_DATA_PHASE:
50365 +#ifdef DEBUG_EP0
50366 +               DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
50367 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50368 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50369 +#endif
50370 +               if (core_if->dma_enable != 0) {
50371 +                       if (core_if->dma_desc_enable == 0) {
50372 +                               deptsiz.d32 =
50373 +                                   DWC_READ_REG32(&core_if->
50374 +                                                  dev_if->out_ep_regs[0]->
50375 +                                                  doeptsiz);
50376 +                               byte_count =
50377 +                                   ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
50378 +                       } else {
50379 +                               desc_sts =
50380 +                                   core_if->dev_if->out_desc_addr->status;
50381 +                               byte_count =
50382 +                                   ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
50383 +                       }
50384 +                       ep0->dwc_ep.xfer_count += byte_count;
50385 +                       ep0->dwc_ep.xfer_buff += byte_count;
50386 +                       ep0->dwc_ep.dma_addr += byte_count;
50387 +               }
50388 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50389 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50390 +                                                     &ep0->dwc_ep);
50391 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50392 +               } else if (ep0->dwc_ep.sent_zlp) {
50393 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50394 +                                                     &ep0->dwc_ep);
50395 +                       ep0->dwc_ep.sent_zlp = 0;
50396 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50397 +               } else {
50398 +                       ep0_complete_request(ep0);
50399 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50400 +               }
50401 +               break;
50402 +
50403 +       case EP0_IN_STATUS_PHASE:
50404 +       case EP0_OUT_STATUS_PHASE:
50405 +               DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
50406 +               ep0_complete_request(ep0);
50407 +               pcd->ep0state = EP0_IDLE;
50408 +               ep0->stopped = 1;
50409 +               ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
50410 +
50411 +               /* Prepare for more SETUP Packets */
50412 +               if (core_if->dma_enable) {
50413 +                       ep0_out_start(core_if, pcd);
50414 +               }
50415 +               break;
50416 +
50417 +       case EP0_STALL:
50418 +               DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
50419 +               break;
50420 +       }
50421 +#ifdef DEBUG_EP0
50422 +       print_ep0_state(pcd);
50423 +#endif
50424 +}
50425 +
50426 +/**
50427 + * Restart transfer
50428 + */
50429 +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
50430 +{
50431 +       dwc_otg_core_if_t *core_if;
50432 +       dwc_otg_dev_if_t *dev_if;
50433 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50434 +       dwc_otg_pcd_ep_t *ep;
50435 +
50436 +       ep = get_in_ep(pcd, epnum);
50437 +
50438 +#ifdef DWC_EN_ISOC
50439 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
50440 +               return;
50441 +       }
50442 +#endif /* DWC_EN_ISOC  */
50443 +
50444 +       core_if = GET_CORE_IF(pcd);
50445 +       dev_if = core_if->dev_if;
50446 +
50447 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50448 +
50449 +       DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
50450 +                   " stopped=%d\n", ep->dwc_ep.xfer_buff,
50451 +                   ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
50452 +       /*
50453 +        * If xfersize is 0 and pktcnt in not 0, resend the last packet.
50454 +        */
50455 +       if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
50456 +           ep->dwc_ep.start_xfer_buff != 0) {
50457 +               if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
50458 +                       ep->dwc_ep.xfer_count = 0;
50459 +                       ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
50460 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50461 +               } else {
50462 +                       ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
50463 +                       /* convert packet size to dwords. */
50464 +                       ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
50465 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50466 +               }
50467 +               ep->stopped = 0;
50468 +               DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
50469 +                           "xfer_len=%0x stopped=%d\n",
50470 +                           ep->dwc_ep.xfer_buff,
50471 +                           ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
50472 +                           ep->stopped);
50473 +               if (epnum == 0) {
50474 +                       dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
50475 +               } else {
50476 +                       dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
50477 +               }
50478 +       }
50479 +}
50480 +
50481 +/*
50482 + * This function create new nextep sequnce based on Learn Queue.
50483 + *
50484 + * @param core_if Programming view of DWC_otg controller
50485 + */
50486 +void predict_nextep_seq( dwc_otg_core_if_t * core_if)
50487 +{
50488 +       dwc_otg_device_global_regs_t *dev_global_regs =
50489 +           core_if->dev_if->dev_global_regs;
50490 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
50491 +       /* Number of Token Queue Registers */
50492 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
50493 +       dtknq1_data_t dtknqr1;
50494 +       uint32_t in_tkn_epnums[4];
50495 +       uint8_t seqnum[MAX_EPS_CHANNELS];
50496 +       uint8_t intkn_seq[TOKEN_Q_DEPTH];
50497 +       grstctl_t resetctl = {.d32 = 0 };
50498 +       uint8_t temp;
50499 +       int ndx = 0;
50500 +       int start = 0;
50501 +       int end = 0;
50502 +       int sort_done = 0;
50503 +       int i = 0;
50504 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
50505 +
50506 +
50507 +       DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
50508 +
50509 +       /* Read the DTKNQ Registers */
50510 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
50511 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
50512 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
50513 +                           in_tkn_epnums[i]);
50514 +               if (addr == &dev_global_regs->dvbusdis) {
50515 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
50516 +               } else {
50517 +                       ++addr;
50518 +               }
50519 +
50520 +       }
50521 +
50522 +       /* Copy the DTKNQR1 data to the bit field. */
50523 +       dtknqr1.d32 = in_tkn_epnums[0];
50524 +       if (dtknqr1.b.wrap_bit) {
50525 +               ndx = dtknqr1.b.intknwptr;
50526 +               end = ndx -1;
50527 +               if (end < 0)
50528 +                       end = TOKEN_Q_DEPTH -1;
50529 +       } else {
50530 +               ndx = 0;
50531 +               end = dtknqr1.b.intknwptr -1;
50532 +               if (end < 0)
50533 +                       end = 0;
50534 +       }
50535 +       start = ndx;
50536 +
50537 +       /* Fill seqnum[] by initial values: EP number + 31 */
50538 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50539 +               seqnum[i] = i +31;
50540 +       }
50541 +
50542 +       /* Fill intkn_seq[] from in_tkn_epnums[0] */
50543 +       for (i=0; i < 6; i++)
50544 +               intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
50545 +
50546 +       if (TOKEN_Q_DEPTH > 6) {
50547 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50548 +               for (i=6; i < 14; i++)
50549 +                       intkn_seq[i] =
50550 +                           (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
50551 +       }
50552 +
50553 +       if (TOKEN_Q_DEPTH > 14) {
50554 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50555 +               for (i=14; i < 22; i++)
50556 +                       intkn_seq[i] =
50557 +                           (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
50558 +       }
50559 +
50560 +       if (TOKEN_Q_DEPTH > 22) {
50561 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50562 +               for (i=22; i < 30; i++)
50563 +                       intkn_seq[i] =
50564 +                           (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
50565 +       }
50566 +
50567 +       DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
50568 +                   start, end);
50569 +       for (i=0; i<TOKEN_Q_DEPTH; i++)
50570 +               DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
50571 +
50572 +       /* Update seqnum based on intkn_seq[] */
50573 +       i = 0;
50574 +       do {
50575 +               seqnum[intkn_seq[ndx]] = i;
50576 +               ndx++;
50577 +               i++;
50578 +               if (ndx == TOKEN_Q_DEPTH)
50579 +                       ndx = 0;
50580 +       } while ( i < TOKEN_Q_DEPTH );
50581 +
50582 +       /* Mark non active EP's in seqnum[] by 0xff */
50583 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50584 +               if (core_if->nextep_seq[i] == 0xff )
50585 +                       seqnum[i] = 0xff;
50586 +       }
50587 +
50588 +       /* Sort seqnum[] */
50589 +       sort_done = 0;
50590 +       while (!sort_done) {
50591 +               sort_done = 1;
50592 +               for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50593 +                       if (seqnum[i] > seqnum[i+1]) {
50594 +                               temp = seqnum[i];
50595 +                               seqnum[i] = seqnum[i+1];
50596 +                               seqnum[i+1] = temp;
50597 +                               sort_done = 0;
50598 +                       }
50599 +               }
50600 +       }
50601 +
50602 +       ndx = start + seqnum[0];
50603 +       if (ndx >= TOKEN_Q_DEPTH)
50604 +               ndx = ndx % TOKEN_Q_DEPTH;
50605 +       core_if->first_in_nextep_seq = intkn_seq[ndx];
50606 +
50607 +       /* Update seqnum[] by EP numbers  */
50608 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50609 +               ndx = start + i;
50610 +               if (seqnum[i] < 31) {
50611 +                       ndx = start + seqnum[i];
50612 +                       if (ndx >= TOKEN_Q_DEPTH)
50613 +                               ndx = ndx % TOKEN_Q_DEPTH;
50614 +                       seqnum[i] = intkn_seq[ndx];
50615 +               } else {
50616 +                       if (seqnum[i] < 0xff) {
50617 +                               seqnum[i] = seqnum[i] - 31;
50618 +                       } else {
50619 +                               break;
50620 +                       }
50621 +               }
50622 +       }
50623 +
50624 +       /* Update nextep_seq[] based on seqnum[] */
50625 +       for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50626 +               if (seqnum[i] != 0xff) {
50627 +                       if (seqnum[i+1] != 0xff) {
50628 +                               core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
50629 +                       } else {
50630 +                               core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
50631 +                               break;
50632 +                       }
50633 +               } else {
50634 +                       break;
50635 +               }
50636 +       }
50637 +
50638 +       DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
50639 +               __func__, core_if->first_in_nextep_seq);
50640 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50641 +               DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
50642 +       }
50643 +
50644 +       /* Flush the Learning Queue */
50645 +       resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
50646 +       resetctl.b.intknqflsh = 1;
50647 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
50648 +
50649 +
50650 +}
50651 +
50652 +/**
50653 + * handle the IN EP disable interrupt.
50654 + */
50655 +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
50656 +                                            const uint32_t epnum)
50657 +{
50658 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50659 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50660 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50661 +       dctl_data_t dctl = {.d32 = 0 };
50662 +       dwc_otg_pcd_ep_t *ep;
50663 +       dwc_ep_t *dwc_ep;
50664 +       gintmsk_data_t gintmsk_data;
50665 +       depctl_data_t depctl;
50666 +       uint32_t diepdma;
50667 +       uint32_t remain_to_transfer = 0;
50668 +       uint8_t i;
50669 +       uint32_t xfer_size;
50670 +
50671 +       ep = get_in_ep(pcd, epnum);
50672 +       dwc_ep = &ep->dwc_ep;
50673 +
50674 +       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
50675 +               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50676 +               complete_ep(ep);
50677 +               return;
50678 +       }
50679 +
50680 +       DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
50681 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
50682 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50683 +       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
50684 +
50685 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
50686 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
50687 +
50688 +       if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {
50689 +               if (ep->stopped) {
50690 +                       if (core_if->en_multiple_tx_fifo)
50691 +                               /* Flush the Tx FIFO */
50692 +                               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50693 +                       /* Clear the Global IN NP NAK */
50694 +                       dctl.d32 = 0;
50695 +                       dctl.b.cgnpinnak = 1;
50696 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50697 +                       /* Restart the transaction */
50698 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50699 +                               restart_transfer(pcd, epnum);
50700 +                       }
50701 +               } else {
50702 +                       /* Restart the transaction */
50703 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50704 +                               restart_transfer(pcd, epnum);
50705 +                       }
50706 +                       DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
50707 +               }
50708 +               return;
50709 +       }
50710 +
50711 +       if (core_if->start_predict > 2) {       // NP IN EP
50712 +               core_if->start_predict--;
50713 +               return;
50714 +       }
50715 +
50716 +       core_if->start_predict--;
50717 +
50718 +       if (core_if->start_predict == 1) {      // All NP IN Ep's disabled now
50719 +
50720 +               predict_nextep_seq(core_if);
50721 +
50722 +               /* Update all active IN EP's NextEP field based of nextep_seq[] */
50723 +               for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
50724 +                       depctl.d32 =
50725 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50726 +                       if (core_if->nextep_seq[i] != 0xff) {   // Active NP IN EP
50727 +                               depctl.b.nextep = core_if->nextep_seq[i];
50728 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50729 +                       }
50730 +               }
50731 +               /* Flush Shared NP TxFIFO */
50732 +               dwc_otg_flush_tx_fifo(core_if, 0);
50733 +               /* Rewind buffers */
50734 +               if (!core_if->dma_desc_enable) {
50735 +                       i = core_if->first_in_nextep_seq;
50736 +                       do {
50737 +                               ep = get_in_ep(pcd, i);
50738 +                               dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50739 +                               xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
50740 +                               if (xfer_size > ep->dwc_ep.maxxfer)
50741 +                                       xfer_size = ep->dwc_ep.maxxfer;
50742 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50743 +                               if (dieptsiz.b.pktcnt != 0) {
50744 +                                       if (xfer_size == 0) {
50745 +                                               remain_to_transfer = 0;
50746 +                                       } else {
50747 +                                               if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
50748 +                                                       remain_to_transfer =
50749 +                                                               dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
50750 +                                               } else {
50751 +                                                       remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)
50752 +                                                               + (xfer_size % ep->dwc_ep.maxpacket);
50753 +                                               }
50754 +                                       }
50755 +                                       diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
50756 +                                       dieptsiz.b.xfersize = remain_to_transfer;
50757 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
50758 +                                       diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
50759 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
50760 +                               }
50761 +                               i = core_if->nextep_seq[i];
50762 +                       } while (i != core_if->first_in_nextep_seq);
50763 +               } else { // dma_desc_enable
50764 +                               DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
50765 +               }
50766 +
50767 +               /* Restart transfers in predicted sequences */
50768 +               i = core_if->first_in_nextep_seq;
50769 +               do {
50770 +                       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50771 +                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50772 +                       if (dieptsiz.b.pktcnt != 0) {
50773 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50774 +                               depctl.b.epena = 1;
50775 +                               depctl.b.cnak = 1;
50776 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50777 +                       }
50778 +                       i = core_if->nextep_seq[i];
50779 +               } while (i != core_if->first_in_nextep_seq);
50780 +
50781 +               /* Clear the global non-periodic IN NAK handshake */
50782 +               dctl.d32 = 0;
50783 +               dctl.b.cgnpinnak = 1;
50784 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50785 +
50786 +               /* Unmask EP Mismatch interrupt */
50787 +               gintmsk_data.d32 = 0;
50788 +               gintmsk_data.b.epmismatch = 1;
50789 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
50790 +
50791 +               core_if->start_predict = 0;
50792 +
50793 +       }
50794 +}
50795 +
50796 +/**
50797 + * Handler for the IN EP timeout handshake interrupt.
50798 + */
50799 +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
50800 +                                            const uint32_t epnum)
50801 +{
50802 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50803 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50804 +
50805 +#ifdef DEBUG
50806 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50807 +       uint32_t num = 0;
50808 +#endif
50809 +       dctl_data_t dctl = {.d32 = 0 };
50810 +       dwc_otg_pcd_ep_t *ep;
50811 +
50812 +       gintmsk_data_t intr_mask = {.d32 = 0 };
50813 +
50814 +       ep = get_in_ep(pcd, epnum);
50815 +
50816 +       /* Disable the NP Tx Fifo Empty Interrrupt */
50817 +       if (!core_if->dma_enable) {
50818 +               intr_mask.b.nptxfempty = 1;
50819 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
50820 +                                intr_mask.d32, 0);
50821 +       }
50822 +       /** @todo NGS Check EP type.
50823 +        * Implement for Periodic EPs */
50824 +       /*
50825 +        * Non-periodic EP
50826 +        */
50827 +       /* Enable the Global IN NAK Effective Interrupt */
50828 +       intr_mask.b.ginnakeff = 1;
50829 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
50830 +
50831 +       /* Set Global IN NAK */
50832 +       dctl.b.sgnpinnak = 1;
50833 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50834 +
50835 +       ep->stopped = 1;
50836 +
50837 +#ifdef DEBUG
50838 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
50839 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
50840 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
50841 +#endif
50842 +
50843 +#ifdef DISABLE_PERIODIC_EP
50844 +       /*
50845 +        * Set the NAK bit for this EP to
50846 +        * start the disable process.
50847 +        */
50848 +       diepctl.d32 = 0;
50849 +       diepctl.b.snak = 1;
50850 +       DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
50851 +                        diepctl.d32);
50852 +       ep->disabling = 1;
50853 +       ep->stopped = 1;
50854 +#endif
50855 +}
50856 +
50857 +/**
50858 + * Handler for the IN EP NAK interrupt.
50859 + */
50860 +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
50861 +                                           const uint32_t epnum)
50862 +{
50863 +       /** @todo implement ISR */
50864 +       dwc_otg_core_if_t *core_if;
50865 +       diepmsk_data_t intr_mask = {.d32 = 0 };
50866 +
50867 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
50868 +       core_if = GET_CORE_IF(pcd);
50869 +       intr_mask.b.nak = 1;
50870 +
50871 +       if (core_if->multiproc_int_enable) {
50872 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50873 +                                diepeachintmsk[epnum], intr_mask.d32, 0);
50874 +       } else {
50875 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
50876 +                                intr_mask.d32, 0);
50877 +       }
50878 +
50879 +       return 1;
50880 +}
50881 +
50882 +/**
50883 + * Handler for the OUT EP Babble interrupt.
50884 + */
50885 +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
50886 +                                               const uint32_t epnum)
50887 +{
50888 +       /** @todo implement ISR */
50889 +       dwc_otg_core_if_t *core_if;
50890 +       doepmsk_data_t intr_mask = {.d32 = 0 };
50891 +
50892 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
50893 +                  "OUT EP Babble");
50894 +       core_if = GET_CORE_IF(pcd);
50895 +       intr_mask.b.babble = 1;
50896 +
50897 +       if (core_if->multiproc_int_enable) {
50898 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50899 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
50900 +       } else {
50901 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
50902 +                                intr_mask.d32, 0);
50903 +       }
50904 +
50905 +       return 1;
50906 +}
50907 +
50908 +/**
50909 + * Handler for the OUT EP NAK interrupt.
50910 + */
50911 +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
50912 +                                            const uint32_t epnum)
50913 +{
50914 +       /** @todo implement ISR */
50915 +       dwc_otg_core_if_t *core_if;
50916 +       doepmsk_data_t intr_mask = {.d32 = 0 };
50917 +
50918 +       DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
50919 +       core_if = GET_CORE_IF(pcd);
50920 +       intr_mask.b.nak = 1;
50921 +
50922 +       if (core_if->multiproc_int_enable) {
50923 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50924 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
50925 +       } else {
50926 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
50927 +                                intr_mask.d32, 0);
50928 +       }
50929 +
50930 +       return 1;
50931 +}
50932 +
50933 +/**
50934 + * Handler for the OUT EP NYET interrupt.
50935 + */
50936 +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
50937 +                                             const uint32_t epnum)
50938 +{
50939 +       /** @todo implement ISR */
50940 +       dwc_otg_core_if_t *core_if;
50941 +       doepmsk_data_t intr_mask = {.d32 = 0 };
50942 +
50943 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
50944 +       core_if = GET_CORE_IF(pcd);
50945 +       intr_mask.b.nyet = 1;
50946 +
50947 +       if (core_if->multiproc_int_enable) {
50948 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50949 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
50950 +       } else {
50951 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
50952 +                                intr_mask.d32, 0);
50953 +       }
50954 +
50955 +       return 1;
50956 +}
50957 +
50958 +/**
50959 + * This interrupt indicates that an IN EP has a pending Interrupt.
50960 + * The sequence for handling the IN EP interrupt is shown below:
50961 + * -#  Read the Device All Endpoint Interrupt register
50962 + * -#  Repeat the following for each IN EP interrupt bit set (from
50963 + *             LSB to MSB).
50964 + * -#  Read the Device Endpoint Interrupt (DIEPINTn) register
50965 + * -#  If "Transfer Complete" call the request complete function
50966 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
50967 + * -#  If "AHB Error Interrupt" log error
50968 + * -#  If "Time-out Handshake" log error
50969 + * -#  If "IN Token Received when TxFIFO Empty" write packet to Tx
50970 + *             FIFO.
50971 + * -#  If "IN Token EP Mismatch" (disable, this is handled by EP
50972 + *             Mismatch Interrupt)
50973 + */
50974 +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
50975 +{
50976 +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
50977 +do { \
50978 +               diepint_data_t diepint = {.d32=0}; \
50979 +               diepint.b.__intr = 1; \
50980 +               DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
50981 +               diepint.d32); \
50982 +} while (0)
50983 +
50984 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50985 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50986 +       diepint_data_t diepint = {.d32 = 0 };
50987 +       depctl_data_t depctl = {.d32 = 0 };
50988 +       uint32_t ep_intr;
50989 +       uint32_t epnum = 0;
50990 +       dwc_otg_pcd_ep_t *ep;
50991 +       dwc_ep_t *dwc_ep;
50992 +       gintmsk_data_t intr_mask = {.d32 = 0 };
50993 +
50994 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
50995 +
50996 +       /* Read in the device interrupt bits */
50997 +       ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
50998 +
50999 +       /* Service the Device IN interrupts for each endpoint */
51000 +       while (ep_intr) {
51001 +               if (ep_intr & 0x1) {
51002 +                       uint32_t empty_msk;
51003 +                       /* Get EP pointer */
51004 +                       ep = get_in_ep(pcd, epnum);
51005 +                       dwc_ep = &ep->dwc_ep;
51006 +
51007 +                       depctl.d32 =
51008 +                           DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51009 +                       empty_msk =
51010 +                           DWC_READ_REG32(&dev_if->
51011 +                                          dev_global_regs->dtknqr4_fifoemptymsk);
51012 +
51013 +                       DWC_DEBUGPL(DBG_PCDV,
51014 +                                   "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",
51015 +                                   epnum, empty_msk, depctl.d32);
51016 +
51017 +                       DWC_DEBUGPL(DBG_PCD,
51018 +                                   "EP%d-%s: type=%d, mps=%d\n",
51019 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51020 +                                   dwc_ep->type, dwc_ep->maxpacket);
51021 +
51022 +                       diepint.d32 =
51023 +                           dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
51024 +
51025 +                       DWC_DEBUGPL(DBG_PCDV,
51026 +                                   "EP %d Interrupt Register - 0x%x\n", epnum,
51027 +                                   diepint.d32);
51028 +                       /* Transfer complete */
51029 +                       if (diepint.b.xfercompl) {
51030 +                               /* Disable the NP Tx FIFO Empty
51031 +                                * Interrupt */
51032 +                               if (core_if->en_multiple_tx_fifo == 0) {
51033 +                                       intr_mask.b.nptxfempty = 1;
51034 +                                       DWC_MODIFY_REG32
51035 +                                           (&core_if->core_global_regs->gintmsk,
51036 +                                            intr_mask.d32, 0);
51037 +                               } else {
51038 +                                       /* Disable the Tx FIFO Empty Interrupt for this EP */
51039 +                                       uint32_t fifoemptymsk =
51040 +                                           0x1 << dwc_ep->num;
51041 +                                       DWC_MODIFY_REG32(&core_if->
51042 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
51043 +                                                        fifoemptymsk, 0);
51044 +                               }
51045 +                               /* Clear the bit in DIEPINTn for this interrupt */
51046 +                               CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
51047 +
51048 +                               /* Complete the transfer */
51049 +                               if (epnum == 0) {
51050 +                                       handle_ep0(pcd);
51051 +                               }
51052 +#ifdef DWC_EN_ISOC
51053 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51054 +                                       if (!ep->stopped)
51055 +                                               complete_iso_ep(pcd, ep);
51056 +                               }
51057 +#endif /* DWC_EN_ISOC */
51058 +#ifdef DWC_UTE_PER_IO
51059 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51060 +                                       if (!ep->stopped)
51061 +                                               complete_xiso_ep(ep);
51062 +                               }
51063 +#endif /* DWC_UTE_PER_IO */
51064 +                               else {
51065 +                                       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&
51066 +                                                       dwc_ep->bInterval > 1) {
51067 +                                               dwc_ep->frame_num += dwc_ep->bInterval;
51068 +                                               if (dwc_ep->frame_num > 0x3FFF)
51069 +                                               {
51070 +                                                       dwc_ep->frm_overrun = 1;
51071 +                                                       dwc_ep->frame_num &= 0x3FFF;
51072 +                                               } else
51073 +                                                       dwc_ep->frm_overrun = 0;
51074 +                                       }
51075 +                                       complete_ep(ep);
51076 +                                       if(diepint.b.nak)
51077 +                                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51078 +                               }
51079 +                       }
51080 +                       /* Endpoint disable      */
51081 +                       if (diepint.b.epdisabled) {
51082 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
51083 +                                           epnum);
51084 +                               handle_in_ep_disable_intr(pcd, epnum);
51085 +
51086 +                               /* Clear the bit in DIEPINTn for this interrupt */
51087 +                               CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
51088 +                       }
51089 +                       /* AHB Error */
51090 +                       if (diepint.b.ahberr) {
51091 +                               DWC_ERROR("EP%d IN AHB Error\n", epnum);
51092 +                               /* Clear the bit in DIEPINTn for this interrupt */
51093 +                               CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
51094 +                       }
51095 +                       /* TimeOUT Handshake (non-ISOC IN EPs) */
51096 +                       if (diepint.b.timeout) {
51097 +                               DWC_ERROR("EP%d IN Time-out\n", epnum);
51098 +                               handle_in_ep_timeout_intr(pcd, epnum);
51099 +
51100 +                               CLEAR_IN_EP_INTR(core_if, epnum, timeout);
51101 +                       }
51102 +                       /** IN Token received with TxF Empty */
51103 +                       if (diepint.b.intktxfemp) {
51104 +                               DWC_DEBUGPL(DBG_ANY,
51105 +                                           "EP%d IN TKN TxFifo Empty\n",
51106 +                                           epnum);
51107 +                               if (!ep->stopped && epnum != 0) {
51108 +
51109 +                                       diepmsk_data_t diepmsk = {.d32 = 0 };
51110 +                                       diepmsk.b.intktxfemp = 1;
51111 +
51112 +                                       if (core_if->multiproc_int_enable) {
51113 +                                               DWC_MODIFY_REG32
51114 +                                                   (&dev_if->dev_global_regs->diepeachintmsk
51115 +                                                    [epnum], diepmsk.d32, 0);
51116 +                                       } else {
51117 +                                               DWC_MODIFY_REG32
51118 +                                                   (&dev_if->dev_global_regs->diepmsk,
51119 +                                                    diepmsk.d32, 0);
51120 +                                       }
51121 +                               } else if (core_if->dma_desc_enable
51122 +                                          && epnum == 0
51123 +                                          && pcd->ep0state ==
51124 +                                          EP0_OUT_STATUS_PHASE) {
51125 +                                       // EP0 IN set STALL
51126 +                                       depctl.d32 =
51127 +                                           DWC_READ_REG32(&dev_if->in_ep_regs
51128 +                                                          [epnum]->diepctl);
51129 +
51130 +                                       /* set the disable and stall bits */
51131 +                                       if (depctl.b.epena) {
51132 +                                               depctl.b.epdis = 1;
51133 +                                       }
51134 +                                       depctl.b.stall = 1;
51135 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs
51136 +                                                       [epnum]->diepctl,
51137 +                                                       depctl.d32);
51138 +                               }
51139 +                               CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
51140 +                       }
51141 +                       /** IN Token Received with EP mismatch */
51142 +                       if (diepint.b.intknepmis) {
51143 +                               DWC_DEBUGPL(DBG_ANY,
51144 +                                           "EP%d IN TKN EP Mismatch\n", epnum);
51145 +                               CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
51146 +                       }
51147 +                       /** IN Endpoint NAK Effective */
51148 +                       if (diepint.b.inepnakeff) {
51149 +                               DWC_DEBUGPL(DBG_ANY,
51150 +                                           "EP%d IN EP NAK Effective\n",
51151 +                                           epnum);
51152 +                               /* Periodic EP */
51153 +                               if (ep->disabling) {
51154 +                                       depctl.d32 = 0;
51155 +                                       depctl.b.snak = 1;
51156 +                                       depctl.b.epdis = 1;
51157 +                                       DWC_MODIFY_REG32(&dev_if->in_ep_regs
51158 +                                                        [epnum]->diepctl,
51159 +                                                        depctl.d32,
51160 +                                                        depctl.d32);
51161 +                               }
51162 +                               CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
51163 +
51164 +                       }
51165 +
51166 +                       /** IN EP Tx FIFO Empty Intr */
51167 +                       if (diepint.b.emptyintr) {
51168 +                               DWC_DEBUGPL(DBG_ANY,
51169 +                                           "EP%d Tx FIFO Empty Intr \n",
51170 +                                           epnum);
51171 +                               write_empty_tx_fifo(pcd, epnum);
51172 +
51173 +                               CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
51174 +
51175 +                       }
51176 +
51177 +                       /** IN EP BNA Intr */
51178 +                       if (diepint.b.bna) {
51179 +                               CLEAR_IN_EP_INTR(core_if, epnum, bna);
51180 +                               if (core_if->dma_desc_enable) {
51181 +#ifdef DWC_EN_ISOC
51182 +                                       if (dwc_ep->type ==
51183 +                                           DWC_OTG_EP_TYPE_ISOC) {
51184 +                                               /*
51185 +                                                * This checking is performed to prevent first "false" BNA
51186 +                                                * handling occuring right after reconnect
51187 +                                                */
51188 +                                               if (dwc_ep->next_frame !=
51189 +                                                   0xffffffff)
51190 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51191 +                                       } else
51192 +#endif                         /* DWC_EN_ISOC */
51193 +                                       {
51194 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51195 +                                       }
51196 +                               }
51197 +                       }
51198 +                       /* NAK Interrutp */
51199 +                       if (diepint.b.nak) {
51200 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
51201 +                                           epnum);
51202 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51203 +                                       depctl_data_t depctl;
51204 +                                       if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
51205 +                                               ep->dwc_ep.frame_num = core_if->frame_num;
51206 +                                               if (ep->dwc_ep.bInterval > 1) {
51207 +                                                       depctl.d32 = 0;
51208 +                                                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51209 +                                                       if (ep->dwc_ep.frame_num & 0x1) {
51210 +                                                               depctl.b.setd1pid = 1;
51211 +                                                               depctl.b.setd0pid = 0;
51212 +                                                       } else {
51213 +                                                               depctl.b.setd0pid = 1;
51214 +                                                               depctl.b.setd1pid = 0;
51215 +                                                       }
51216 +                                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
51217 +                                               }
51218 +                                               start_next_request(ep);
51219 +                                       }
51220 +                                       ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
51221 +                                       if (dwc_ep->frame_num > 0x3FFF) {
51222 +                                               dwc_ep->frm_overrun = 1;
51223 +                                               dwc_ep->frame_num &= 0x3FFF;
51224 +                                       } else
51225 +                                               dwc_ep->frm_overrun = 0;
51226 +                               }
51227 +
51228 +                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51229 +                       }
51230 +               }
51231 +               epnum++;
51232 +               ep_intr >>= 1;
51233 +       }
51234 +
51235 +       return 1;
51236 +#undef CLEAR_IN_EP_INTR
51237 +}
51238 +
51239 +/**
51240 + * This interrupt indicates that an OUT EP has a pending Interrupt.
51241 + * The sequence for handling the OUT EP interrupt is shown below:
51242 + * -#  Read the Device All Endpoint Interrupt register
51243 + * -#  Repeat the following for each OUT EP interrupt bit set (from
51244 + *             LSB to MSB).
51245 + * -#  Read the Device Endpoint Interrupt (DOEPINTn) register
51246 + * -#  If "Transfer Complete" call the request complete function
51247 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
51248 + * -#  If "AHB Error Interrupt" log error
51249 + * -#  If "Setup Phase Done" process Setup Packet (See Standard USB
51250 + *             Command Processing)
51251 + */
51252 +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
51253 +{
51254 +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
51255 +do { \
51256 +               doepint_data_t doepint = {.d32=0}; \
51257 +               doepint.b.__intr = 1; \
51258 +               DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
51259 +               doepint.d32); \
51260 +} while (0)
51261 +
51262 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51263 +       uint32_t ep_intr;
51264 +       doepint_data_t doepint = {.d32 = 0 };
51265 +       uint32_t epnum = 0;
51266 +       dwc_otg_pcd_ep_t *ep;
51267 +       dwc_ep_t *dwc_ep;
51268 +       dctl_data_t dctl = {.d32 = 0 };
51269 +       gintmsk_data_t gintmsk = {.d32 = 0 };
51270 +
51271 +
51272 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
51273 +
51274 +       /* Read in the device interrupt bits */
51275 +       ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
51276 +
51277 +       while (ep_intr) {
51278 +               if (ep_intr & 0x1) {
51279 +                       /* Get EP pointer */
51280 +                       ep = get_out_ep(pcd, epnum);
51281 +                       dwc_ep = &ep->dwc_ep;
51282 +
51283 +#ifdef VERBOSE
51284 +                       DWC_DEBUGPL(DBG_PCDV,
51285 +                                   "EP%d-%s: type=%d, mps=%d\n",
51286 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51287 +                                   dwc_ep->type, dwc_ep->maxpacket);
51288 +#endif
51289 +                       doepint.d32 =
51290 +                           dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
51291 +                       /* Moved this interrupt upper due to core deffect of asserting
51292 +                        * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
51293 +                       if (doepint.b.stsphsercvd) {
51294 +                               deptsiz0_data_t deptsiz;
51295 +                               CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
51296 +                               deptsiz.d32 =
51297 +                                   DWC_READ_REG32(&core_if->dev_if->
51298 +                                                  out_ep_regs[0]->doeptsiz);
51299 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51300 +                                   && core_if->dma_enable
51301 +                                   && core_if->dma_desc_enable == 0
51302 +                                   && doepint.b.xfercompl
51303 +                                   && deptsiz.b.xfersize == 24) {
51304 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51305 +                                                         xfercompl);
51306 +                                       doepint.b.xfercompl = 0;
51307 +                                       ep0_out_start(core_if, pcd);
51308 +                               }
51309 +                               if ((core_if->dma_desc_enable) ||
51310 +                                   (core_if->dma_enable
51311 +                                    && core_if->snpsid >=
51312 +                                    OTG_CORE_REV_3_00a)) {
51313 +                                       do_setup_in_status_phase(pcd);
51314 +                               }
51315 +                       }
51316 +                       /* Transfer complete */
51317 +                       if (doepint.b.xfercompl) {
51318 +
51319 +                               if (epnum == 0) {
51320 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51321 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51322 +                                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
51323 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51324 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
51325 +                                                       doepint.d32);
51326 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
51327 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
51328 +
51329 +                                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51330 +                                                       && core_if->dma_enable == 0) {
51331 +                                                       doepint_data_t doepint;
51332 +                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51333 +                                                                                                               out_ep_regs[0]->doepint);
51334 +                                                       if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
51335 +                                                               CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51336 +                                                               goto exit_xfercompl;
51337 +                                                       }
51338 +                                               }
51339 +                                               /* In case of DDMA  look at SR bit to go to the Data Stage */
51340 +                                               if (core_if->dma_desc_enable) {
51341 +                                                       dev_dma_desc_sts_t status = {.d32 = 0};
51342 +                                                       if (pcd->ep0state == EP0_IDLE) {
51343 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51344 +                                                                                       dev_if->setup_desc_index]->status.d32;
51345 +                                                               if(pcd->data_terminated) {
51346 +                                                                        pcd->data_terminated = 0;
51347 +                                                                        status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51348 +                                                                        dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
51349 +                                                               }
51350 +                                                               if (status.b.sr) {
51351 +                                                                       if (doepint.b.setup) {
51352 +                                                                               DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
51353 +                                                                               /* Already started data stage, clear setup */
51354 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51355 +                                                                               doepint.b.setup = 0;
51356 +                                                                               handle_ep0(pcd);
51357 +                                                                               /* Prepare for more setup packets */
51358 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51359 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51360 +                                                                                       ep0_out_start(core_if, pcd);
51361 +                                                                               }
51362 +
51363 +                                                                               goto exit_xfercompl;
51364 +                                                                       } else {
51365 +                                                                               /* Prepare for more setup packets */
51366 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51367 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51368 +                                                                               ep0_out_start(core_if, pcd);
51369 +                                                                       }
51370 +                                                               }
51371 +                                                       } else {
51372 +                                                               dwc_otg_pcd_request_t *req;
51373 +                                                               dev_dma_desc_sts_t status = {.d32 = 0};
51374 +                                                               diepint_data_t diepint0;
51375 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51376 +                                                                                                                       in_ep_regs[0]->diepint);
51377 +
51378 +                                                               if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
51379 +                                                                       DWC_ERROR("EP0 is stalled/disconnected\n");
51380 +                                                               }
51381 +
51382 +                                                               /* Clear IN xfercompl if set */
51383 +                                                               if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
51384 +                                                                       || pcd->ep0state == EP0_IN_DATA_PHASE)) {
51385 +                                                                       DWC_WRITE_REG32(&core_if->dev_if->
51386 +                                                                               in_ep_regs[0]->diepint, diepint0.d32);
51387 +                                                               }
51388 +
51389 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51390 +                                                                       dev_if->setup_desc_index]->status.d32;
51391 +
51392 +                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
51393 +                                                                       && (pcd->ep0state == EP0_OUT_DATA_PHASE))
51394 +                                                                       status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51395 +                                                               if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
51396 +                                                                       status.d32 = status.d32 = core_if->dev_if->
51397 +                                                                       out_desc_addr->status.d32;
51398 +
51399 +                                                               if (status.b.sr) {
51400 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51401 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51402 +                                                                       } else {
51403 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51404 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51405 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51406 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51407 +                                                                                               /* Read arrived setup packet from req->buf */
51408 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51409 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51410 +                                                                               }
51411 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51412 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51413 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51414 +                                                                               ep->dwc_ep.xfer_buff = 0;
51415 +                                                                               ep->dwc_ep.xfer_len = 0;
51416 +                                                                       }
51417 +                                                                       pcd->ep0state = EP0_IDLE;
51418 +                                                                       if (doepint.b.setup) {
51419 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51420 +                                                                               /* Data stage started, clear setup */
51421 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51422 +                                                                               doepint.b.setup = 0;
51423 +                                                                               handle_ep0(pcd);
51424 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51425 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51426 +                                                                                       ep0_out_start(core_if, pcd);
51427 +                                                                               }
51428 +
51429 +                                                                               goto exit_xfercompl;
51430 +                                                                       } else {
51431 +                                                                               /* Prepare for more setup packets */
51432 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51433 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51434 +                                                                               ep0_out_start(core_if, pcd);
51435 +                                                                       }
51436 +                                                               }
51437 +                                                       }
51438 +                                               }
51439 +                                               if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
51440 +                                                       && core_if->dma_desc_enable == 0) {
51441 +                                                       doepint_data_t doepint_temp = {.d32 = 0};
51442 +                                                       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
51443 +                                                       doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51444 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doepint);
51445 +                                                       doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
51446 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doeptsiz);
51447 +                                                       if (pcd->ep0state == EP0_IDLE) {
51448 +                                                               if (doepint_temp.b.sr) {
51449 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51450 +                                                               }
51451 +                                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51452 +                                                                                                                                       out_ep_regs[0]->doepint);
51453 +                                                                       if (doeptsize0.b.supcnt == 3) {
51454 +                                                                               DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
51455 +                                                                               ep->dwc_ep.stp_rollover = 1;
51456 +                                                                       }
51457 +                                                                       if (doepint.b.setup) {
51458 +retry:
51459 +                                                                               /* Already started data stage, clear setup */
51460 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51461 +                                                                               doepint.b.setup = 0;
51462 +                                                                               handle_ep0(pcd);
51463 +                                                                               ep->dwc_ep.stp_rollover = 0;
51464 +                                                                               /* Prepare for more setup packets */
51465 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51466 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51467 +                                                                                       ep0_out_start(core_if, pcd);
51468 +                                                                               }
51469 +                                                                               goto exit_xfercompl;
51470 +                                                                       } else {
51471 +                                                                               /* Prepare for more setup packets */
51472 +                                                                               DWC_DEBUGPL(DBG_ANY,
51473 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51474 +                                                                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51475 +                                                                                                                                       out_ep_regs[0]->doepint);
51476 +                                                                               if(doepint.b.setup)
51477 +                                                                                       goto retry;
51478 +                                                                               ep0_out_start(core_if, pcd);
51479 +                                                                       }
51480 +                                                       } else {
51481 +                                                               dwc_otg_pcd_request_t *req;
51482 +                                                               diepint_data_t diepint0 = {.d32 = 0};
51483 +                                                               doepint_data_t doepint_temp = {.d32 = 0};
51484 +                                                               depctl_data_t diepctl0;
51485 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51486 +                                                                                                                               in_ep_regs[0]->diepint);
51487 +                                                               diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
51488 +                                                                                                                               in_ep_regs[0]->diepctl);
51489 +
51490 +                                                               if (pcd->ep0state == EP0_IN_DATA_PHASE
51491 +                                                                       || pcd->ep0state == EP0_IN_STATUS_PHASE) {
51492 +                                                                       if (diepint0.b.xfercompl) {
51493 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51494 +                                                                                       in_ep_regs[0]->diepint, diepint0.d32);
51495 +                                                                       }
51496 +                                                                       if (diepctl0.b.epena) {
51497 +                                                                               diepint_data_t diepint = {.d32 = 0};
51498 +                                                                               diepctl0.b.snak = 1;
51499 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51500 +                                                                                                               in_ep_regs[0]->diepctl, diepctl0.d32);
51501 +                                                                               do {
51502 +                                                                                       dwc_udelay(10);
51503 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51504 +                                                                                               in_ep_regs[0]->diepint);
51505 +                                                                               } while (!diepint.b.inepnakeff);
51506 +                                                                               diepint.b.inepnakeff = 1;
51507 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51508 +                                                                                       in_ep_regs[0]->diepint, diepint.d32);
51509 +                                                                               diepctl0.d32 = 0;
51510 +                                                                               diepctl0.b.epdis = 1;
51511 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
51512 +                                                                                                               diepctl0.d32);
51513 +                                                                               do {
51514 +                                                                                       dwc_udelay(10);
51515 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51516 +                                                                                               in_ep_regs[0]->diepint);
51517 +                                                                               } while (!diepint.b.epdisabled);
51518 +                                                                               diepint.b.epdisabled = 1;
51519 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
51520 +                                                                                                                       diepint.d32);
51521 +                                                                       }
51522 +                                                               }
51523 +                                                               doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51524 +                                                                                                                               out_ep_regs[ep->dwc_ep.num]->doepint);
51525 +                                                               if (doepint_temp.b.sr) {
51526 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51527 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51528 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51529 +                                                                       } else {
51530 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51531 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51532 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51533 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51534 +                                                                                               /* Read arrived setup packet from req->buf */
51535 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51536 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51537 +                                                                               }
51538 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51539 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51540 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51541 +                                                                               ep->dwc_ep.xfer_buff = 0;
51542 +                                                                               ep->dwc_ep.xfer_len = 0;
51543 +                                                                       }
51544 +                                                                       pcd->ep0state = EP0_IDLE;
51545 +                                                                       if (doepint.b.setup) {
51546 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51547 +                                                                               /* Data stage started, clear setup */
51548 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51549 +                                                                               doepint.b.setup = 0;
51550 +                                                                               handle_ep0(pcd);
51551 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51552 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51553 +                                                                                       ep0_out_start(core_if, pcd);
51554 +                                                                               }
51555 +                                                                               goto exit_xfercompl;
51556 +                                                                       } else {
51557 +                                                                               /* Prepare for more setup packets */
51558 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51559 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51560 +                                                                               ep0_out_start(core_if, pcd);
51561 +                                                                       }
51562 +                                                               }
51563 +                                                       }
51564 +                                               }
51565 +                                               if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
51566 +                                                       handle_ep0(pcd);
51567 +exit_xfercompl:
51568 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51569 +                                                       dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
51570 +                                       } else {
51571 +                                       if (core_if->dma_desc_enable == 0
51572 +                                           || pcd->ep0state != EP0_IDLE)
51573 +                                               handle_ep0(pcd);
51574 +                                       }
51575 +#ifdef DWC_EN_ISOC
51576 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51577 +                                       if (doepint.b.pktdrpsts == 0) {
51578 +                                               /* Clear the bit in DOEPINTn for this interrupt */
51579 +                                               CLEAR_OUT_EP_INTR(core_if,
51580 +                                                                 epnum,
51581 +                                                                 xfercompl);
51582 +                                               complete_iso_ep(pcd, ep);
51583 +                                       } else {
51584 +
51585 +                                               doepint_data_t doepint = {.d32 = 0 };
51586 +                                               doepint.b.xfercompl = 1;
51587 +                                               doepint.b.pktdrpsts = 1;
51588 +                                               DWC_WRITE_REG32
51589 +                                                   (&core_if->dev_if->out_ep_regs
51590 +                                                    [epnum]->doepint,
51591 +                                                    doepint.d32);
51592 +                                               if (handle_iso_out_pkt_dropped
51593 +                                                   (core_if, dwc_ep)) {
51594 +                                                       complete_iso_ep(pcd,
51595 +                                                                       ep);
51596 +                                               }
51597 +                                       }
51598 +#endif /* DWC_EN_ISOC */
51599 +#ifdef DWC_UTE_PER_IO
51600 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51601 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51602 +                                       if (!ep->stopped)
51603 +                                               complete_xiso_ep(ep);
51604 +#endif /* DWC_UTE_PER_IO */
51605 +                               } else {
51606 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51607 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51608 +                                                         xfercompl);
51609 +
51610 +                                       if (core_if->core_params->dev_out_nak) {
51611 +                                               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
51612 +                                               pcd->core_if->ep_xfer_info[epnum].state = 0;
51613 +#ifdef DEBUG
51614 +                                               print_memory_payload(pcd, dwc_ep);
51615 +#endif
51616 +                                       }
51617 +                                       complete_ep(ep);
51618 +                               }
51619 +
51620 +                       }
51621 +
51622 +                       /* Endpoint disable      */
51623 +                       if (doepint.b.epdisabled) {
51624 +
51625 +                               /* Clear the bit in DOEPINTn for this interrupt */
51626 +                               CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
51627 +                               if (core_if->core_params->dev_out_nak) {
51628 +#ifdef DEBUG
51629 +                                       print_memory_payload(pcd, dwc_ep);
51630 +#endif
51631 +                                       /* In case of timeout condition */
51632 +                                       if (core_if->ep_xfer_info[epnum].state == 2) {
51633 +                                               dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51634 +                                                                               dev_global_regs->dctl);
51635 +                                               dctl.b.cgoutnak = 1;
51636 +                                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51637 +                                                                                                                               dctl.d32);
51638 +                                               /* Unmask goutnakeff interrupt which was masked
51639 +                                                * during handle nak out interrupt */
51640 +                                               gintmsk.b.goutnakeff = 1;
51641 +                                               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51642 +                                                                                                                               0, gintmsk.d32);
51643 +
51644 +                                               complete_ep(ep);
51645 +                                       }
51646 +                               }
51647 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
51648 +                               {
51649 +                                       dctl_data_t dctl;
51650 +                                       gintmsk_data_t intr_mask = {.d32 = 0};
51651 +                                       dwc_otg_pcd_request_t *req = 0;
51652 +
51653 +                                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51654 +                                               dev_global_regs->dctl);
51655 +                                       dctl.b.cgoutnak = 1;
51656 +                                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51657 +                                               dctl.d32);
51658 +
51659 +                                       intr_mask.d32 = 0;
51660 +                                       intr_mask.b.incomplisoout = 1;
51661 +
51662 +                                       /* Get any pending requests */
51663 +                                       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51664 +                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51665 +                                               if (!req) {
51666 +                                                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
51667 +                                               } else {
51668 +                                                       dwc_otg_request_done(ep, req, 0);
51669 +                                                       start_next_request(ep);
51670 +                                               }
51671 +                                       } else {
51672 +                                               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
51673 +                                       }
51674 +                               }
51675 +                       }
51676 +                       /* AHB Error */
51677 +                       if (doepint.b.ahberr) {
51678 +                               DWC_ERROR("EP%d OUT AHB Error\n", epnum);
51679 +                               DWC_ERROR("EP%d DEPDMA=0x%08x \n",
51680 +                                         epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
51681 +                               CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
51682 +                       }
51683 +                       /* Setup Phase Done (contorl EPs) */
51684 +                       if (doepint.b.setup) {
51685 +#ifdef DEBUG_EP0
51686 +                               DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
51687 +#endif
51688 +                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51689 +
51690 +                               handle_ep0(pcd);
51691 +                       }
51692 +
51693 +                       /** OUT EP BNA Intr */
51694 +                       if (doepint.b.bna) {
51695 +                               CLEAR_OUT_EP_INTR(core_if, epnum, bna);
51696 +                               if (core_if->dma_desc_enable) {
51697 +#ifdef DWC_EN_ISOC
51698 +                                       if (dwc_ep->type ==
51699 +                                           DWC_OTG_EP_TYPE_ISOC) {
51700 +                                               /*
51701 +                                                * This checking is performed to prevent first "false" BNA
51702 +                                                * handling occuring right after reconnect
51703 +                                                */
51704 +                                               if (dwc_ep->next_frame !=
51705 +                                                   0xffffffff)
51706 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51707 +                                       } else
51708 +#endif                         /* DWC_EN_ISOC */
51709 +                                       {
51710 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51711 +                                       }
51712 +                               }
51713 +                       }
51714 +                       /* Babble Interrupt */
51715 +                       if (doepint.b.babble) {
51716 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
51717 +                                           epnum);
51718 +                               handle_out_ep_babble_intr(pcd, epnum);
51719 +
51720 +                               CLEAR_OUT_EP_INTR(core_if, epnum, babble);
51721 +                       }
51722 +                       if (doepint.b.outtknepdis) {
51723 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
51724 +                                       disabled\n",epnum);
51725 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51726 +                                       doepmsk_data_t doepmsk = {.d32 = 0};
51727 +                                       ep->dwc_ep.frame_num = core_if->frame_num;
51728 +                                       if (ep->dwc_ep.bInterval > 1) {
51729 +                                               depctl_data_t depctl;
51730 +                                               depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51731 +                                                                                                       out_ep_regs[epnum]->doepctl);
51732 +                                               if (ep->dwc_ep.frame_num & 0x1) {
51733 +                                                       depctl.b.setd1pid = 1;
51734 +                                                       depctl.b.setd0pid = 0;
51735 +                                               } else {
51736 +                                                       depctl.b.setd0pid = 1;
51737 +                                                       depctl.b.setd1pid = 0;
51738 +                                               }
51739 +                                               DWC_WRITE_REG32(&core_if->dev_if->
51740 +                                                                               out_ep_regs[epnum]->doepctl, depctl.d32);
51741 +                                       }
51742 +                                       start_next_request(ep);
51743 +                                       doepmsk.b.outtknepdis = 1;
51744 +                                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51745 +                                                                doepmsk.d32, 0);
51746 +                               }
51747 +                               CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
51748 +                       }
51749 +
51750 +                       /* NAK Interrutp */
51751 +                       if (doepint.b.nak) {
51752 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
51753 +                               handle_out_ep_nak_intr(pcd, epnum);
51754 +
51755 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nak);
51756 +                       }
51757 +                       /* NYET Interrutp */
51758 +                       if (doepint.b.nyet) {
51759 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
51760 +                               handle_out_ep_nyet_intr(pcd, epnum);
51761 +
51762 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
51763 +                       }
51764 +               }
51765 +
51766 +               epnum++;
51767 +               ep_intr >>= 1;
51768 +       }
51769 +
51770 +       return 1;
51771 +
51772 +#undef CLEAR_OUT_EP_INTR
51773 +}
51774 +static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
51775 +{
51776 +       int retval = 0;
51777 +       if(!frm_overrun && curr_fr >= trgt_fr)
51778 +               retval = 1;
51779 +       else if (frm_overrun
51780 +                && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
51781 +               retval = 1;
51782 +       return retval;
51783 +}
51784 +/**
51785 + * Incomplete ISO IN Transfer Interrupt.
51786 + * This interrupt indicates one of the following conditions occurred
51787 + * while transmitting an ISOC transaction.
51788 + * - Corrupted IN Token for ISOC EP.
51789 + * - Packet not complete in FIFO.
51790 + * The follow actions will be taken:
51791 + *     -#      Determine the EP
51792 + *     -#      Set incomplete flag in dwc_ep structure
51793 + *     -#      Disable EP; when "Endpoint Disabled" interrupt is received
51794 + *             Flush FIFO
51795 + */
51796 +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
51797 +{
51798 +       gintsts_data_t gintsts;
51799 +
51800 +#ifdef DWC_EN_ISOC
51801 +       dwc_otg_dev_if_t *dev_if;
51802 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51803 +       depctl_data_t depctl = {.d32 = 0 };
51804 +       dsts_data_t dsts = {.d32 = 0 };
51805 +       dwc_ep_t *dwc_ep;
51806 +       int i;
51807 +
51808 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51809 +
51810 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
51811 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
51812 +               if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51813 +                       deptsiz.d32 =
51814 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
51815 +                       depctl.d32 =
51816 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51817 +
51818 +                       if (depctl.b.epdis && deptsiz.d32) {
51819 +                               set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
51820 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
51821 +                                       dwc_ep->cur_pkt = 0;
51822 +                                       dwc_ep->proc_buf_num =
51823 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
51824 +
51825 +                                       if (dwc_ep->proc_buf_num) {
51826 +                                               dwc_ep->cur_pkt_addr =
51827 +                                                   dwc_ep->xfer_buff1;
51828 +                                               dwc_ep->cur_pkt_dma_addr =
51829 +                                                   dwc_ep->dma_addr1;
51830 +                                       } else {
51831 +                                               dwc_ep->cur_pkt_addr =
51832 +                                                   dwc_ep->xfer_buff0;
51833 +                                               dwc_ep->cur_pkt_dma_addr =
51834 +                                                   dwc_ep->dma_addr0;
51835 +                                       }
51836 +
51837 +                               }
51838 +
51839 +                               dsts.d32 =
51840 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
51841 +                                                  dev_global_regs->dsts);
51842 +                               dwc_ep->next_frame = dsts.b.soffn;
51843 +
51844 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
51845 +                                                                 (pcd),
51846 +                                                                 dwc_ep);
51847 +                       }
51848 +               }
51849 +       }
51850 +
51851 +#else
51852 +       depctl_data_t depctl = {.d32 = 0 };
51853 +       dwc_ep_t *dwc_ep;
51854 +       dwc_otg_dev_if_t *dev_if;
51855 +       int i;
51856 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51857 +
51858 +       DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
51859 +
51860 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
51861 +               dwc_ep = &pcd->in_ep[i-1].dwc_ep;
51862 +               depctl.d32 =
51863 +                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51864 +               if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51865 +                       if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,
51866 +                                                       dwc_ep->frm_overrun))
51867 +                       {
51868 +                               depctl.d32 =
51869 +                                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51870 +                               depctl.b.snak = 1;
51871 +                               depctl.b.epdis = 1;
51872 +                               DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
51873 +                       }
51874 +               }
51875 +       }
51876 +
51877 +       /*intr_mask.b.incomplisoin = 1;
51878 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
51879 +                        intr_mask.d32, 0);      */
51880 +#endif                         //DWC_EN_ISOC
51881 +
51882 +       /* Clear interrupt */
51883 +       gintsts.d32 = 0;
51884 +       gintsts.b.incomplisoin = 1;
51885 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
51886 +                       gintsts.d32);
51887 +
51888 +       return 1;
51889 +}
51890 +
51891 +/**
51892 + * Incomplete ISO OUT Transfer Interrupt.
51893 + *
51894 + * This interrupt indicates that the core has dropped an ISO OUT
51895 + * packet. The following conditions can be the cause:
51896 + * - FIFO Full, the entire packet would not fit in the FIFO.
51897 + * - CRC Error
51898 + * - Corrupted Token
51899 + * The follow actions will be taken:
51900 + *     -#      Determine the EP
51901 + *     -#      Set incomplete flag in dwc_ep structure
51902 + *     -#      Read any data from the FIFO
51903 + *     -#      Disable EP. When "Endpoint Disabled" interrupt is received
51904 + *             re-enable EP.
51905 + */
51906 +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
51907 +{
51908 +
51909 +       gintsts_data_t gintsts;
51910 +
51911 +#ifdef DWC_EN_ISOC
51912 +       dwc_otg_dev_if_t *dev_if;
51913 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51914 +       depctl_data_t depctl = {.d32 = 0 };
51915 +       dsts_data_t dsts = {.d32 = 0 };
51916 +       dwc_ep_t *dwc_ep;
51917 +       int i;
51918 +
51919 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51920 +
51921 +       for (i = 1; i <= dev_if->num_out_eps; ++i) {
51922 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
51923 +               if (pcd->out_ep[i].dwc_ep.active &&
51924 +                   pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51925 +                       deptsiz.d32 =
51926 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
51927 +                       depctl.d32 =
51928 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
51929 +
51930 +                       if (depctl.b.epdis && deptsiz.d32) {
51931 +                               set_current_pkt_info(GET_CORE_IF(pcd),
51932 +                                                    &pcd->out_ep[i].dwc_ep);
51933 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
51934 +                                       dwc_ep->cur_pkt = 0;
51935 +                                       dwc_ep->proc_buf_num =
51936 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
51937 +
51938 +                                       if (dwc_ep->proc_buf_num) {
51939 +                                               dwc_ep->cur_pkt_addr =
51940 +                                                   dwc_ep->xfer_buff1;
51941 +                                               dwc_ep->cur_pkt_dma_addr =
51942 +                                                   dwc_ep->dma_addr1;
51943 +                                       } else {
51944 +                                               dwc_ep->cur_pkt_addr =
51945 +                                                   dwc_ep->xfer_buff0;
51946 +                                               dwc_ep->cur_pkt_dma_addr =
51947 +                                                   dwc_ep->dma_addr0;
51948 +                                       }
51949 +
51950 +                               }
51951 +
51952 +                               dsts.d32 =
51953 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
51954 +                                                  dev_global_regs->dsts);
51955 +                               dwc_ep->next_frame = dsts.b.soffn;
51956 +
51957 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
51958 +                                                                 (pcd),
51959 +                                                                 dwc_ep);
51960 +                       }
51961 +               }
51962 +       }
51963 +#else
51964 +       /** @todo implement ISR */
51965 +       gintmsk_data_t intr_mask = {.d32 = 0 };
51966 +       dwc_otg_core_if_t *core_if;
51967 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51968 +       depctl_data_t depctl = {.d32 = 0 };
51969 +       dctl_data_t dctl = {.d32 = 0 };
51970 +       dwc_ep_t *dwc_ep = NULL;
51971 +       int i;
51972 +       core_if = GET_CORE_IF(pcd);
51973 +
51974 +       for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
51975 +               dwc_ep = &pcd->out_ep[i].dwc_ep;
51976 +               depctl.d32 =
51977 +                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
51978 +               if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
51979 +                       core_if->dev_if->isoc_ep = dwc_ep;
51980 +                       deptsiz.d32 =
51981 +                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
51982 +                               break;
51983 +               }
51984 +       }
51985 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
51986 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
51987 +       intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
51988 +
51989 +       if (!intr_mask.b.goutnakeff) {
51990 +               /* Unmask it */
51991 +               intr_mask.b.goutnakeff = 1;
51992 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
51993 +       }
51994 +       if (!gintsts.b.goutnakeff) {
51995 +               dctl.b.sgoutnak = 1;
51996 +       }
51997 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
51998 +
51999 +       depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52000 +       if (depctl.b.epena) {
52001 +               depctl.b.epdis = 1;
52002 +               depctl.b.snak = 1;
52003 +       }
52004 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
52005 +
52006 +       intr_mask.d32 = 0;
52007 +       intr_mask.b.incomplisoout = 1;
52008 +
52009 +#endif /* DWC_EN_ISOC */
52010 +
52011 +       /* Clear interrupt */
52012 +       gintsts.d32 = 0;
52013 +       gintsts.b.incomplisoout = 1;
52014 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52015 +                       gintsts.d32);
52016 +
52017 +       return 1;
52018 +}
52019 +
52020 +/**
52021 + * This function handles the Global IN NAK Effective interrupt.
52022 + *
52023 + */
52024 +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
52025 +{
52026 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52027 +       depctl_data_t diepctl = {.d32 = 0 };
52028 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52029 +       gintsts_data_t gintsts;
52030 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52031 +       int i;
52032 +
52033 +       DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
52034 +
52035 +       /* Disable all active IN EPs */
52036 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
52037 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52038 +               if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
52039 +                       if (core_if->start_predict > 0)
52040 +                               core_if->start_predict++;
52041 +                       diepctl.b.epdis = 1;
52042 +                       diepctl.b.snak = 1;
52043 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
52044 +               }
52045 +       }
52046 +
52047 +
52048 +       /* Disable the Global IN NAK Effective Interrupt */
52049 +       intr_mask.b.ginnakeff = 1;
52050 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52051 +                        intr_mask.d32, 0);
52052 +
52053 +       /* Clear interrupt */
52054 +       gintsts.d32 = 0;
52055 +       gintsts.b.ginnakeff = 1;
52056 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52057 +                       gintsts.d32);
52058 +
52059 +       return 1;
52060 +}
52061 +
52062 +/**
52063 + * OUT NAK Effective.
52064 + *
52065 + */
52066 +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
52067 +{
52068 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52069 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52070 +       gintsts_data_t gintsts;
52071 +       depctl_data_t doepctl;
52072 +       int i;
52073 +
52074 +       /* Disable the Global OUT NAK Effective Interrupt */
52075 +       intr_mask.b.goutnakeff = 1;
52076 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52077 +               intr_mask.d32, 0);
52078 +
52079 +       /* If DEV OUT NAK enabled*/
52080 +       if (pcd->core_if->core_params->dev_out_nak) {
52081 +               /* Run over all out endpoints to determine the ep number on
52082 +                * which the timeout has happened
52083 +                */
52084 +               for (i = 0; i <= dev_if->num_out_eps; i++) {
52085 +                       if ( pcd->core_if->ep_xfer_info[i].state == 2 )
52086 +                               break;
52087 +               }
52088 +               if (i > dev_if->num_out_eps) {
52089 +                       dctl_data_t dctl;
52090 +                       dctl.d32 =
52091 +                           DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
52092 +                       dctl.b.cgoutnak = 1;
52093 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
52094 +                               dctl.d32);
52095 +                       goto out;
52096 +               }
52097 +
52098 +               /* Disable the endpoint */
52099 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52100 +               if (doepctl.b.epena) {
52101 +                       doepctl.b.epdis = 1;
52102 +                       doepctl.b.snak = 1;
52103 +               }
52104 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
52105 +               return 1;
52106 +       }
52107 +       /* We come here from Incomplete ISO OUT handler */
52108 +       if (dev_if->isoc_ep) {
52109 +               dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
52110 +               uint32_t epnum = dwc_ep->num;
52111 +               doepint_data_t doepint;
52112 +               doepint.d32 =
52113 +                   DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
52114 +               dev_if->isoc_ep = NULL;
52115 +               doepctl.d32 =
52116 +                   DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
52117 +               DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
52118 +               if (doepctl.b.epena) {
52119 +                       doepctl.b.epdis = 1;
52120 +                       doepctl.b.snak = 1;
52121 +               }
52122 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
52123 +                               doepctl.d32);
52124 +               return 1;
52125 +       } else
52126 +               DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
52127 +                          "Global OUT NAK Effective\n");
52128 +
52129 +out:
52130 +       /* Clear interrupt */
52131 +       gintsts.d32 = 0;
52132 +       gintsts.b.goutnakeff = 1;
52133 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52134 +                       gintsts.d32);
52135 +
52136 +       return 1;
52137 +}
52138 +
52139 +/**
52140 + * PCD interrupt handler.
52141 + *
52142 + * The PCD handles the device interrupts.  Many conditions can cause a
52143 + * device interrupt. When an interrupt occurs, the device interrupt
52144 + * service routine determines the cause of the interrupt and
52145 + * dispatches handling to the appropriate function. These interrupt
52146 + * handling functions are described below.
52147 + *
52148 + * All interrupt registers are processed from LSB to MSB.
52149 + *
52150 + */
52151 +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
52152 +{
52153 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52154 +#ifdef VERBOSE
52155 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
52156 +#endif
52157 +       gintsts_data_t gintr_status;
52158 +       int32_t retval = 0;
52159 +
52160 +       /* Exit from ISR if core is hibernated */
52161 +       if (core_if->hibernation_suspend == 1) {
52162 +               return retval;
52163 +       }
52164 +#ifdef VERBOSE
52165 +       DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n",
52166 +                   __func__,
52167 +                   DWC_READ_REG32(&global_regs->gintsts),
52168 +                   DWC_READ_REG32(&global_regs->gintmsk));
52169 +#endif
52170 +
52171 +       if (dwc_otg_is_device_mode(core_if)) {
52172 +               DWC_SPINLOCK(pcd->lock);
52173 +#ifdef VERBOSE
52174 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",
52175 +                           __func__,
52176 +                           DWC_READ_REG32(&global_regs->gintsts),
52177 +                           DWC_READ_REG32(&global_regs->gintmsk));
52178 +#endif
52179 +
52180 +               gintr_status.d32 = dwc_otg_read_core_intr(core_if);
52181 +
52182 +               DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
52183 +                           __func__, gintr_status.d32);
52184 +
52185 +               if (gintr_status.b.sofintr) {
52186 +                       retval |= dwc_otg_pcd_handle_sof_intr(pcd);
52187 +               }
52188 +               if (gintr_status.b.rxstsqlvl) {
52189 +                       retval |=
52190 +                           dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
52191 +               }
52192 +               if (gintr_status.b.nptxfempty) {
52193 +                       retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
52194 +               }
52195 +               if (gintr_status.b.goutnakeff) {
52196 +                       retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
52197 +               }
52198 +               if (gintr_status.b.i2cintr) {
52199 +                       retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
52200 +               }
52201 +               if (gintr_status.b.erlysuspend) {
52202 +                       retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
52203 +               }
52204 +               if (gintr_status.b.usbreset) {
52205 +                       retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
52206 +               }
52207 +               if (gintr_status.b.enumdone) {
52208 +                       retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
52209 +               }
52210 +               if (gintr_status.b.isooutdrop) {
52211 +                       retval |=
52212 +                           dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
52213 +                           (pcd);
52214 +               }
52215 +               if (gintr_status.b.eopframe) {
52216 +                       retval |=
52217 +                           dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
52218 +               }
52219 +               if (gintr_status.b.inepint) {
52220 +                       if (!core_if->multiproc_int_enable) {
52221 +                               retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52222 +                       }
52223 +               }
52224 +               if (gintr_status.b.outepintr) {
52225 +                       if (!core_if->multiproc_int_enable) {
52226 +                               retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52227 +                       }
52228 +               }
52229 +               if (gintr_status.b.epmismatch) {
52230 +                       retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
52231 +               }
52232 +               if (gintr_status.b.fetsusp) {
52233 +                       retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
52234 +               }
52235 +               if (gintr_status.b.ginnakeff) {
52236 +                       retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
52237 +               }
52238 +               if (gintr_status.b.incomplisoin) {
52239 +                       retval |=
52240 +                           dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
52241 +               }
52242 +               if (gintr_status.b.incomplisoout) {
52243 +                       retval |=
52244 +                           dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
52245 +               }
52246 +
52247 +               /* In MPI mode Device Endpoints interrupts are asserted
52248 +                * without setting outepintr and inepint bits set, so these
52249 +                * Interrupt handlers are called without checking these bit-fields
52250 +                */
52251 +               if (core_if->multiproc_int_enable) {
52252 +                       retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52253 +                       retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52254 +               }
52255 +#ifdef VERBOSE
52256 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
52257 +                           DWC_READ_REG32(&global_regs->gintsts));
52258 +#endif
52259 +               DWC_SPINUNLOCK(pcd->lock);
52260 +       }
52261 +       return retval;
52262 +}
52263 +
52264 +#endif /* DWC_HOST_ONLY */
52265 --- /dev/null
52266 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52267 @@ -0,0 +1,1358 @@
52268 + /* ==========================================================================
52269 +  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
52270 +  * $Revision: #21 $
52271 +  * $Date: 2012/08/10 $
52272 +  * $Change: 2047372 $
52273 +  *
52274 +  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
52275 +  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
52276 +  * otherwise expressly agreed to in writing between Synopsys and you.
52277 +  *
52278 +  * The Software IS NOT an item of Licensed Software or Licensed Product under
52279 +  * any End User Software License Agreement or Agreement for Licensed Product
52280 +  * with Synopsys or any supplement thereto. You are permitted to use and
52281 +  * redistribute this Software in source and binary forms, with or without
52282 +  * modification, provided that redistributions of source code must retain this
52283 +  * notice. You may not view, use, disclose, copy or distribute this file or
52284 +  * any information contained herein except pursuant to this license grant from
52285 +  * Synopsys. If you do not agree with this notice, including the disclaimer
52286 +  * below, then you are not authorized to use the Software.
52287 +  *
52288 +  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
52289 +  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52290 +  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52291 +  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
52292 +  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52293 +  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
52294 +  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52295 +  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52296 +  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52297 +  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52298 +  * DAMAGE.
52299 +  * ========================================================================== */
52300 +#ifndef DWC_HOST_ONLY
52301 +
52302 +/** @file
52303 + * This file implements the Peripheral Controller Driver.
52304 + *
52305 + * The Peripheral Controller Driver (PCD) is responsible for
52306 + * translating requests from the Function Driver into the appropriate
52307 + * actions on the DWC_otg controller. It isolates the Function Driver
52308 + * from the specifics of the controller by providing an API to the
52309 + * Function Driver.
52310 + *
52311 + * The Peripheral Controller Driver for Linux will implement the
52312 + * Gadget API, so that the existing Gadget drivers can be used.
52313 + * (Gadget Driver is the Linux terminology for a Function Driver.)
52314 + *
52315 + * The Linux Gadget API is defined in the header file
52316 + * <code><linux/usb_gadget.h></code>.  The USB EP operations API is
52317 + * defined in the structure <code>usb_ep_ops</code> and the USB
52318 + * Controller API is defined in the structure
52319 + * <code>usb_gadget_ops</code>.
52320 + *
52321 + */
52322 +
52323 +#include "dwc_otg_os_dep.h"
52324 +#include "dwc_otg_pcd_if.h"
52325 +#include "dwc_otg_pcd.h"
52326 +#include "dwc_otg_driver.h"
52327 +#include "dwc_otg_dbg.h"
52328 +
52329 +static struct gadget_wrapper {
52330 +       dwc_otg_pcd_t *pcd;
52331 +
52332 +       struct usb_gadget gadget;
52333 +       struct usb_gadget_driver *driver;
52334 +
52335 +       struct usb_ep ep0;
52336 +       struct usb_ep in_ep[16];
52337 +       struct usb_ep out_ep[16];
52338 +
52339 +} *gadget_wrapper;
52340 +
52341 +/* Display the contents of the buffer */
52342 +extern void dump_msg(const u8 * buf, unsigned int length);
52343 +/**
52344 + * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
52345 + * if the endpoint is not found
52346 + */
52347 +static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
52348 +{
52349 +       int i;
52350 +       if (pcd->ep0.priv == handle) {
52351 +               return &pcd->ep0;
52352 +       }
52353 +
52354 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
52355 +               if (pcd->in_ep[i].priv == handle)
52356 +                       return &pcd->in_ep[i];
52357 +               if (pcd->out_ep[i].priv == handle)
52358 +                       return &pcd->out_ep[i];
52359 +       }
52360 +
52361 +       return NULL;
52362 +}
52363 +
52364 +/* USB Endpoint Operations */
52365 +/*
52366 + * The following sections briefly describe the behavior of the Gadget
52367 + * API endpoint operations implemented in the DWC_otg driver
52368 + * software. Detailed descriptions of the generic behavior of each of
52369 + * these functions can be found in the Linux header file
52370 + * include/linux/usb_gadget.h.
52371 + *
52372 + * The Gadget API provides wrapper functions for each of the function
52373 + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
52374 + * function, which then calls the underlying PCD function. The
52375 + * following sections are named according to the wrapper
52376 + * functions. Within each section, the corresponding DWC_otg PCD
52377 + * function name is specified.
52378 + *
52379 + */
52380 +
52381 +/**
52382 + * This function is called by the Gadget Driver for each EP to be
52383 + * configured for the current configuration (SET_CONFIGURATION).
52384 + *
52385 + * This function initializes the dwc_otg_ep_t data structure, and then
52386 + * calls dwc_otg_ep_activate.
52387 + */
52388 +static int ep_enable(struct usb_ep *usb_ep,
52389 +                    const struct usb_endpoint_descriptor *ep_desc)
52390 +{
52391 +       int retval;
52392 +
52393 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
52394 +
52395 +       if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
52396 +               DWC_WARN("%s, bad ep or descriptor\n", __func__);
52397 +               return -EINVAL;
52398 +       }
52399 +       if (usb_ep == &gadget_wrapper->ep0) {
52400 +               DWC_WARN("%s, bad ep(0)\n", __func__);
52401 +               return -EINVAL;
52402 +       }
52403 +
52404 +       /* Check FIFO size? */
52405 +       if (!ep_desc->wMaxPacketSize) {
52406 +               DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
52407 +               return -ERANGE;
52408 +       }
52409 +
52410 +       if (!gadget_wrapper->driver ||
52411 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52412 +               DWC_WARN("%s, bogus device state\n", __func__);
52413 +               return -ESHUTDOWN;
52414 +       }
52415 +
52416 +       /* Delete after check - MAS */
52417 +#if 0
52418 +       nat = (uint32_t) ep_desc->wMaxPacketSize;
52419 +       printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
52420 +       nat = (nat >> 11) & 0x03;
52421 +       printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
52422 +#endif
52423 +       retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
52424 +                                      (const uint8_t *)ep_desc,
52425 +                                      (void *)usb_ep);
52426 +       if (retval) {
52427 +               DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
52428 +               return -EINVAL;
52429 +       }
52430 +
52431 +       usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
52432 +
52433 +       return 0;
52434 +}
52435 +
52436 +/**
52437 + * This function is called when an EP is disabled due to disconnect or
52438 + * change in configuration. Any pending requests will terminate with a
52439 + * status of -ESHUTDOWN.
52440 + *
52441 + * This function modifies the dwc_otg_ep_t data structure for this EP,
52442 + * and then calls dwc_otg_ep_deactivate.
52443 + */
52444 +static int ep_disable(struct usb_ep *usb_ep)
52445 +{
52446 +       int retval;
52447 +
52448 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
52449 +       if (!usb_ep) {
52450 +               DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
52451 +                           usb_ep ? usb_ep->name : NULL);
52452 +               return -EINVAL;
52453 +       }
52454 +
52455 +       retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
52456 +       if (retval) {
52457 +               retval = -EINVAL;
52458 +       }
52459 +
52460 +       return retval;
52461 +}
52462 +
52463 +/**
52464 + * This function allocates a request object to use with the specified
52465 + * endpoint.
52466 + *
52467 + * @param ep The endpoint to be used with with the request
52468 + * @param gfp_flags the GFP_* flags to use.
52469 + */
52470 +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
52471 +                                                    gfp_t gfp_flags)
52472 +{
52473 +       struct usb_request *usb_req;
52474 +
52475 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
52476 +       if (0 == ep) {
52477 +               DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
52478 +               return 0;
52479 +       }
52480 +       usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
52481 +       if (0 == usb_req) {
52482 +               DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
52483 +               return 0;
52484 +       }
52485 +       memset(usb_req, 0, sizeof(*usb_req));
52486 +       usb_req->dma = DWC_DMA_ADDR_INVALID;
52487 +
52488 +       return usb_req;
52489 +}
52490 +
52491 +/**
52492 + * This function frees a request object.
52493 + *
52494 + * @param ep The endpoint associated with the request
52495 + * @param req The request being freed
52496 + */
52497 +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
52498 +{
52499 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
52500 +
52501 +       if (0 == ep || 0 == req) {
52502 +               DWC_WARN("%s() %s\n", __func__,
52503 +                        "Invalid ep or req argument!\n");
52504 +               return;
52505 +       }
52506 +
52507 +       kfree(req);
52508 +}
52509 +
52510 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52511 +/**
52512 + * This function allocates an I/O buffer to be used for a transfer
52513 + * to/from the specified endpoint.
52514 + *
52515 + * @param usb_ep The endpoint to be used with with the request
52516 + * @param bytes The desired number of bytes for the buffer
52517 + * @param dma Pointer to the buffer's DMA address; must be valid
52518 + * @param gfp_flags the GFP_* flags to use.
52519 + * @return address of a new buffer or null is buffer could not be allocated.
52520 + */
52521 +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
52522 +                                     dma_addr_t * dma, gfp_t gfp_flags)
52523 +{
52524 +       void *buf;
52525 +       dwc_otg_pcd_t *pcd = 0;
52526 +
52527 +       pcd = gadget_wrapper->pcd;
52528 +
52529 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
52530 +                   dma, gfp_flags);
52531 +
52532 +       /* Check dword alignment */
52533 +       if ((bytes & 0x3UL) != 0) {
52534 +               DWC_WARN("%s() Buffer size is not a multiple of"
52535 +                        "DWORD size (%d)", __func__, bytes);
52536 +       }
52537 +
52538 +       buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
52539 +
52540 +       /* Check dword alignment */
52541 +       if (((int)buf & 0x3UL) != 0) {
52542 +               DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
52543 +                        __func__, buf);
52544 +       }
52545 +
52546 +       return buf;
52547 +}
52548 +
52549 +/**
52550 + * This function frees an I/O buffer that was allocated by alloc_buffer.
52551 + *
52552 + * @param usb_ep the endpoint associated with the buffer
52553 + * @param buf address of the buffer
52554 + * @param dma The buffer's DMA address
52555 + * @param bytes The number of bytes of the buffer
52556 + */
52557 +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
52558 +                                   dma_addr_t dma, unsigned bytes)
52559 +{
52560 +       dwc_otg_pcd_t *pcd = 0;
52561 +
52562 +       pcd = gadget_wrapper->pcd;
52563 +
52564 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
52565 +
52566 +       dma_free_coherent(NULL, bytes, buf, dma);
52567 +}
52568 +#endif
52569 +
52570 +/**
52571 + * This function is used to submit an I/O Request to an EP.
52572 + *
52573 + *     - When the request completes the request's completion callback
52574 + *       is called to return the request to the driver.
52575 + *     - An EP, except control EPs, may have multiple requests
52576 + *       pending.
52577 + *     - Once submitted the request cannot be examined or modified.
52578 + *     - Each request is turned into one or more packets.
52579 + *     - A BULK EP can queue any amount of data; the transfer is
52580 + *       packetized.
52581 + *     - Zero length Packets are specified with the request 'zero'
52582 + *       flag.
52583 + */
52584 +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
52585 +                   gfp_t gfp_flags)
52586 +{
52587 +       dwc_otg_pcd_t *pcd;
52588 +       struct dwc_otg_pcd_ep *ep = NULL;
52589 +       int retval = 0, is_isoc_ep = 0;
52590 +       dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
52591 +
52592 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
52593 +                   __func__, usb_ep, usb_req, gfp_flags);
52594 +
52595 +       if (!usb_req || !usb_req->complete || !usb_req->buf) {
52596 +               DWC_WARN("bad params\n");
52597 +               return -EINVAL;
52598 +       }
52599 +
52600 +       if (!usb_ep) {
52601 +               DWC_WARN("bad ep\n");
52602 +               return -EINVAL;
52603 +       }
52604 +
52605 +       pcd = gadget_wrapper->pcd;
52606 +       if (!gadget_wrapper->driver ||
52607 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52608 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52609 +                           gadget_wrapper->gadget.speed);
52610 +               DWC_WARN("bogus device state\n");
52611 +               return -ESHUTDOWN;
52612 +       }
52613 +
52614 +       DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
52615 +                   usb_ep->name, usb_req, usb_req->length, usb_req->buf);
52616 +
52617 +       usb_req->status = -EINPROGRESS;
52618 +       usb_req->actual = 0;
52619 +
52620 +       ep = ep_from_handle(pcd, usb_ep);
52621 +       if (ep == NULL)
52622 +               is_isoc_ep = 0;
52623 +       else
52624 +               is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
52625 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52626 +       dma_addr = usb_req->dma;
52627 +#else
52628 +       if (GET_CORE_IF(pcd)->dma_enable) {
52629 +                dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
52630 +                struct device *dev = NULL;
52631 +
52632 +                if (otg_dev != NULL)
52633 +                        dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
52634 +
52635 +               if (usb_req->length != 0 &&
52636 +                    usb_req->dma == DWC_DMA_ADDR_INVALID) {
52637 +                        dma_addr = dma_map_single(dev, usb_req->buf,
52638 +                                                  usb_req->length,
52639 +                                                  ep->dwc_ep.is_in ?
52640 +                                                        DMA_TO_DEVICE:
52641 +                                                        DMA_FROM_DEVICE);
52642 +               }
52643 +       }
52644 +#endif
52645 +
52646 +#ifdef DWC_UTE_PER_IO
52647 +       if (is_isoc_ep == 1) {
52648 +               retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52649 +                       usb_req->length, usb_req->zero, usb_req,
52650 +                       gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
52651 +               if (retval)
52652 +                       return -EINVAL;
52653 +
52654 +               return 0;
52655 +       }
52656 +#endif
52657 +       retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52658 +                                     usb_req->length, usb_req->zero, usb_req,
52659 +                                     gfp_flags == GFP_ATOMIC ? 1 : 0);
52660 +       if (retval) {
52661 +               return -EINVAL;
52662 +       }
52663 +
52664 +       return 0;
52665 +}
52666 +
52667 +/**
52668 + * This function cancels an I/O request from an EP.
52669 + */
52670 +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
52671 +{
52672 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
52673 +
52674 +       if (!usb_ep || !usb_req) {
52675 +               DWC_WARN("bad argument\n");
52676 +               return -EINVAL;
52677 +       }
52678 +       if (!gadget_wrapper->driver ||
52679 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52680 +               DWC_WARN("bogus device state\n");
52681 +               return -ESHUTDOWN;
52682 +       }
52683 +       if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
52684 +               return -EINVAL;
52685 +       }
52686 +
52687 +       return 0;
52688 +}
52689 +
52690 +/**
52691 + * usb_ep_set_halt stalls an endpoint.
52692 + *
52693 + * usb_ep_clear_halt clears an endpoint halt and resets its data
52694 + * toggle.
52695 + *
52696 + * Both of these functions are implemented with the same underlying
52697 + * function. The behavior depends on the value argument.
52698 + *
52699 + * @param[in] usb_ep the Endpoint to halt or clear halt.
52700 + * @param[in] value
52701 + *     - 0 means clear_halt.
52702 + *     - 1 means set_halt,
52703 + *     - 2 means clear stall lock flag.
52704 + *     - 3 means set  stall lock flag.
52705 + */
52706 +static int ep_halt(struct usb_ep *usb_ep, int value)
52707 +{
52708 +       int retval = 0;
52709 +
52710 +       DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
52711 +
52712 +       if (!usb_ep) {
52713 +               DWC_WARN("bad ep\n");
52714 +               return -EINVAL;
52715 +       }
52716 +
52717 +       retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
52718 +       if (retval == -DWC_E_AGAIN) {
52719 +               return -EAGAIN;
52720 +       } else if (retval) {
52721 +               retval = -EINVAL;
52722 +       }
52723 +
52724 +       return retval;
52725 +}
52726 +
52727 +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
52728 +#if 0
52729 +/**
52730 + * ep_wedge: sets the halt feature and ignores clear requests
52731 + *
52732 + * @usb_ep: the endpoint being wedged
52733 + *
52734 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
52735 + * requests. If the gadget driver clears the halt status, it will
52736 + * automatically unwedge the endpoint.
52737 + *
52738 + * Returns zero on success, else negative errno. *
52739 + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
52740 + */
52741 +static int ep_wedge(struct usb_ep *usb_ep)
52742 +{
52743 +       int retval = 0;
52744 +
52745 +       DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
52746 +
52747 +       if (!usb_ep) {
52748 +               DWC_WARN("bad ep\n");
52749 +               return -EINVAL;
52750 +       }
52751 +
52752 +       retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
52753 +       if (retval == -DWC_E_AGAIN) {
52754 +               retval = -EAGAIN;
52755 +       } else if (retval) {
52756 +               retval = -EINVAL;
52757 +       }
52758 +
52759 +       return retval;
52760 +}
52761 +#endif
52762 +
52763 +#ifdef DWC_EN_ISOC
52764 +/**
52765 + * This function is used to submit an ISOC Transfer Request to an EP.
52766 + *
52767 + *     - Every time a sync period completes the request's completion callback
52768 + *       is called to provide data to the gadget driver.
52769 + *     - Once submitted the request cannot be modified.
52770 + *     - Each request is turned into periodic data packets untill ISO
52771 + *       Transfer is stopped..
52772 + */
52773 +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
52774 +                       gfp_t gfp_flags)
52775 +{
52776 +       int retval = 0;
52777 +
52778 +       if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
52779 +               DWC_WARN("bad params\n");
52780 +               return -EINVAL;
52781 +       }
52782 +
52783 +       if (!usb_ep) {
52784 +               DWC_PRINTF("bad params\n");
52785 +               return -EINVAL;
52786 +       }
52787 +
52788 +       req->status = -EINPROGRESS;
52789 +
52790 +       retval =
52791 +           dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
52792 +                                    req->buf1, req->dma0, req->dma1,
52793 +                                    req->sync_frame, req->data_pattern_frame,
52794 +                                    req->data_per_frame,
52795 +                                    req->
52796 +                                    flags & USB_REQ_ISO_ASAP ? -1 :
52797 +                                    req->start_frame, req->buf_proc_intrvl,
52798 +                                    req, gfp_flags == GFP_ATOMIC ? 1 : 0);
52799 +
52800 +       if (retval) {
52801 +               return -EINVAL;
52802 +       }
52803 +
52804 +       return retval;
52805 +}
52806 +
52807 +/**
52808 + * This function stops ISO EP Periodic Data Transfer.
52809 + */
52810 +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
52811 +{
52812 +       int retval = 0;
52813 +       if (!usb_ep) {
52814 +               DWC_WARN("bad ep\n");
52815 +       }
52816 +
52817 +       if (!gadget_wrapper->driver ||
52818 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52819 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52820 +                           gadget_wrapper->gadget.speed);
52821 +               DWC_WARN("bogus device state\n");
52822 +       }
52823 +
52824 +       dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
52825 +       if (retval) {
52826 +               retval = -EINVAL;
52827 +       }
52828 +
52829 +       return retval;
52830 +}
52831 +
52832 +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
52833 +                                                int packets, gfp_t gfp_flags)
52834 +{
52835 +       struct usb_iso_request *pReq = NULL;
52836 +       uint32_t req_size;
52837 +
52838 +       req_size = sizeof(struct usb_iso_request);
52839 +       req_size +=
52840 +           (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
52841 +
52842 +       pReq = kmalloc(req_size, gfp_flags);
52843 +       if (!pReq) {
52844 +               DWC_WARN("Can't allocate Iso Request\n");
52845 +               return 0;
52846 +       }
52847 +       pReq->iso_packet_desc0 = (void *)(pReq + 1);
52848 +
52849 +       pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
52850 +
52851 +       return pReq;
52852 +}
52853 +
52854 +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
52855 +{
52856 +       kfree(req);
52857 +}
52858 +
52859 +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
52860 +       .ep_ops = {
52861 +                  .enable = ep_enable,
52862 +                  .disable = ep_disable,
52863 +
52864 +                  .alloc_request = dwc_otg_pcd_alloc_request,
52865 +                  .free_request = dwc_otg_pcd_free_request,
52866 +
52867 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52868 +                  .alloc_buffer = dwc_otg_pcd_alloc_buffer,
52869 +                  .free_buffer = dwc_otg_pcd_free_buffer,
52870 +#endif
52871 +
52872 +                  .queue = ep_queue,
52873 +                  .dequeue = ep_dequeue,
52874 +
52875 +                  .set_halt = ep_halt,
52876 +                  .fifo_status = 0,
52877 +                  .fifo_flush = 0,
52878 +                  },
52879 +       .iso_ep_start = iso_ep_start,
52880 +       .iso_ep_stop = iso_ep_stop,
52881 +       .alloc_iso_request = alloc_iso_request,
52882 +       .free_iso_request = free_iso_request,
52883 +};
52884 +
52885 +#else
52886 +
52887 +       int (*enable) (struct usb_ep *ep,
52888 +               const struct usb_endpoint_descriptor *desc);
52889 +       int (*disable) (struct usb_ep *ep);
52890 +
52891 +       struct usb_request *(*alloc_request) (struct usb_ep *ep,
52892 +               gfp_t gfp_flags);
52893 +       void (*free_request) (struct usb_ep *ep, struct usb_request *req);
52894 +
52895 +       int (*queue) (struct usb_ep *ep, struct usb_request *req,
52896 +               gfp_t gfp_flags);
52897 +       int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
52898 +
52899 +       int (*set_halt) (struct usb_ep *ep, int value);
52900 +       int (*set_wedge) (struct usb_ep *ep);
52901 +
52902 +       int (*fifo_status) (struct usb_ep *ep);
52903 +       void (*fifo_flush) (struct usb_ep *ep);
52904 +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
52905 +       .enable = ep_enable,
52906 +       .disable = ep_disable,
52907 +
52908 +       .alloc_request = dwc_otg_pcd_alloc_request,
52909 +       .free_request = dwc_otg_pcd_free_request,
52910 +
52911 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52912 +       .alloc_buffer = dwc_otg_pcd_alloc_buffer,
52913 +       .free_buffer = dwc_otg_pcd_free_buffer,
52914 +#else
52915 +       /* .set_wedge = ep_wedge, */
52916 +        .set_wedge = NULL, /* uses set_halt instead */
52917 +#endif
52918 +
52919 +       .queue = ep_queue,
52920 +       .dequeue = ep_dequeue,
52921 +
52922 +       .set_halt = ep_halt,
52923 +       .fifo_status = 0,
52924 +       .fifo_flush = 0,
52925 +
52926 +};
52927 +
52928 +#endif /* _EN_ISOC_ */
52929 +/*     Gadget Operations */
52930 +/**
52931 + * The following gadget operations will be implemented in the DWC_otg
52932 + * PCD. Functions in the API that are not described below are not
52933 + * implemented.
52934 + *
52935 + * The Gadget API provides wrapper functions for each of the function
52936 + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
52937 + * wrapper function, which then calls the underlying PCD function. The
52938 + * following sections are named according to the wrapper functions
52939 + * (except for ioctl, which doesn't have a wrapper function). Within
52940 + * each section, the corresponding DWC_otg PCD function name is
52941 + * specified.
52942 + *
52943 + */
52944 +
52945 +/**
52946 + *Gets the USB Frame number of the last SOF.
52947 + */
52948 +static int get_frame_number(struct usb_gadget *gadget)
52949 +{
52950 +       struct gadget_wrapper *d;
52951 +
52952 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
52953 +
52954 +       if (gadget == 0) {
52955 +               return -ENODEV;
52956 +       }
52957 +
52958 +       d = container_of(gadget, struct gadget_wrapper, gadget);
52959 +       return dwc_otg_pcd_get_frame_number(d->pcd);
52960 +}
52961 +
52962 +#ifdef CONFIG_USB_DWC_OTG_LPM
52963 +static int test_lpm_enabled(struct usb_gadget *gadget)
52964 +{
52965 +       struct gadget_wrapper *d;
52966 +
52967 +       d = container_of(gadget, struct gadget_wrapper, gadget);
52968 +
52969 +       return dwc_otg_pcd_is_lpm_enabled(d->pcd);
52970 +}
52971 +#endif
52972 +
52973 +/**
52974 + * Initiates Session Request Protocol (SRP) to wakeup the host if no
52975 + * session is in progress. If a session is already in progress, but
52976 + * the device is suspended, remote wakeup signaling is started.
52977 + *
52978 + */
52979 +static int wakeup(struct usb_gadget *gadget)
52980 +{
52981 +       struct gadget_wrapper *d;
52982 +
52983 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
52984 +
52985 +       if (gadget == 0) {
52986 +               return -ENODEV;
52987 +       } else {
52988 +               d = container_of(gadget, struct gadget_wrapper, gadget);
52989 +       }
52990 +       dwc_otg_pcd_wakeup(d->pcd);
52991 +       return 0;
52992 +}
52993 +
52994 +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
52995 +       .get_frame = get_frame_number,
52996 +       .wakeup = wakeup,
52997 +#ifdef CONFIG_USB_DWC_OTG_LPM
52998 +       .lpm_support = test_lpm_enabled,
52999 +#endif
53000 +       // current versions must always be self-powered
53001 +};
53002 +
53003 +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
53004 +{
53005 +       int retval = -DWC_E_NOT_SUPPORTED;
53006 +       if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
53007 +               retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
53008 +                                                      (struct usb_ctrlrequest
53009 +                                                       *)bytes);
53010 +       }
53011 +
53012 +       if (retval == -ENOTSUPP) {
53013 +               retval = -DWC_E_NOT_SUPPORTED;
53014 +       } else if (retval < 0) {
53015 +               retval = -DWC_E_INVALID;
53016 +       }
53017 +
53018 +       return retval;
53019 +}
53020 +
53021 +#ifdef DWC_EN_ISOC
53022 +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53023 +                         void *req_handle, int proc_buf_num)
53024 +{
53025 +       int i, packet_count;
53026 +       struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
53027 +       struct usb_iso_request *iso_req = req_handle;
53028 +
53029 +       if (proc_buf_num) {
53030 +               iso_packet = iso_req->iso_packet_desc1;
53031 +       } else {
53032 +               iso_packet = iso_req->iso_packet_desc0;
53033 +       }
53034 +       packet_count =
53035 +           dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
53036 +       for (i = 0; i < packet_count; ++i) {
53037 +               int status;
53038 +               int actual;
53039 +               int offset;
53040 +               dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
53041 +                                                 i, &status, &actual, &offset);
53042 +               switch (status) {
53043 +               case -DWC_E_NO_DATA:
53044 +                       status = -ENODATA;
53045 +                       break;
53046 +               default:
53047 +                       if (status) {
53048 +                               DWC_PRINTF("unknown status in isoc packet\n");
53049 +                       }
53050 +
53051 +               }
53052 +               iso_packet[i].status = status;
53053 +               iso_packet[i].offset = offset;
53054 +               iso_packet[i].actual_length = actual;
53055 +       }
53056 +
53057 +       iso_req->status = 0;
53058 +       iso_req->process_buffer(ep_handle, iso_req);
53059 +
53060 +       return 0;
53061 +}
53062 +#endif /* DWC_EN_ISOC */
53063 +
53064 +#ifdef DWC_UTE_PER_IO
53065 +/**
53066 + * Copy the contents of the extended request to the Linux usb_request's
53067 + * extended part and call the gadget's completion.
53068 + *
53069 + * @param pcd                  Pointer to the pcd structure
53070 + * @param ep_handle            Void pointer to the usb_ep structure
53071 + * @param req_handle   Void pointer to the usb_request structure
53072 + * @param status               Request status returned from the portable logic
53073 + * @param ereq_port            Void pointer to the extended request structure
53074 + *                                             created in the the portable part that contains the
53075 + *                                             results of the processed iso packets.
53076 + */
53077 +static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53078 +                          void *req_handle, int32_t status, void *ereq_port)
53079 +{
53080 +       struct dwc_ute_iso_req_ext *ereqorg = NULL;
53081 +       struct dwc_iso_xreq_port *ereqport = NULL;
53082 +       struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
53083 +       int i;
53084 +       struct usb_request *req;
53085 +       //struct dwc_ute_iso_packet_descriptor *
53086 +       //int status = 0;
53087 +
53088 +       req = (struct usb_request *)req_handle;
53089 +       ereqorg = &req->ext_req;
53090 +       ereqport = (struct dwc_iso_xreq_port *)ereq_port;
53091 +       desc_org = ereqorg->per_io_frame_descs;
53092 +
53093 +       if (req && req->complete) {
53094 +               /* Copy the request data from the portable logic to our request */
53095 +               for (i = 0; i < ereqport->pio_pkt_count; i++) {
53096 +                       desc_org[i].actual_length =
53097 +                           ereqport->per_io_frame_descs[i].actual_length;
53098 +                       desc_org[i].status =
53099 +                           ereqport->per_io_frame_descs[i].status;
53100 +               }
53101 +
53102 +               switch (status) {
53103 +               case -DWC_E_SHUTDOWN:
53104 +                       req->status = -ESHUTDOWN;
53105 +                       break;
53106 +               case -DWC_E_RESTART:
53107 +                       req->status = -ECONNRESET;
53108 +                       break;
53109 +               case -DWC_E_INVALID:
53110 +                       req->status = -EINVAL;
53111 +                       break;
53112 +               case -DWC_E_TIMEOUT:
53113 +                       req->status = -ETIMEDOUT;
53114 +                       break;
53115 +               default:
53116 +                       req->status = status;
53117 +               }
53118 +
53119 +               /* And call the gadget's completion */
53120 +               req->complete(ep_handle, req);
53121 +       }
53122 +
53123 +       return 0;
53124 +}
53125 +#endif /* DWC_UTE_PER_IO */
53126 +
53127 +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53128 +                    void *req_handle, int32_t status, uint32_t actual)
53129 +{
53130 +       struct usb_request *req = (struct usb_request *)req_handle;
53131 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53132 +       struct dwc_otg_pcd_ep *ep = NULL;
53133 +#endif
53134 +
53135 +       if (req && req->complete) {
53136 +               switch (status) {
53137 +               case -DWC_E_SHUTDOWN:
53138 +                       req->status = -ESHUTDOWN;
53139 +                       break;
53140 +               case -DWC_E_RESTART:
53141 +                       req->status = -ECONNRESET;
53142 +                       break;
53143 +               case -DWC_E_INVALID:
53144 +                       req->status = -EINVAL;
53145 +                       break;
53146 +               case -DWC_E_TIMEOUT:
53147 +                       req->status = -ETIMEDOUT;
53148 +                       break;
53149 +               default:
53150 +                       req->status = status;
53151 +
53152 +               }
53153 +
53154 +               req->actual = actual;
53155 +               DWC_SPINUNLOCK(pcd->lock);
53156 +               req->complete(ep_handle, req);
53157 +               DWC_SPINLOCK(pcd->lock);
53158 +       }
53159 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53160 +       ep = ep_from_handle(pcd, ep_handle);
53161 +       if (GET_CORE_IF(pcd)->dma_enable) {
53162 +                if (req->length != 0) {
53163 +                        dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
53164 +                        struct device *dev = NULL;
53165 +
53166 +                        if (otg_dev != NULL)
53167 +                                  dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
53168 +
53169 +                       dma_unmap_single(dev, req->dma, req->length,
53170 +                                         ep->dwc_ep.is_in ?
53171 +                                                DMA_TO_DEVICE: DMA_FROM_DEVICE);
53172 +                }
53173 +       }
53174 +#endif
53175 +
53176 +       return 0;
53177 +}
53178 +
53179 +static int _connect(dwc_otg_pcd_t * pcd, int speed)
53180 +{
53181 +       gadget_wrapper->gadget.speed = speed;
53182 +       return 0;
53183 +}
53184 +
53185 +static int _disconnect(dwc_otg_pcd_t * pcd)
53186 +{
53187 +       if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
53188 +               gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
53189 +       }
53190 +       return 0;
53191 +}
53192 +
53193 +static int _resume(dwc_otg_pcd_t * pcd)
53194 +{
53195 +       if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
53196 +               gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
53197 +       }
53198 +
53199 +       return 0;
53200 +}
53201 +
53202 +static int _suspend(dwc_otg_pcd_t * pcd)
53203 +{
53204 +       if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
53205 +               gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
53206 +       }
53207 +       return 0;
53208 +}
53209 +
53210 +/**
53211 + * This function updates the otg values in the gadget structure.
53212 + */
53213 +static int _hnp_changed(dwc_otg_pcd_t * pcd)
53214 +{
53215 +
53216 +       if (!gadget_wrapper->gadget.is_otg)
53217 +               return 0;
53218 +
53219 +       gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
53220 +       gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
53221 +       gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
53222 +       return 0;
53223 +}
53224 +
53225 +static int _reset(dwc_otg_pcd_t * pcd)
53226 +{
53227 +       return 0;
53228 +}
53229 +
53230 +#ifdef DWC_UTE_CFI
53231 +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
53232 +{
53233 +       int retval = -DWC_E_INVALID;
53234 +       if (gadget_wrapper->driver->cfi_feature_setup) {
53235 +               retval =
53236 +                   gadget_wrapper->driver->
53237 +                   cfi_feature_setup(&gadget_wrapper->gadget,
53238 +                                     (struct cfi_usb_ctrlrequest *)cfi_req);
53239 +       }
53240 +
53241 +       return retval;
53242 +}
53243 +#endif
53244 +
53245 +static const struct dwc_otg_pcd_function_ops fops = {
53246 +       .complete = _complete,
53247 +#ifdef DWC_EN_ISOC
53248 +       .isoc_complete = _isoc_complete,
53249 +#endif
53250 +       .setup = _setup,
53251 +       .disconnect = _disconnect,
53252 +       .connect = _connect,
53253 +       .resume = _resume,
53254 +       .suspend = _suspend,
53255 +       .hnp_changed = _hnp_changed,
53256 +       .reset = _reset,
53257 +#ifdef DWC_UTE_CFI
53258 +       .cfi_setup = _cfi_setup,
53259 +#endif
53260 +#ifdef DWC_UTE_PER_IO
53261 +       .xisoc_complete = _xisoc_complete,
53262 +#endif
53263 +};
53264 +
53265 +/**
53266 + * This function is the top level PCD interrupt handler.
53267 + */
53268 +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
53269 +{
53270 +       dwc_otg_pcd_t *pcd = dev;
53271 +       int32_t retval = IRQ_NONE;
53272 +
53273 +       retval = dwc_otg_pcd_handle_intr(pcd);
53274 +       if (retval != 0) {
53275 +               S3C2410X_CLEAR_EINTPEND();
53276 +       }
53277 +       return IRQ_RETVAL(retval);
53278 +}
53279 +
53280 +/**
53281 + * This function initialized the usb_ep structures to there default
53282 + * state.
53283 + *
53284 + * @param d Pointer on gadget_wrapper.
53285 + */
53286 +void gadget_add_eps(struct gadget_wrapper *d)
53287 +{
53288 +       static const char *names[] = {
53289 +
53290 +               "ep0",
53291 +               "ep1in",
53292 +               "ep2in",
53293 +               "ep3in",
53294 +               "ep4in",
53295 +               "ep5in",
53296 +               "ep6in",
53297 +               "ep7in",
53298 +               "ep8in",
53299 +               "ep9in",
53300 +               "ep10in",
53301 +               "ep11in",
53302 +               "ep12in",
53303 +               "ep13in",
53304 +               "ep14in",
53305 +               "ep15in",
53306 +               "ep1out",
53307 +               "ep2out",
53308 +               "ep3out",
53309 +               "ep4out",
53310 +               "ep5out",
53311 +               "ep6out",
53312 +               "ep7out",
53313 +               "ep8out",
53314 +               "ep9out",
53315 +               "ep10out",
53316 +               "ep11out",
53317 +               "ep12out",
53318 +               "ep13out",
53319 +               "ep14out",
53320 +               "ep15out"
53321 +       };
53322 +
53323 +       int i;
53324 +       struct usb_ep *ep;
53325 +       int8_t dev_endpoints;
53326 +
53327 +       DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
53328 +
53329 +       INIT_LIST_HEAD(&d->gadget.ep_list);
53330 +       d->gadget.ep0 = &d->ep0;
53331 +       d->gadget.speed = USB_SPEED_UNKNOWN;
53332 +
53333 +       INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
53334 +
53335 +       /**
53336 +        * Initialize the EP0 structure.
53337 +        */
53338 +       ep = &d->ep0;
53339 +
53340 +       /* Init the usb_ep structure. */
53341 +       ep->name = names[0];
53342 +       ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53343 +
53344 +       /**
53345 +        * @todo NGS: What should the max packet size be set to
53346 +        * here?  Before EP type is set?
53347 +        */
53348 +       ep->maxpacket = MAX_PACKET_SIZE;
53349 +       dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
53350 +
53351 +       list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53352 +
53353 +       /**
53354 +        * Initialize the EP structures.
53355 +        */
53356 +       dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
53357 +
53358 +       for (i = 0; i < dev_endpoints; i++) {
53359 +               ep = &d->in_ep[i];
53360 +
53361 +               /* Init the usb_ep structure. */
53362 +               ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
53363 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53364 +
53365 +               /**
53366 +                * @todo NGS: What should the max packet size be set to
53367 +                * here?  Before EP type is set?
53368 +                */
53369 +               ep->maxpacket = MAX_PACKET_SIZE;
53370 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53371 +       }
53372 +
53373 +       dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
53374 +
53375 +       for (i = 0; i < dev_endpoints; i++) {
53376 +               ep = &d->out_ep[i];
53377 +
53378 +               /* Init the usb_ep structure. */
53379 +               ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
53380 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53381 +
53382 +               /**
53383 +                * @todo NGS: What should the max packet size be set to
53384 +                * here?  Before EP type is set?
53385 +                */
53386 +               ep->maxpacket = MAX_PACKET_SIZE;
53387 +
53388 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53389 +       }
53390 +
53391 +       /* remove ep0 from the list.  There is a ep0 pointer. */
53392 +       list_del_init(&d->ep0.ep_list);
53393 +
53394 +       d->ep0.maxpacket = MAX_EP0_SIZE;
53395 +}
53396 +
53397 +/**
53398 + * This function releases the Gadget device.
53399 + * required by device_unregister().
53400 + *
53401 + * @todo Should this do something?     Should it free the PCD?
53402 + */
53403 +static void dwc_otg_pcd_gadget_release(struct device *dev)
53404 +{
53405 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
53406 +}
53407 +
53408 +static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)
53409 +{
53410 +       static char pcd_name[] = "dwc_otg_pcd";
53411 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53412 +       struct gadget_wrapper *d;
53413 +       int retval;
53414 +
53415 +       d = DWC_ALLOC(sizeof(*d));
53416 +       if (d == NULL) {
53417 +               return NULL;
53418 +       }
53419 +
53420 +       memset(d, 0, sizeof(*d));
53421 +
53422 +       d->gadget.name = pcd_name;
53423 +       d->pcd = otg_dev->pcd;
53424 +
53425 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
53426 +       strcpy(d->gadget.dev.bus_id, "gadget");
53427 +#else
53428 +       dev_set_name(&d->gadget.dev, "%s", "gadget");
53429 +#endif
53430 +
53431 +       d->gadget.dev.parent = &_dev->dev;
53432 +       d->gadget.dev.release = dwc_otg_pcd_gadget_release;
53433 +       d->gadget.ops = &dwc_otg_pcd_ops;
53434 +       d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;
53435 +       d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
53436 +
53437 +       d->driver = 0;
53438 +       /* Register the gadget device */
53439 +       retval = device_register(&d->gadget.dev);
53440 +       if (retval != 0) {
53441 +               DWC_ERROR("device_register failed\n");
53442 +               DWC_FREE(d);
53443 +               return NULL;
53444 +       }
53445 +
53446 +       return d;
53447 +}
53448 +
53449 +static void free_wrapper(struct gadget_wrapper *d)
53450 +{
53451 +       if (d->driver) {
53452 +               /* should have been done already by driver model core */
53453 +               DWC_WARN("driver '%s' is still registered\n",
53454 +                        d->driver->driver.name);
53455 +               usb_gadget_unregister_driver(d->driver);
53456 +       }
53457 +
53458 +       device_unregister(&d->gadget.dev);
53459 +       DWC_FREE(d);
53460 +}
53461 +
53462 +/**
53463 + * This function initialized the PCD portion of the driver.
53464 + *
53465 + */
53466 +int pcd_init(dwc_bus_dev_t *_dev)
53467 +{
53468 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53469 +       int retval = 0;
53470 +
53471 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
53472 +
53473 +       otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
53474 +
53475 +       if (!otg_dev->pcd) {
53476 +               DWC_ERROR("dwc_otg_pcd_init failed\n");
53477 +               return -ENOMEM;
53478 +       }
53479 +
53480 +       otg_dev->pcd->otg_dev = otg_dev;
53481 +       gadget_wrapper = alloc_wrapper(_dev);
53482 +
53483 +       /*
53484 +        * Initialize EP structures
53485 +        */
53486 +       gadget_add_eps(gadget_wrapper);
53487 +       /*
53488 +        * Setup interupt handler
53489 +        */
53490 +#ifdef PLATFORM_INTERFACE
53491 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53492 +                    platform_get_irq(_dev, 0));
53493 +       retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
53494 +                            IRQF_SHARED, gadget_wrapper->gadget.name,
53495 +                            otg_dev->pcd);
53496 +       if (retval != 0) {
53497 +               DWC_ERROR("request of irq%d failed\n",
53498 +                          platform_get_irq(_dev, 0));
53499 +               free_wrapper(gadget_wrapper);
53500 +               return -EBUSY;
53501 +       }
53502 +#else
53503 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53504 +                    _dev->irq);
53505 +       retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
53506 +                            IRQF_SHARED | IRQF_DISABLED,
53507 +                            gadget_wrapper->gadget.name, otg_dev->pcd);
53508 +       if (retval != 0) {
53509 +               DWC_ERROR("request of irq%d failed\n", _dev->irq);
53510 +               free_wrapper(gadget_wrapper);
53511 +               return -EBUSY;
53512 +       }
53513 +#endif
53514 +
53515 +       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
53516 +
53517 +       return retval;
53518 +}
53519 +
53520 +/**
53521 + * Cleanup the PCD.
53522 + */
53523 +void pcd_remove(dwc_bus_dev_t *_dev)
53524 +{
53525 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53526 +       dwc_otg_pcd_t *pcd = otg_dev->pcd;
53527 +
53528 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
53529 +
53530 +       /*
53531 +        * Free the IRQ
53532 +        */
53533 +#ifdef PLATFORM_INTERFACE
53534 +       free_irq(platform_get_irq(_dev, 0), pcd);
53535 +#else
53536 +       free_irq(_dev->irq, pcd);
53537 +#endif
53538 +       dwc_otg_pcd_remove(otg_dev->pcd);
53539 +       free_wrapper(gadget_wrapper);
53540 +       otg_dev->pcd = 0;
53541 +}
53542 +
53543 +/**
53544 + * This function registers a gadget driver with the PCD.
53545 + *
53546 + * When a driver is successfully registered, it will receive control
53547 + * requests including set_configuration(), which enables non-control
53548 + * requests.  then usb traffic follows until a disconnect is reported.
53549 + * then a host may connect again, or the driver might get unbound.
53550 + *
53551 + * @param driver The driver being registered
53552 + * @param bind The bind function of gadget driver
53553 + */
53554 +
53555 +int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
53556 +{
53557 +       int retval;
53558 +
53559 +       DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
53560 +                   driver->driver.name);
53561 +
53562 +       if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
53563 +           !driver->bind ||
53564 +           !driver->unbind || !driver->disconnect || !driver->setup) {
53565 +               DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
53566 +               return -EINVAL;
53567 +       }
53568 +       if (gadget_wrapper == 0) {
53569 +               DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
53570 +               return -ENODEV;
53571 +       }
53572 +       if (gadget_wrapper->driver != 0) {
53573 +               DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
53574 +               return -EBUSY;
53575 +       }
53576 +
53577 +       /* hook up the driver */
53578 +       gadget_wrapper->driver = driver;
53579 +       gadget_wrapper->gadget.dev.driver = &driver->driver;
53580 +
53581 +       DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
53582 +       retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);
53583 +       if (retval) {
53584 +               DWC_ERROR("bind to driver %s --> error %d\n",
53585 +                         driver->driver.name, retval);
53586 +               gadget_wrapper->driver = 0;
53587 +               gadget_wrapper->gadget.dev.driver = 0;
53588 +               return retval;
53589 +       }
53590 +       DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
53591 +                   driver->driver.name);
53592 +       return 0;
53593 +}
53594 +EXPORT_SYMBOL(usb_gadget_probe_driver);
53595 +
53596 +/**
53597 + * This function unregisters a gadget driver
53598 + *
53599 + * @param driver The driver being unregistered
53600 + */
53601 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
53602 +{
53603 +       //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
53604 +
53605 +       if (gadget_wrapper == 0) {
53606 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
53607 +                           -ENODEV);
53608 +               return -ENODEV;
53609 +       }
53610 +       if (driver == 0 || driver != gadget_wrapper->driver) {
53611 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
53612 +                           -EINVAL);
53613 +               return -EINVAL;
53614 +       }
53615 +
53616 +       driver->unbind(&gadget_wrapper->gadget);
53617 +       gadget_wrapper->driver = 0;
53618 +
53619 +       DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
53620 +       return 0;
53621 +}
53622 +
53623 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
53624 +
53625 +#endif /* DWC_HOST_ONLY */
53626 --- /dev/null
53627 +++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53628 @@ -0,0 +1,2550 @@
53629 +/* ==========================================================================
53630 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
53631 + * $Revision: #98 $
53632 + * $Date: 2012/08/10 $
53633 + * $Change: 2047372 $
53634 + *
53635 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
53636 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
53637 + * otherwise expressly agreed to in writing between Synopsys and you.
53638 + *
53639 + * The Software IS NOT an item of Licensed Software or Licensed Product under
53640 + * any End User Software License Agreement or Agreement for Licensed Product
53641 + * with Synopsys or any supplement thereto. You are permitted to use and
53642 + * redistribute this Software in source and binary forms, with or without
53643 + * modification, provided that redistributions of source code must retain this
53644 + * notice. You may not view, use, disclose, copy or distribute this file or
53645 + * any information contained herein except pursuant to this license grant from
53646 + * Synopsys. If you do not agree with this notice, including the disclaimer
53647 + * below, then you are not authorized to use the Software.
53648 + *
53649 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
53650 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53651 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53652 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
53653 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53654 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53655 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
53656 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53657 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53658 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53659 + * DAMAGE.
53660 + * ========================================================================== */
53661 +
53662 +#ifndef __DWC_OTG_REGS_H__
53663 +#define __DWC_OTG_REGS_H__
53664 +
53665 +#include "dwc_otg_core_if.h"
53666 +
53667 +/**
53668 + * @file
53669 + *
53670 + * This file contains the data structures for accessing the DWC_otg core registers.
53671 + *
53672 + * The application interfaces with the HS OTG core by reading from and
53673 + * writing to the Control and Status Register (CSR) space through the
53674 + * AHB Slave interface. These registers are 32 bits wide, and the
53675 + * addresses are 32-bit-block aligned.
53676 + * CSRs are classified as follows:
53677 + * - Core Global Registers
53678 + * - Device Mode Registers
53679 + * - Device Global Registers
53680 + * - Device Endpoint Specific Registers
53681 + * - Host Mode Registers
53682 + * - Host Global Registers
53683 + * - Host Port CSRs
53684 + * - Host Channel Specific Registers
53685 + *
53686 + * Only the Core Global registers can be accessed in both Device and
53687 + * Host modes. When the HS OTG core is operating in one mode, either
53688 + * Device or Host, the application must not access registers from the
53689 + * other mode. When the core switches from one mode to another, the
53690 + * registers in the new mode of operation must be reprogrammed as they
53691 + * would be after a power-on reset.
53692 + */
53693 +
53694 +/****************************************************************************/
53695 +/** DWC_otg Core registers .
53696 + * The dwc_otg_core_global_regs structure defines the size
53697 + * and relative field offsets for the Core Global registers.
53698 + */
53699 +typedef struct dwc_otg_core_global_regs {
53700 +       /** OTG Control and Status Register.  <i>Offset: 000h</i> */
53701 +       volatile uint32_t gotgctl;
53702 +       /** OTG Interrupt Register.      <i>Offset: 004h</i> */
53703 +       volatile uint32_t gotgint;
53704 +       /**Core AHB Configuration Register.      <i>Offset: 008h</i> */
53705 +       volatile uint32_t gahbcfg;
53706 +
53707 +#define DWC_GLBINTRMASK                0x0001
53708 +#define DWC_DMAENABLE          0x0020
53709 +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
53710 +#define DWC_NPTXEMPTYLVL_HALFEMPTY     0x0000
53711 +#define DWC_PTXEMPTYLVL_EMPTY  0x0100
53712 +#define DWC_PTXEMPTYLVL_HALFEMPTY      0x0000
53713 +
53714 +       /**Core USB Configuration Register.      <i>Offset: 00Ch</i> */
53715 +       volatile uint32_t gusbcfg;
53716 +       /**Core Reset Register.  <i>Offset: 010h</i> */
53717 +       volatile uint32_t grstctl;
53718 +       /**Core Interrupt Register.      <i>Offset: 014h</i> */
53719 +       volatile uint32_t gintsts;
53720 +       /**Core Interrupt Mask Register.  <i>Offset: 018h</i> */
53721 +       volatile uint32_t gintmsk;
53722 +       /**Receive Status Queue Read Register (Read Only).      <i>Offset: 01Ch</i> */
53723 +       volatile uint32_t grxstsr;
53724 +       /**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/
53725 +       volatile uint32_t grxstsp;
53726 +       /**Receive FIFO Size Register.  <i>Offset: 024h</i> */
53727 +       volatile uint32_t grxfsiz;
53728 +       /**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */
53729 +       volatile uint32_t gnptxfsiz;
53730 +       /**Non Periodic Transmit FIFO/Queue Status Register (Read
53731 +        * Only). <i>Offset: 02Ch</i> */
53732 +       volatile uint32_t gnptxsts;
53733 +       /**I2C Access Register.  <i>Offset: 030h</i> */
53734 +       volatile uint32_t gi2cctl;
53735 +       /**PHY Vendor Control Register.  <i>Offset: 034h</i> */
53736 +       volatile uint32_t gpvndctl;
53737 +       /**General Purpose Input/Output Register.  <i>Offset: 038h</i> */
53738 +       volatile uint32_t ggpio;
53739 +       /**User ID Register.  <i>Offset: 03Ch</i> */
53740 +       volatile uint32_t guid;
53741 +       /**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */
53742 +       volatile uint32_t gsnpsid;
53743 +       /**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */
53744 +       volatile uint32_t ghwcfg1;
53745 +       /**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */
53746 +       volatile uint32_t ghwcfg2;
53747 +#define DWC_SLAVE_ONLY_ARCH 0
53748 +#define DWC_EXT_DMA_ARCH 1
53749 +#define DWC_INT_DMA_ARCH 2
53750 +
53751 +#define DWC_MODE_HNP_SRP_CAPABLE       0
53752 +#define DWC_MODE_SRP_ONLY_CAPABLE      1
53753 +#define DWC_MODE_NO_HNP_SRP_CAPABLE            2
53754 +#define DWC_MODE_SRP_CAPABLE_DEVICE            3
53755 +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
53756 +#define DWC_MODE_SRP_CAPABLE_HOST      5
53757 +#define DWC_MODE_NO_SRP_CAPABLE_HOST   6
53758 +
53759 +       /**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */
53760 +       volatile uint32_t ghwcfg3;
53761 +       /**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/
53762 +       volatile uint32_t ghwcfg4;
53763 +       /** Core LPM Configuration register <i>Offset: 054h</i>*/
53764 +       volatile uint32_t glpmcfg;
53765 +       /** Global PowerDn Register <i>Offset: 058h</i> */
53766 +       volatile uint32_t gpwrdn;
53767 +       /** Global DFIFO SW Config Register  <i>Offset: 05Ch</i> */
53768 +       volatile uint32_t gdfifocfg;
53769 +       /** ADP Control Register  <i>Offset: 060h</i> */
53770 +       volatile uint32_t adpctl;
53771 +       /** Reserved  <i>Offset: 064h-0FFh</i> */
53772 +       volatile uint32_t reserved39[39];
53773 +       /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
53774 +       volatile uint32_t hptxfsiz;
53775 +       /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
53776 +               otherwise Device Transmit FIFO#n Register.
53777 +        * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
53778 +       volatile uint32_t dtxfsiz[15];
53779 +} dwc_otg_core_global_regs_t;
53780 +
53781 +/**
53782 + * This union represents the bit fields of the Core OTG Control
53783 + * and Status Register (GOTGCTL).  Set the bits using the bit
53784 + * fields then write the <i>d32</i> value to the register.
53785 + */
53786 +typedef union gotgctl_data {
53787 +       /** raw register data */
53788 +       uint32_t d32;
53789 +       /** register bits */
53790 +       struct {
53791 +               unsigned sesreqscs:1;
53792 +               unsigned sesreq:1;
53793 +               unsigned vbvalidoven:1;
53794 +               unsigned vbvalidovval:1;
53795 +               unsigned avalidoven:1;
53796 +               unsigned avalidovval:1;
53797 +               unsigned bvalidoven:1;
53798 +               unsigned bvalidovval:1;
53799 +               unsigned hstnegscs:1;
53800 +               unsigned hnpreq:1;
53801 +               unsigned hstsethnpen:1;
53802 +               unsigned devhnpen:1;
53803 +               unsigned reserved12_15:4;
53804 +               unsigned conidsts:1;
53805 +               unsigned dbnctime:1;
53806 +               unsigned asesvld:1;
53807 +               unsigned bsesvld:1;
53808 +               unsigned otgver:1;
53809 +               unsigned reserved1:1;
53810 +               unsigned multvalidbc:5;
53811 +               unsigned chirpen:1;
53812 +               unsigned reserved28_31:4;
53813 +       } b;
53814 +} gotgctl_data_t;
53815 +
53816 +/**
53817 + * This union represents the bit fields of the Core OTG Interrupt Register
53818 + * (GOTGINT).  Set/clear the bits using the bit fields then write the <i>d32</i>
53819 + * value to the register.
53820 + */
53821 +typedef union gotgint_data {
53822 +       /** raw register data */
53823 +       uint32_t d32;
53824 +       /** register bits */
53825 +       struct {
53826 +               /** Current Mode */
53827 +               unsigned reserved0_1:2;
53828 +
53829 +               /** Session End Detected */
53830 +               unsigned sesenddet:1;
53831 +
53832 +               unsigned reserved3_7:5;
53833 +
53834 +               /** Session Request Success Status Change */
53835 +               unsigned sesreqsucstschng:1;
53836 +               /** Host Negotiation Success Status Change */
53837 +               unsigned hstnegsucstschng:1;
53838 +
53839 +               unsigned reserved10_16:7;
53840 +
53841 +               /** Host Negotiation Detected */
53842 +               unsigned hstnegdet:1;
53843 +               /** A-Device Timeout Change */
53844 +               unsigned adevtoutchng:1;
53845 +               /** Debounce Done */
53846 +               unsigned debdone:1;
53847 +               /** Multi-Valued input changed */
53848 +               unsigned mvic:1;
53849 +
53850 +               unsigned reserved31_21:11;
53851 +
53852 +       } b;
53853 +} gotgint_data_t;
53854 +
53855 +/**
53856 + * This union represents the bit fields of the Core AHB Configuration
53857 + * Register (GAHBCFG). Set/clear the bits using the bit fields then
53858 + * write the <i>d32</i> value to the register.
53859 + */
53860 +typedef union gahbcfg_data {
53861 +       /** raw register data */
53862 +       uint32_t d32;
53863 +       /** register bits */
53864 +       struct {
53865 +               unsigned glblintrmsk:1;
53866 +#define DWC_GAHBCFG_GLBINT_ENABLE              1
53867 +
53868 +               unsigned hburstlen:4;
53869 +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE       0
53870 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR         1
53871 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4                3
53872 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8                5
53873 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16       7
53874 +
53875 +               unsigned dmaenable:1;
53876 +#define DWC_GAHBCFG_DMAENABLE                  1
53877 +               unsigned reserved:1;
53878 +               unsigned nptxfemplvl_txfemplvl:1;
53879 +               unsigned ptxfemplvl:1;
53880 +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY          1
53881 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY      0
53882 +               unsigned reserved9_20:12;
53883 +               unsigned remmemsupp:1;
53884 +               unsigned notialldmawrit:1;
53885 +               unsigned ahbsingle:1;
53886 +               unsigned reserved24_31:8;
53887 +       } b;
53888 +} gahbcfg_data_t;
53889 +
53890 +/**
53891 + * This union represents the bit fields of the Core USB Configuration
53892 + * Register (GUSBCFG). Set the bits using the bit fields then write
53893 + * the <i>d32</i> value to the register.
53894 + */
53895 +typedef union gusbcfg_data {
53896 +       /** raw register data */
53897 +       uint32_t d32;
53898 +       /** register bits */
53899 +       struct {
53900 +               unsigned toutcal:3;
53901 +               unsigned phyif:1;
53902 +               unsigned ulpi_utmi_sel:1;
53903 +               unsigned fsintf:1;
53904 +               unsigned physel:1;
53905 +               unsigned ddrsel:1;
53906 +               unsigned srpcap:1;
53907 +               unsigned hnpcap:1;
53908 +               unsigned usbtrdtim:4;
53909 +               unsigned reserved1:1;
53910 +               unsigned phylpwrclksel:1;
53911 +               unsigned otgutmifssel:1;
53912 +               unsigned ulpi_fsls:1;
53913 +               unsigned ulpi_auto_res:1;
53914 +               unsigned ulpi_clk_sus_m:1;
53915 +               unsigned ulpi_ext_vbus_drv:1;
53916 +               unsigned ulpi_int_vbus_indicator:1;
53917 +               unsigned term_sel_dl_pulse:1;
53918 +               unsigned indicator_complement:1;
53919 +               unsigned indicator_pass_through:1;
53920 +               unsigned ulpi_int_prot_dis:1;
53921 +               unsigned ic_usb_cap:1;
53922 +               unsigned ic_traffic_pull_remove:1;
53923 +               unsigned tx_end_delay:1;
53924 +               unsigned force_host_mode:1;
53925 +               unsigned force_dev_mode:1;
53926 +               unsigned reserved31:1;
53927 +       } b;
53928 +} gusbcfg_data_t;
53929 +
53930 +/**
53931 + * This union represents the bit fields of the Core Reset Register
53932 + * (GRSTCTL).  Set/clear the bits using the bit fields then write the
53933 + * <i>d32</i> value to the register.
53934 + */
53935 +typedef union grstctl_data {
53936 +       /** raw register data */
53937 +       uint32_t d32;
53938 +       /** register bits */
53939 +       struct {
53940 +               /** Core Soft Reset (CSftRst) (Device and Host)
53941 +                *
53942 +                * The application can flush the control logic in the
53943 +                * entire core using this bit. This bit resets the
53944 +                * pipelines in the AHB Clock domain as well as the
53945 +                * PHY Clock domain.
53946 +                *
53947 +                * The state machines are reset to an IDLE state, the
53948 +                * control bits in the CSRs are cleared, all the
53949 +                * transmit FIFOs and the receive FIFO are flushed.
53950 +                *
53951 +                * The status mask bits that control the generation of
53952 +                * the interrupt, are cleared, to clear the
53953 +                * interrupt. The interrupt status bits are not
53954 +                * cleared, so the application can get the status of
53955 +                * any events that occurred in the core after it has
53956 +                * set this bit.
53957 +                *
53958 +                * Any transactions on the AHB are terminated as soon
53959 +                * as possible following the protocol. Any
53960 +                * transactions on the USB are terminated immediately.
53961 +                *
53962 +                * The configuration settings in the CSRs are
53963 +                * unchanged, so the software doesn't have to
53964 +                * reprogram these registers (Device
53965 +                * Configuration/Host Configuration/Core System
53966 +                * Configuration/Core PHY Configuration).
53967 +                *
53968 +                * The application can write to this bit, any time it
53969 +                * wants to reset the core. This is a self clearing
53970 +                * bit and the core clears this bit after all the
53971 +                * necessary logic is reset in the core, which may
53972 +                * take several clocks, depending on the current state
53973 +                * of the core.
53974 +                */
53975 +               unsigned csftrst:1;
53976 +               /** Hclk Soft Reset
53977 +                *
53978 +                * The application uses this bit to reset the control logic in
53979 +                * the AHB clock domain. Only AHB clock domain pipelines are
53980 +                * reset.
53981 +                */
53982 +               unsigned hsftrst:1;
53983 +               /** Host Frame Counter Reset (Host Only)<br>
53984 +                *
53985 +                * The application can reset the (micro)frame number
53986 +                * counter inside the core, using this bit. When the
53987 +                * (micro)frame counter is reset, the subsequent SOF
53988 +                * sent out by the core, will have a (micro)frame
53989 +                * number of 0.
53990 +                */
53991 +               unsigned hstfrm:1;
53992 +               /** In Token Sequence Learning Queue Flush
53993 +                * (INTknQFlsh) (Device Only)
53994 +                */
53995 +               unsigned intknqflsh:1;
53996 +               /** RxFIFO Flush (RxFFlsh) (Device and Host)
53997 +                *
53998 +                * The application can flush the entire Receive FIFO
53999 +                * using this bit. The application must first
54000 +                * ensure that the core is not in the middle of a
54001 +                * transaction. The application should write into
54002 +                * this bit, only after making sure that neither the
54003 +                * DMA engine is reading from the RxFIFO nor the MAC
54004 +                * is writing the data in to the FIFO. The
54005 +                * application should wait until the bit is cleared
54006 +                * before performing any other operations. This bit
54007 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54008 +                * to clear.
54009 +                */
54010 +               unsigned rxfflsh:1;
54011 +               /** TxFIFO Flush (TxFFlsh) (Device and Host).
54012 +                *
54013 +                * This bit is used to selectively flush a single or
54014 +                * all transmit FIFOs. The application must first
54015 +                * ensure that the core is not in the middle of a
54016 +                * transaction. The application should write into
54017 +                * this bit, only after making sure that neither the
54018 +                * DMA engine is writing into the TxFIFO nor the MAC
54019 +                * is reading the data out of the FIFO. The
54020 +                * application should wait until the core clears this
54021 +                * bit, before performing any operations. This bit
54022 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54023 +                * to clear.
54024 +                */
54025 +               unsigned txfflsh:1;
54026 +
54027 +               /** TxFIFO Number (TxFNum) (Device and Host).
54028 +                *
54029 +                * This is the FIFO number which needs to be flushed,
54030 +                * using the TxFIFO Flush bit. This field should not
54031 +                * be changed until the TxFIFO Flush bit is cleared by
54032 +                * the core.
54033 +                *       - 0x0 : Non Periodic TxFIFO Flush
54034 +                *       - 0x1 : Periodic TxFIFO #1 Flush in device mode
54035 +                *         or Periodic TxFIFO in host mode
54036 +                *       - 0x2 : Periodic TxFIFO #2 Flush in device mode.
54037 +                *       - ...
54038 +                *       - 0xF : Periodic TxFIFO #15 Flush in device mode
54039 +                *       - 0x10: Flush all the Transmit NonPeriodic and
54040 +                *         Transmit Periodic FIFOs in the core
54041 +                */
54042 +               unsigned txfnum:5;
54043 +               /** Reserved */
54044 +               unsigned reserved11_29:19;
54045 +               /** DMA Request Signal.  Indicated DMA request is in
54046 +                * probress. Used for debug purpose. */
54047 +               unsigned dmareq:1;
54048 +               /** AHB Master Idle.  Indicates the AHB Master State
54049 +                * Machine is in IDLE condition. */
54050 +               unsigned ahbidle:1;
54051 +       } b;
54052 +} grstctl_t;
54053 +
54054 +/**
54055 + * This union represents the bit fields of the Core Interrupt Mask
54056 + * Register (GINTMSK). Set/clear the bits using the bit fields then
54057 + * write the <i>d32</i> value to the register.
54058 + */
54059 +typedef union gintmsk_data {
54060 +       /** raw register data */
54061 +       uint32_t d32;
54062 +       /** register bits */
54063 +       struct {
54064 +               unsigned reserved0:1;
54065 +               unsigned modemismatch:1;
54066 +               unsigned otgintr:1;
54067 +               unsigned sofintr:1;
54068 +               unsigned rxstsqlvl:1;
54069 +               unsigned nptxfempty:1;
54070 +               unsigned ginnakeff:1;
54071 +               unsigned goutnakeff:1;
54072 +               unsigned ulpickint:1;
54073 +               unsigned i2cintr:1;
54074 +               unsigned erlysuspend:1;
54075 +               unsigned usbsuspend:1;
54076 +               unsigned usbreset:1;
54077 +               unsigned enumdone:1;
54078 +               unsigned isooutdrop:1;
54079 +               unsigned eopframe:1;
54080 +               unsigned restoredone:1;
54081 +               unsigned epmismatch:1;
54082 +               unsigned inepintr:1;
54083 +               unsigned outepintr:1;
54084 +               unsigned incomplisoin:1;
54085 +               unsigned incomplisoout:1;
54086 +               unsigned fetsusp:1;
54087 +               unsigned resetdet:1;
54088 +               unsigned portintr:1;
54089 +               unsigned hcintr:1;
54090 +               unsigned ptxfempty:1;
54091 +               unsigned lpmtranrcvd:1;
54092 +               unsigned conidstschng:1;
54093 +               unsigned disconnect:1;
54094 +               unsigned sessreqintr:1;
54095 +               unsigned wkupintr:1;
54096 +       } b;
54097 +} gintmsk_data_t;
54098 +/**
54099 + * This union represents the bit fields of the Core Interrupt Register
54100 + * (GINTSTS).  Set/clear the bits using the bit fields then write the
54101 + * <i>d32</i> value to the register.
54102 + */
54103 +typedef union gintsts_data {
54104 +       /** raw register data */
54105 +       uint32_t d32;
54106 +#define DWC_SOF_INTR_MASK 0x0008
54107 +       /** register bits */
54108 +       struct {
54109 +#define DWC_HOST_MODE 1
54110 +               unsigned curmode:1;
54111 +               unsigned modemismatch:1;
54112 +               unsigned otgintr:1;
54113 +               unsigned sofintr:1;
54114 +               unsigned rxstsqlvl:1;
54115 +               unsigned nptxfempty:1;
54116 +               unsigned ginnakeff:1;
54117 +               unsigned goutnakeff:1;
54118 +               unsigned ulpickint:1;
54119 +               unsigned i2cintr:1;
54120 +               unsigned erlysuspend:1;
54121 +               unsigned usbsuspend:1;
54122 +               unsigned usbreset:1;
54123 +               unsigned enumdone:1;
54124 +               unsigned isooutdrop:1;
54125 +               unsigned eopframe:1;
54126 +               unsigned restoredone:1;
54127 +               unsigned epmismatch:1;
54128 +               unsigned inepint:1;
54129 +               unsigned outepintr:1;
54130 +               unsigned incomplisoin:1;
54131 +               unsigned incomplisoout:1;
54132 +               unsigned fetsusp:1;
54133 +               unsigned resetdet:1;
54134 +               unsigned portintr:1;
54135 +               unsigned hcintr:1;
54136 +               unsigned ptxfempty:1;
54137 +               unsigned lpmtranrcvd:1;
54138 +               unsigned conidstschng:1;
54139 +               unsigned disconnect:1;
54140 +               unsigned sessreqintr:1;
54141 +               unsigned wkupintr:1;
54142 +       } b;
54143 +} gintsts_data_t;
54144 +
54145 +/**
54146 + * This union represents the bit fields in the Device Receive Status Read and
54147 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54148 + * element then read out the bits using the <i>b</i>it elements.
54149 + */
54150 +typedef union device_grxsts_data {
54151 +       /** raw register data */
54152 +       uint32_t d32;
54153 +       /** register bits */
54154 +       struct {
54155 +               unsigned epnum:4;
54156 +               unsigned bcnt:11;
54157 +               unsigned dpid:2;
54158 +
54159 +#define DWC_STS_DATA_UPDT              0x2     // OUT Data Packet
54160 +#define DWC_STS_XFER_COMP              0x3     // OUT Data Transfer Complete
54161 +
54162 +#define DWC_DSTS_GOUT_NAK              0x1     // Global OUT NAK
54163 +#define DWC_DSTS_SETUP_COMP            0x4     // Setup Phase Complete
54164 +#define DWC_DSTS_SETUP_UPDT 0x6        // SETUP Packet
54165 +               unsigned pktsts:4;
54166 +               unsigned fn:4;
54167 +               unsigned reserved25_31:7;
54168 +       } b;
54169 +} device_grxsts_data_t;
54170 +
54171 +/**
54172 + * This union represents the bit fields in the Host Receive Status Read and
54173 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54174 + * element then read out the bits using the <i>b</i>it elements.
54175 + */
54176 +typedef union host_grxsts_data {
54177 +       /** raw register data */
54178 +       uint32_t d32;
54179 +       /** register bits */
54180 +       struct {
54181 +               unsigned chnum:4;
54182 +               unsigned bcnt:11;
54183 +               unsigned dpid:2;
54184 +
54185 +               unsigned pktsts:4;
54186 +#define DWC_GRXSTS_PKTSTS_IN                     0x2
54187 +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP   0x3
54188 +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
54189 +#define DWC_GRXSTS_PKTSTS_CH_HALTED              0x7
54190 +
54191 +               unsigned reserved21_31:11;
54192 +       } b;
54193 +} host_grxsts_data_t;
54194 +
54195 +/**
54196 + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
54197 + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element
54198 + * then read out the bits using the <i>b</i>it elements.
54199 + */
54200 +typedef union fifosize_data {
54201 +       /** raw register data */
54202 +       uint32_t d32;
54203 +       /** register bits */
54204 +       struct {
54205 +               unsigned startaddr:16;
54206 +               unsigned depth:16;
54207 +       } b;
54208 +} fifosize_data_t;
54209 +
54210 +/**
54211 + * This union represents the bit fields in the Non-Periodic Transmit
54212 + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
54213 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54214 + * elements.
54215 + */
54216 +typedef union gnptxsts_data {
54217 +       /** raw register data */
54218 +       uint32_t d32;
54219 +       /** register bits */
54220 +       struct {
54221 +               unsigned nptxfspcavail:16;
54222 +               unsigned nptxqspcavail:8;
54223 +               /** Top of the Non-Periodic Transmit Request Queue
54224 +                *      - bit 24 - Terminate (Last entry for the selected
54225 +                *        channel/EP)
54226 +                *      - bits 26:25 - Token Type
54227 +                *        - 2'b00 - IN/OUT
54228 +                *        - 2'b01 - Zero Length OUT
54229 +                *        - 2'b10 - PING/Complete Split
54230 +                *        - 2'b11 - Channel Halt
54231 +                *      - bits 30:27 - Channel/EP Number
54232 +                */
54233 +               unsigned nptxqtop_terminate:1;
54234 +               unsigned nptxqtop_token:2;
54235 +               unsigned nptxqtop_chnep:4;
54236 +               unsigned reserved:1;
54237 +       } b;
54238 +} gnptxsts_data_t;
54239 +
54240 +/**
54241 + * This union represents the bit fields in the Transmit
54242 + * FIFO Status Register (DTXFSTS). Read the register into the
54243 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54244 + * elements.
54245 + */
54246 +typedef union dtxfsts_data {
54247 +       /** raw register data */
54248 +       uint32_t d32;
54249 +       /** register bits */
54250 +       struct {
54251 +               unsigned txfspcavail:16;
54252 +               unsigned reserved:16;
54253 +       } b;
54254 +} dtxfsts_data_t;
54255 +
54256 +/**
54257 + * This union represents the bit fields in the I2C Control Register
54258 + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
54259 + * bits using the <i>b</i>it elements.
54260 + */
54261 +typedef union gi2cctl_data {
54262 +       /** raw register data */
54263 +       uint32_t d32;
54264 +       /** register bits */
54265 +       struct {
54266 +               unsigned rwdata:8;
54267 +               unsigned regaddr:8;
54268 +               unsigned addr:7;
54269 +               unsigned i2cen:1;
54270 +               unsigned ack:1;
54271 +               unsigned i2csuspctl:1;
54272 +               unsigned i2cdevaddr:2;
54273 +               unsigned i2cdatse0:1;
54274 +               unsigned reserved:1;
54275 +               unsigned rw:1;
54276 +               unsigned bsydne:1;
54277 +       } b;
54278 +} gi2cctl_data_t;
54279 +
54280 +/**
54281 + * This union represents the bit fields in the PHY Vendor Control Register
54282 + * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the
54283 + * bits using the <i>b</i>it elements.
54284 + */
54285 +typedef union gpvndctl_data {
54286 +       /** raw register data */
54287 +       uint32_t d32;
54288 +       /** register bits */
54289 +       struct {
54290 +               unsigned regdata:8;
54291 +               unsigned vctrl:8;
54292 +               unsigned regaddr16_21:6;
54293 +               unsigned regwr:1;
54294 +               unsigned reserved23_24:2;
54295 +               unsigned newregreq:1;
54296 +               unsigned vstsbsy:1;
54297 +               unsigned vstsdone:1;
54298 +               unsigned reserved28_30:3;
54299 +               unsigned disulpidrvr:1;
54300 +       } b;
54301 +} gpvndctl_data_t;
54302 +
54303 +/**
54304 + * This union represents the bit fields in the General Purpose
54305 + * Input/Output Register (GGPIO).
54306 + * Read the register into the <i>d32</i> element then read out the
54307 + * bits using the <i>b</i>it elements.
54308 + */
54309 +typedef union ggpio_data {
54310 +       /** raw register data */
54311 +       uint32_t d32;
54312 +       /** register bits */
54313 +       struct {
54314 +               unsigned gpi:16;
54315 +               unsigned gpo:16;
54316 +       } b;
54317 +} ggpio_data_t;
54318 +
54319 +/**
54320 + * This union represents the bit fields in the User ID Register
54321 + * (GUID). Read the register into the <i>d32</i> element then read out the
54322 + * bits using the <i>b</i>it elements.
54323 + */
54324 +typedef union guid_data {
54325 +       /** raw register data */
54326 +       uint32_t d32;
54327 +       /** register bits */
54328 +       struct {
54329 +               unsigned rwdata:32;
54330 +       } b;
54331 +} guid_data_t;
54332 +
54333 +/**
54334 + * This union represents the bit fields in the Synopsys ID Register
54335 + * (GSNPSID). Read the register into the <i>d32</i> element then read out the
54336 + * bits using the <i>b</i>it elements.
54337 + */
54338 +typedef union gsnpsid_data {
54339 +       /** raw register data */
54340 +       uint32_t d32;
54341 +       /** register bits */
54342 +       struct {
54343 +               unsigned rwdata:32;
54344 +       } b;
54345 +} gsnpsid_data_t;
54346 +
54347 +/**
54348 + * This union represents the bit fields in the User HW Config1
54349 + * Register.  Read the register into the <i>d32</i> element then read
54350 + * out the bits using the <i>b</i>it elements.
54351 + */
54352 +typedef union hwcfg1_data {
54353 +       /** raw register data */
54354 +       uint32_t d32;
54355 +       /** register bits */
54356 +       struct {
54357 +               unsigned ep_dir0:2;
54358 +               unsigned ep_dir1:2;
54359 +               unsigned ep_dir2:2;
54360 +               unsigned ep_dir3:2;
54361 +               unsigned ep_dir4:2;
54362 +               unsigned ep_dir5:2;
54363 +               unsigned ep_dir6:2;
54364 +               unsigned ep_dir7:2;
54365 +               unsigned ep_dir8:2;
54366 +               unsigned ep_dir9:2;
54367 +               unsigned ep_dir10:2;
54368 +               unsigned ep_dir11:2;
54369 +               unsigned ep_dir12:2;
54370 +               unsigned ep_dir13:2;
54371 +               unsigned ep_dir14:2;
54372 +               unsigned ep_dir15:2;
54373 +       } b;
54374 +} hwcfg1_data_t;
54375 +
54376 +/**
54377 + * This union represents the bit fields in the User HW Config2
54378 + * Register.  Read the register into the <i>d32</i> element then read
54379 + * out the bits using the <i>b</i>it elements.
54380 + */
54381 +typedef union hwcfg2_data {
54382 +       /** raw register data */
54383 +       uint32_t d32;
54384 +       /** register bits */
54385 +       struct {
54386 +               /* GHWCFG2 */
54387 +               unsigned op_mode:3;
54388 +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
54389 +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
54390 +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
54391 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
54392 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
54393 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
54394 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
54395 +
54396 +               unsigned architecture:2;
54397 +               unsigned point2point:1;
54398 +               unsigned hs_phy_type:2;
54399 +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
54400 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
54401 +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
54402 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
54403 +
54404 +               unsigned fs_phy_type:2;
54405 +               unsigned num_dev_ep:4;
54406 +               unsigned num_host_chan:4;
54407 +               unsigned perio_ep_supported:1;
54408 +               unsigned dynamic_fifo:1;
54409 +               unsigned multi_proc_int:1;
54410 +               unsigned reserved21:1;
54411 +               unsigned nonperio_tx_q_depth:2;
54412 +               unsigned host_perio_tx_q_depth:2;
54413 +               unsigned dev_token_q_depth:5;
54414 +               unsigned otg_enable_ic_usb:1;
54415 +       } b;
54416 +} hwcfg2_data_t;
54417 +
54418 +/**
54419 + * This union represents the bit fields in the User HW Config3
54420 + * Register.  Read the register into the <i>d32</i> element then read
54421 + * out the bits using the <i>b</i>it elements.
54422 + */
54423 +typedef union hwcfg3_data {
54424 +       /** raw register data */
54425 +       uint32_t d32;
54426 +       /** register bits */
54427 +       struct {
54428 +               /* GHWCFG3 */
54429 +               unsigned xfer_size_cntr_width:4;
54430 +               unsigned packet_size_cntr_width:3;
54431 +               unsigned otg_func:1;
54432 +               unsigned i2c:1;
54433 +               unsigned vendor_ctrl_if:1;
54434 +               unsigned optional_features:1;
54435 +               unsigned synch_reset_type:1;
54436 +               unsigned adp_supp:1;
54437 +               unsigned otg_enable_hsic:1;
54438 +               unsigned bc_support:1;
54439 +               unsigned otg_lpm_en:1;
54440 +               unsigned dfifo_depth:16;
54441 +       } b;
54442 +} hwcfg3_data_t;
54443 +
54444 +/**
54445 + * This union represents the bit fields in the User HW Config4
54446 + * Register.  Read the register into the <i>d32</i> element then read
54447 + * out the bits using the <i>b</i>it elements.
54448 + */
54449 +typedef union hwcfg4_data {
54450 +       /** raw register data */
54451 +       uint32_t d32;
54452 +       /** register bits */
54453 +       struct {
54454 +               unsigned num_dev_perio_in_ep:4;
54455 +               unsigned power_optimiz:1;
54456 +               unsigned min_ahb_freq:1;
54457 +               unsigned hiber:1;
54458 +               unsigned xhiber:1;
54459 +               unsigned reserved:6;
54460 +               unsigned utmi_phy_data_width:2;
54461 +               unsigned num_dev_mode_ctrl_ep:4;
54462 +               unsigned iddig_filt_en:1;
54463 +               unsigned vbus_valid_filt_en:1;
54464 +               unsigned a_valid_filt_en:1;
54465 +               unsigned b_valid_filt_en:1;
54466 +               unsigned session_end_filt_en:1;
54467 +               unsigned ded_fifo_en:1;
54468 +               unsigned num_in_eps:4;
54469 +               unsigned desc_dma:1;
54470 +               unsigned desc_dma_dyn:1;
54471 +       } b;
54472 +} hwcfg4_data_t;
54473 +
54474 +/**
54475 + * This union represents the bit fields of the Core LPM Configuration
54476 + * Register (GLPMCFG). Set the bits using bit fields then write
54477 + * the <i>d32</i> value to the register.
54478 + */
54479 +typedef union glpmctl_data {
54480 +       /** raw register data */
54481 +       uint32_t d32;
54482 +       /** register bits */
54483 +       struct {
54484 +               /** LPM-Capable (LPMCap) (Device and Host)
54485 +                * The application uses this bit to control
54486 +                * the DWC_otg core LPM capabilities.
54487 +                */
54488 +               unsigned lpm_cap_en:1;
54489 +               /** LPM response programmed by application (AppL1Res) (Device)
54490 +                * Handshake response to LPM token pre-programmed
54491 +                * by device application software.
54492 +                */
54493 +               unsigned appl_resp:1;
54494 +               /** Host Initiated Resume Duration (HIRD) (Device and Host)
54495 +                * In Host mode this field indicates the value of HIRD
54496 +                * to be sent in an LPM transaction.
54497 +                * In Device mode this field is updated with the
54498 +                * Received LPM Token HIRD bmAttribute
54499 +                * when an ACK/NYET/STALL response is sent
54500 +                * to an LPM transaction.
54501 +                */
54502 +               unsigned hird:4;
54503 +               /** RemoteWakeEnable (bRemoteWake) (Device and Host)
54504 +                * In Host mode this bit indicates the value of remote
54505 +                * wake up to be sent in wIndex field of LPM transaction.
54506 +                * In Device mode this field is updated with the
54507 +                * Received LPM Token bRemoteWake bmAttribute
54508 +                * when an ACK/NYET/STALL response is sent
54509 +                * to an LPM transaction.
54510 +                */
54511 +               unsigned rem_wkup_en:1;
54512 +               /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
54513 +                * The application uses this bit to control
54514 +                * the utmi_sleep_n assertion to the PHY when in L1 state.
54515 +                */
54516 +               unsigned en_utmi_sleep:1;
54517 +               /** HIRD Threshold (HIRD_Thres) (Device and Host)
54518 +                */
54519 +               unsigned hird_thres:5;
54520 +               /** LPM Response (CoreL1Res) (Device and Host)
54521 +                * In Host mode this bit contains handsake response to
54522 +                * LPM transaction.
54523 +                * In Device mode the response of the core to
54524 +                * LPM transaction received is reflected in these two bits.
54525 +                       - 0x0 : ERROR (No handshake response)
54526 +                       - 0x1 : STALL
54527 +                       - 0x2 : NYET
54528 +                       - 0x3 : ACK
54529 +                */
54530 +               unsigned lpm_resp:2;
54531 +               /** Port Sleep Status (SlpSts) (Device and Host)
54532 +                * This bit is set as long as a Sleep condition
54533 +                * is present on the USB bus.
54534 +                */
54535 +               unsigned prt_sleep_sts:1;
54536 +               /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
54537 +                * Indicates that the application or host
54538 +                * can start resume from Sleep state.
54539 +                */
54540 +               unsigned sleep_state_resumeok:1;
54541 +               /** LPM channel Index (LPM_Chnl_Indx) (Host)
54542 +                * The channel number on which the LPM transaction
54543 +                * has to be applied while sending
54544 +                * an LPM transaction to the local device.
54545 +                */
54546 +               unsigned lpm_chan_index:4;
54547 +               /** LPM Retry Count (LPM_Retry_Cnt) (Host)
54548 +                * Number host retries that would be performed
54549 +                * if the device response was not valid response.
54550 +                */
54551 +               unsigned retry_count:3;
54552 +               /** Send LPM Transaction (SndLPM) (Host)
54553 +                * When set by application software,
54554 +                * an LPM transaction containing two tokens
54555 +                * is sent.
54556 +                */
54557 +               unsigned send_lpm:1;
54558 +               /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
54559 +                * Number of LPM Host Retries still remaining
54560 +                * to be transmitted for the current LPM sequence
54561 +                */
54562 +               unsigned retry_count_sts:3;
54563 +               unsigned reserved28_29:2;
54564 +               /** In host mode once this bit is set, the host
54565 +                * configures to drive the HSIC Idle state on the bus.
54566 +                * It then waits for the  device to initiate the Connect sequence.
54567 +                * In device mode once this bit is set, the device waits for
54568 +                * the HSIC Idle line state on the bus. Upon receving the Idle
54569 +                * line state, it initiates the HSIC Connect sequence.
54570 +                */
54571 +               unsigned hsic_connect:1;
54572 +               /** This bit overrides and functionally inverts
54573 +                * the if_select_hsic input port signal.
54574 +                */
54575 +               unsigned inv_sel_hsic:1;
54576 +       } b;
54577 +} glpmcfg_data_t;
54578 +
54579 +/**
54580 + * This union represents the bit fields of the Core ADP Timer, Control and
54581 + * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write
54582 + * the <i>d32</i> value to the register.
54583 + */
54584 +typedef union adpctl_data {
54585 +       /** raw register data */
54586 +       uint32_t d32;
54587 +       /** register bits */
54588 +       struct {
54589 +               /** Probe Discharge (PRB_DSCHG)
54590 +                *  These bits set the times for TADP_DSCHG.
54591 +                *  These bits are defined as follows:
54592 +                *  2'b00 - 4 msec
54593 +                *  2'b01 - 8 msec
54594 +                *  2'b10 - 16 msec
54595 +                *  2'b11 - 32 msec
54596 +                */
54597 +               unsigned prb_dschg:2;
54598 +               /** Probe Delta (PRB_DELTA)
54599 +                *  These bits set the resolution for RTIM   value.
54600 +                *  The bits are defined in units of 32 kHz clock cycles as follows:
54601 +                *  2'b00  -  1 cycles
54602 +                *  2'b01  -  2 cycles
54603 +                *  2'b10 -  3 cycles
54604 +                *  2'b11 - 4 cycles
54605 +                *  For example if this value is chosen to 2'b01, it means that RTIM
54606 +                *  increments for every 3(three) 32Khz clock cycles.
54607 +                */
54608 +               unsigned prb_delta:2;
54609 +               /** Probe Period (PRB_PER)
54610 +                *  These bits sets the TADP_PRD as shown in Figure 4 as follows:
54611 +                *  2'b00  -  0.625 to 0.925 sec (typical 0.775 sec)
54612 +                *  2'b01  -  1.25 to 1.85 sec (typical 1.55 sec)
54613 +                *  2'b10  -  1.9 to 2.6 sec (typical 2.275 sec)
54614 +                *  2'b11  -  Reserved
54615 +                */
54616 +               unsigned prb_per:2;
54617 +               /** These bits capture the latest time it took for VBUS to ramp from
54618 +                *  VADP_SINK to VADP_PRB.
54619 +                *  0x000  -  1 cycles
54620 +                *  0x001  -  2 cycles
54621 +                *  0x002  -  3 cycles
54622 +                *  etc
54623 +                *  0x7FF  -  2048 cycles
54624 +                *  A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.
54625 +               */
54626 +               unsigned rtim:11;
54627 +               /** Enable Probe (EnaPrb)
54628 +                *  When programmed to 1'b1, the core performs a probe operation.
54629 +                *  This bit is valid only if OTG_Ver = 1'b1.
54630 +                */
54631 +               unsigned enaprb:1;
54632 +               /** Enable Sense (EnaSns)
54633 +                *  When programmed to 1'b1, the core performs a Sense operation.
54634 +                *  This bit is valid only if OTG_Ver = 1'b1.
54635 +                */
54636 +               unsigned enasns:1;
54637 +               /** ADP Reset (ADPRes)
54638 +                *  When set, ADP controller is reset.
54639 +                *  This bit is valid only if OTG_Ver = 1'b1.
54640 +                */
54641 +               unsigned adpres:1;
54642 +               /** ADP Enable (ADPEn)
54643 +                *  When set, the core performs either ADP probing or sensing
54644 +                *  based on EnaPrb or EnaSns.
54645 +                *  This bit is valid only if OTG_Ver = 1'b1.
54646 +                */
54647 +               unsigned adpen:1;
54648 +               /** ADP Probe Interrupt (ADP_PRB_INT)
54649 +                *  When this bit is set, it means that the VBUS
54650 +                *  voltage is greater than VADP_PRB or VADP_PRB is reached.
54651 +                *  This bit is valid only if OTG_Ver = 1'b1.
54652 +                */
54653 +               unsigned adp_prb_int:1;
54654 +               /**
54655 +                *  ADP Sense Interrupt (ADP_SNS_INT)
54656 +                *  When this bit is set, it means that the VBUS voltage is greater than
54657 +                *  VADP_SNS value or VADP_SNS is reached.
54658 +                *  This bit is valid only if OTG_Ver = 1'b1.
54659 +                */
54660 +               unsigned adp_sns_int:1;
54661 +               /** ADP Tomeout Interrupt (ADP_TMOUT_INT)
54662 +                *  This bit is relevant only for an ADP probe.
54663 +                *  When this bit is set, it means that the ramp time has
54664 +                *  completed ie ADPCTL.RTIM has reached its terminal value
54665 +                *  of 0x7FF.  This is a debug feature that allows software
54666 +                *  to read the ramp time after each cycle.
54667 +                *  This bit is valid only if OTG_Ver = 1'b1.
54668 +                */
54669 +               unsigned adp_tmout_int:1;
54670 +               /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)
54671 +                *  When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.
54672 +                *  This bit is valid only if OTG_Ver = 1'b1.
54673 +                */
54674 +               unsigned adp_prb_int_msk:1;
54675 +               /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)
54676 +                *  When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.
54677 +                *  This bit is valid only if OTG_Ver = 1'b1.
54678 +                */
54679 +               unsigned adp_sns_int_msk:1;
54680 +               /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)
54681 +                *  When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.
54682 +                *  This bit is valid only if OTG_Ver = 1'b1.
54683 +                */
54684 +               unsigned adp_tmout_int_msk:1;
54685 +               /** Access Request
54686 +                * 2'b00 - Read/Write Valid (updated by the core)
54687 +                * 2'b01 - Read
54688 +                * 2'b00 - Write
54689 +                * 2'b00 - Reserved
54690 +                */
54691 +               unsigned ar:2;
54692 +                /** Reserved */
54693 +               unsigned reserved29_31:3;
54694 +       } b;
54695 +} adpctl_data_t;
54696 +
54697 +////////////////////////////////////////////
54698 +// Device Registers
54699 +/**
54700 + * Device Global Registers. <i>Offsets 800h-BFFh</i>
54701 + *
54702 + * The following structures define the size and relative field offsets
54703 + * for the Device Mode Registers.
54704 + *
54705 + * <i>These registers are visible only in Device mode and must not be
54706 + * accessed in Host mode, as the results are unknown.</i>
54707 + */
54708 +typedef struct dwc_otg_dev_global_regs {
54709 +       /** Device Configuration Register. <i>Offset 800h</i> */
54710 +       volatile uint32_t dcfg;
54711 +       /** Device Control Register. <i>Offset: 804h</i> */
54712 +       volatile uint32_t dctl;
54713 +       /** Device Status Register (Read Only). <i>Offset: 808h</i> */
54714 +       volatile uint32_t dsts;
54715 +       /** Reserved. <i>Offset: 80Ch</i> */
54716 +       uint32_t unused;
54717 +       /** Device IN Endpoint Common Interrupt Mask
54718 +        * Register. <i>Offset: 810h</i> */
54719 +       volatile uint32_t diepmsk;
54720 +       /** Device OUT Endpoint Common Interrupt Mask
54721 +        * Register. <i>Offset: 814h</i> */
54722 +       volatile uint32_t doepmsk;
54723 +       /** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */
54724 +       volatile uint32_t daint;
54725 +       /** Device All Endpoints Interrupt Mask Register.  <i>Offset:
54726 +        * 81Ch</i> */
54727 +       volatile uint32_t daintmsk;
54728 +       /** Device IN Token Queue Read Register-1 (Read Only).
54729 +        * <i>Offset: 820h</i> */
54730 +       volatile uint32_t dtknqr1;
54731 +       /** Device IN Token Queue Read Register-2 (Read Only).
54732 +        * <i>Offset: 824h</i> */
54733 +       volatile uint32_t dtknqr2;
54734 +       /** Device VBUS  discharge Register.  <i>Offset: 828h</i> */
54735 +       volatile uint32_t dvbusdis;
54736 +       /** Device VBUS Pulse Register.  <i>Offset: 82Ch</i> */
54737 +       volatile uint32_t dvbuspulse;
54738 +       /** Device IN Token Queue Read Register-3 (Read Only). /
54739 +        *      Device Thresholding control register (Read/Write)
54740 +        * <i>Offset: 830h</i> */
54741 +       volatile uint32_t dtknqr3_dthrctl;
54742 +       /** Device IN Token Queue Read Register-4 (Read Only). /
54743 +        *      Device IN EPs empty Inr. Mask Register (Read/Write)
54744 +        * <i>Offset: 834h</i> */
54745 +       volatile uint32_t dtknqr4_fifoemptymsk;
54746 +       /** Device Each Endpoint Interrupt Register (Read Only). /
54747 +        * <i>Offset: 838h</i> */
54748 +       volatile uint32_t deachint;
54749 +       /** Device Each Endpoint Interrupt mask Register (Read/Write). /
54750 +        * <i>Offset: 83Ch</i> */
54751 +       volatile uint32_t deachintmsk;
54752 +       /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
54753 +        * <i>Offset: 840h</i> */
54754 +       volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
54755 +       /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
54756 +        * <i>Offset: 880h</i> */
54757 +       volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
54758 +} dwc_otg_device_global_regs_t;
54759 +
54760 +/**
54761 + * This union represents the bit fields in the Device Configuration
54762 + * Register.  Read the register into the <i>d32</i> member then
54763 + * set/clear the bits using the <i>b</i>it elements.  Write the
54764 + * <i>d32</i> member to the dcfg register.
54765 + */
54766 +typedef union dcfg_data {
54767 +       /** raw register data */
54768 +       uint32_t d32;
54769 +       /** register bits */
54770 +       struct {
54771 +               /** Device Speed */
54772 +               unsigned devspd:2;
54773 +               /** Non Zero Length Status OUT Handshake */
54774 +               unsigned nzstsouthshk:1;
54775 +#define DWC_DCFG_SEND_STALL 1
54776 +
54777 +               unsigned ena32khzs:1;
54778 +               /** Device Addresses */
54779 +               unsigned devaddr:7;
54780 +               /** Periodic Frame Interval */
54781 +               unsigned perfrint:2;
54782 +#define DWC_DCFG_FRAME_INTERVAL_80 0
54783 +#define DWC_DCFG_FRAME_INTERVAL_85 1
54784 +#define DWC_DCFG_FRAME_INTERVAL_90 2
54785 +#define DWC_DCFG_FRAME_INTERVAL_95 3
54786 +
54787 +               /** Enable Device OUT NAK for bulk in DDMA mode */
54788 +               unsigned endevoutnak:1;
54789 +
54790 +               unsigned reserved14_17:4;
54791 +               /** In Endpoint Mis-match count */
54792 +               unsigned epmscnt:5;
54793 +               /** Enable Descriptor DMA in Device mode */
54794 +               unsigned descdma:1;
54795 +               unsigned perschintvl:2;
54796 +               unsigned resvalid:6;
54797 +       } b;
54798 +} dcfg_data_t;
54799 +
54800 +/**
54801 + * This union represents the bit fields in the Device Control
54802 + * Register.  Read the register into the <i>d32</i> member then
54803 + * set/clear the bits using the <i>b</i>it elements.
54804 + */
54805 +typedef union dctl_data {
54806 +       /** raw register data */
54807 +       uint32_t d32;
54808 +       /** register bits */
54809 +       struct {
54810 +               /** Remote Wakeup */
54811 +               unsigned rmtwkupsig:1;
54812 +               /** Soft Disconnect */
54813 +               unsigned sftdiscon:1;
54814 +               /** Global Non-Periodic IN NAK Status */
54815 +               unsigned gnpinnaksts:1;
54816 +               /** Global OUT NAK Status */
54817 +               unsigned goutnaksts:1;
54818 +               /** Test Control */
54819 +               unsigned tstctl:3;
54820 +               /** Set Global Non-Periodic IN NAK */
54821 +               unsigned sgnpinnak:1;
54822 +               /** Clear Global Non-Periodic IN NAK */
54823 +               unsigned cgnpinnak:1;
54824 +               /** Set Global OUT NAK */
54825 +               unsigned sgoutnak:1;
54826 +               /** Clear Global OUT NAK */
54827 +               unsigned cgoutnak:1;
54828 +               /** Power-On Programming Done */
54829 +               unsigned pwronprgdone:1;
54830 +               /** Reserved */
54831 +               unsigned reserved:1;
54832 +               /** Global Multi Count */
54833 +               unsigned gmc:2;
54834 +               /** Ignore Frame Number for ISOC EPs */
54835 +               unsigned ifrmnum:1;
54836 +               /** NAK on Babble */
54837 +               unsigned nakonbble:1;
54838 +               /** Enable Continue on BNA */
54839 +               unsigned encontonbna:1;
54840 +
54841 +               unsigned reserved18_31:14;
54842 +       } b;
54843 +} dctl_data_t;
54844 +
54845 +/**
54846 + * This union represents the bit fields in the Device Status
54847 + * Register.  Read the register into the <i>d32</i> member then
54848 + * set/clear the bits using the <i>b</i>it elements.
54849 + */
54850 +typedef union dsts_data {
54851 +       /** raw register data */
54852 +       uint32_t d32;
54853 +       /** register bits */
54854 +       struct {
54855 +               /** Suspend Status */
54856 +               unsigned suspsts:1;
54857 +               /** Enumerated Speed */
54858 +               unsigned enumspd:2;
54859 +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
54860 +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
54861 +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ              2
54862 +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ             3
54863 +               /** Erratic Error */
54864 +               unsigned errticerr:1;
54865 +               unsigned reserved4_7:4;
54866 +               /** Frame or Microframe Number of the received SOF */
54867 +               unsigned soffn:14;
54868 +               unsigned reserved22_31:10;
54869 +       } b;
54870 +} dsts_data_t;
54871 +
54872 +/**
54873 + * This union represents the bit fields in the Device IN EP Interrupt
54874 + * Register and the Device IN EP Common Mask Register.
54875 + *
54876 + * - Read the register into the <i>d32</i> member then set/clear the
54877 + *      bits using the <i>b</i>it elements.
54878 + */
54879 +typedef union diepint_data {
54880 +       /** raw register data */
54881 +       uint32_t d32;
54882 +       /** register bits */
54883 +       struct {
54884 +               /** Transfer complete mask */
54885 +               unsigned xfercompl:1;
54886 +               /** Endpoint disable mask */
54887 +               unsigned epdisabled:1;
54888 +               /** AHB Error mask */
54889 +               unsigned ahberr:1;
54890 +               /** TimeOUT Handshake mask (non-ISOC EPs) */
54891 +               unsigned timeout:1;
54892 +               /** IN Token received with TxF Empty mask */
54893 +               unsigned intktxfemp:1;
54894 +               /** IN Token Received with EP mismatch mask */
54895 +               unsigned intknepmis:1;
54896 +               /** IN Endpoint NAK Effective mask */
54897 +               unsigned inepnakeff:1;
54898 +               /** Reserved */
54899 +               unsigned emptyintr:1;
54900 +
54901 +               unsigned txfifoundrn:1;
54902 +
54903 +               /** BNA Interrupt mask */
54904 +               unsigned bna:1;
54905 +
54906 +               unsigned reserved10_12:3;
54907 +               /** BNA Interrupt mask */
54908 +               unsigned nak:1;
54909 +
54910 +               unsigned reserved14_31:18;
54911 +       } b;
54912 +} diepint_data_t;
54913 +
54914 +/**
54915 + * This union represents the bit fields in the Device IN EP
54916 + * Common/Dedicated Interrupt Mask Register.
54917 + */
54918 +typedef union diepint_data diepmsk_data_t;
54919 +
54920 +/**
54921 + * This union represents the bit fields in the Device OUT EP Interrupt
54922 + * Registerand Device OUT EP Common Interrupt Mask Register.
54923 + *
54924 + * - Read the register into the <i>d32</i> member then set/clear the
54925 + *      bits using the <i>b</i>it elements.
54926 + */
54927 +typedef union doepint_data {
54928 +       /** raw register data */
54929 +       uint32_t d32;
54930 +       /** register bits */
54931 +       struct {
54932 +               /** Transfer complete */
54933 +               unsigned xfercompl:1;
54934 +               /** Endpoint disable  */
54935 +               unsigned epdisabled:1;
54936 +               /** AHB Error */
54937 +               unsigned ahberr:1;
54938 +               /** Setup Phase Done (contorl EPs) */
54939 +               unsigned setup:1;
54940 +               /** OUT Token Received when Endpoint Disabled */
54941 +               unsigned outtknepdis:1;
54942 +
54943 +               unsigned stsphsercvd:1;
54944 +               /** Back-to-Back SETUP Packets Received */
54945 +               unsigned back2backsetup:1;
54946 +
54947 +               unsigned reserved7:1;
54948 +               /** OUT packet Error */
54949 +               unsigned outpkterr:1;
54950 +               /** BNA Interrupt */
54951 +               unsigned bna:1;
54952 +
54953 +               unsigned reserved10:1;
54954 +               /** Packet Drop Status */
54955 +               unsigned pktdrpsts:1;
54956 +               /** Babble Interrupt */
54957 +               unsigned babble:1;
54958 +               /** NAK Interrupt */
54959 +               unsigned nak:1;
54960 +               /** NYET Interrupt */
54961 +               unsigned nyet:1;
54962 +               /** Bit indicating setup packet received */
54963 +               unsigned sr:1;
54964 +
54965 +               unsigned reserved16_31:16;
54966 +       } b;
54967 +} doepint_data_t;
54968 +
54969 +/**
54970 + * This union represents the bit fields in the Device OUT EP
54971 + * Common/Dedicated Interrupt Mask Register.
54972 + */
54973 +typedef union doepint_data doepmsk_data_t;
54974 +
54975 +/**
54976 + * This union represents the bit fields in the Device All EP Interrupt
54977 + * and Mask Registers.
54978 + * - Read the register into the <i>d32</i> member then set/clear the
54979 + *      bits using the <i>b</i>it elements.
54980 + */
54981 +typedef union daint_data {
54982 +       /** raw register data */
54983 +       uint32_t d32;
54984 +       /** register bits */
54985 +       struct {
54986 +               /** IN Endpoint bits */
54987 +               unsigned in:16;
54988 +               /** OUT Endpoint bits */
54989 +               unsigned out:16;
54990 +       } ep;
54991 +       struct {
54992 +               /** IN Endpoint bits */
54993 +               unsigned inep0:1;
54994 +               unsigned inep1:1;
54995 +               unsigned inep2:1;
54996 +               unsigned inep3:1;
54997 +               unsigned inep4:1;
54998 +               unsigned inep5:1;
54999 +               unsigned inep6:1;
55000 +               unsigned inep7:1;
55001 +               unsigned inep8:1;
55002 +               unsigned inep9:1;
55003 +               unsigned inep10:1;
55004 +               unsigned inep11:1;
55005 +               unsigned inep12:1;
55006 +               unsigned inep13:1;
55007 +               unsigned inep14:1;
55008 +               unsigned inep15:1;
55009 +               /** OUT Endpoint bits */
55010 +               unsigned outep0:1;
55011 +               unsigned outep1:1;
55012 +               unsigned outep2:1;
55013 +               unsigned outep3:1;
55014 +               unsigned outep4:1;
55015 +               unsigned outep5:1;
55016 +               unsigned outep6:1;
55017 +               unsigned outep7:1;
55018 +               unsigned outep8:1;
55019 +               unsigned outep9:1;
55020 +               unsigned outep10:1;
55021 +               unsigned outep11:1;
55022 +               unsigned outep12:1;
55023 +               unsigned outep13:1;
55024 +               unsigned outep14:1;
55025 +               unsigned outep15:1;
55026 +       } b;
55027 +} daint_data_t;
55028 +
55029 +/**
55030 + * This union represents the bit fields in the Device IN Token Queue
55031 + * Read Registers.
55032 + * - Read the register into the <i>d32</i> member.
55033 + * - READ-ONLY Register
55034 + */
55035 +typedef union dtknq1_data {
55036 +       /** raw register data */
55037 +       uint32_t d32;
55038 +       /** register bits */
55039 +       struct {
55040 +               /** In Token Queue Write Pointer */
55041 +               unsigned intknwptr:5;
55042 +               /** Reserved */
55043 +               unsigned reserved05_06:2;
55044 +               /** write pointer has wrapped. */
55045 +               unsigned wrap_bit:1;
55046 +               /** EP Numbers of IN Tokens 0 ... 4 */
55047 +               unsigned epnums0_5:24;
55048 +       } b;
55049 +} dtknq1_data_t;
55050 +
55051 +/**
55052 + * This union represents Threshold control Register
55053 + * - Read and write the register into the <i>d32</i> member.
55054 + * - READ-WRITABLE Register
55055 + */
55056 +typedef union dthrctl_data {
55057 +       /** raw register data */
55058 +       uint32_t d32;
55059 +       /** register bits */
55060 +       struct {
55061 +               /** non ISO Tx Thr. Enable */
55062 +               unsigned non_iso_thr_en:1;
55063 +               /** ISO Tx Thr. Enable */
55064 +               unsigned iso_thr_en:1;
55065 +               /** Tx Thr. Length */
55066 +               unsigned tx_thr_len:9;
55067 +               /** AHB Threshold ratio */
55068 +               unsigned ahb_thr_ratio:2;
55069 +               /** Reserved */
55070 +               unsigned reserved13_15:3;
55071 +               /** Rx Thr. Enable */
55072 +               unsigned rx_thr_en:1;
55073 +               /** Rx Thr. Length */
55074 +               unsigned rx_thr_len:9;
55075 +               unsigned reserved26:1;
55076 +               /** Arbiter Parking Enable*/
55077 +               unsigned arbprken:1;
55078 +               /** Reserved */
55079 +               unsigned reserved28_31:4;
55080 +       } b;
55081 +} dthrctl_data_t;
55082 +
55083 +/**
55084 + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
55085 + * 900h-AFCh</i>
55086 + *
55087 + * There will be one set of endpoint registers per logical endpoint
55088 + * implemented.
55089 + *
55090 + * <i>These registers are visible only in Device mode and must not be
55091 + * accessed in Host mode, as the results are unknown.</i>
55092 + */
55093 +typedef struct dwc_otg_dev_in_ep_regs {
55094 +       /** Device IN Endpoint Control Register. <i>Offset:900h +
55095 +        * (ep_num * 20h) + 00h</i> */
55096 +       volatile uint32_t diepctl;
55097 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
55098 +       uint32_t reserved04;
55099 +       /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
55100 +        * (ep_num * 20h) + 08h</i> */
55101 +       volatile uint32_t diepint;
55102 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
55103 +       uint32_t reserved0C;
55104 +       /** Device IN Endpoint Transfer Size
55105 +        * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
55106 +       volatile uint32_t dieptsiz;
55107 +       /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
55108 +        * (ep_num * 20h) + 14h</i> */
55109 +       volatile uint32_t diepdma;
55110 +       /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
55111 +        * (ep_num * 20h) + 18h</i> */
55112 +       volatile uint32_t dtxfsts;
55113 +       /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
55114 +        * (ep_num * 20h) + 1Ch</i> */
55115 +       volatile uint32_t diepdmab;
55116 +} dwc_otg_dev_in_ep_regs_t;
55117 +
55118 +/**
55119 + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
55120 + * B00h-CFCh</i>
55121 + *
55122 + * There will be one set of endpoint registers per logical endpoint
55123 + * implemented.
55124 + *
55125 + * <i>These registers are visible only in Device mode and must not be
55126 + * accessed in Host mode, as the results are unknown.</i>
55127 + */
55128 +typedef struct dwc_otg_dev_out_ep_regs {
55129 +       /** Device OUT Endpoint Control Register. <i>Offset:B00h +
55130 +        * (ep_num * 20h) + 00h</i> */
55131 +       volatile uint32_t doepctl;
55132 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
55133 +       uint32_t reserved04;
55134 +       /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
55135 +        * (ep_num * 20h) + 08h</i> */
55136 +       volatile uint32_t doepint;
55137 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
55138 +       uint32_t reserved0C;
55139 +       /** Device OUT Endpoint Transfer Size Register. <i>Offset:
55140 +        * B00h + (ep_num * 20h) + 10h</i> */
55141 +       volatile uint32_t doeptsiz;
55142 +       /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
55143 +        * + (ep_num * 20h) + 14h</i> */
55144 +       volatile uint32_t doepdma;
55145 +       /** Reserved. <i>Offset:B00h +   * (ep_num * 20h) + 18h</i> */
55146 +       uint32_t unused;
55147 +       /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
55148 +        * + (ep_num * 20h) + 1Ch</i> */
55149 +       uint32_t doepdmab;
55150 +} dwc_otg_dev_out_ep_regs_t;
55151 +
55152 +/**
55153 + * This union represents the bit fields in the Device EP Control
55154 + * Register.  Read the register into the <i>d32</i> member then
55155 + * set/clear the bits using the <i>b</i>it elements.
55156 + */
55157 +typedef union depctl_data {
55158 +       /** raw register data */
55159 +       uint32_t d32;
55160 +       /** register bits */
55161 +       struct {
55162 +               /** Maximum Packet Size
55163 +                * IN/OUT EPn
55164 +                * IN/OUT EP0 - 2 bits
55165 +                *       2'b00: 64 Bytes
55166 +                *       2'b01: 32
55167 +                *       2'b10: 16
55168 +                *       2'b11: 8 */
55169 +               unsigned mps:11;
55170 +#define DWC_DEP0CTL_MPS_64      0
55171 +#define DWC_DEP0CTL_MPS_32      1
55172 +#define DWC_DEP0CTL_MPS_16      2
55173 +#define DWC_DEP0CTL_MPS_8       3
55174 +
55175 +               /** Next Endpoint
55176 +                * IN EPn/IN EP0
55177 +                * OUT EPn/OUT EP0 - reserved */
55178 +               unsigned nextep:4;
55179 +
55180 +               /** USB Active Endpoint */
55181 +               unsigned usbactep:1;
55182 +
55183 +               /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
55184 +                * This field contains the PID of the packet going to
55185 +                * be received or transmitted on this endpoint. The
55186 +                * application should program the PID of the first
55187 +                * packet going to be received or transmitted on this
55188 +                * endpoint , after the endpoint is
55189 +                * activated. Application use the SetD1PID and
55190 +                * SetD0PID fields of this register to program either
55191 +                * D0 or D1 PID.
55192 +                *
55193 +                * The encoding for this field is
55194 +                *       - 0: D0
55195 +                *       - 1: D1
55196 +                */
55197 +               unsigned dpid:1;
55198 +
55199 +               /** NAK Status */
55200 +               unsigned naksts:1;
55201 +
55202 +               /** Endpoint Type
55203 +                *      2'b00: Control
55204 +                *      2'b01: Isochronous
55205 +                *      2'b10: Bulk
55206 +                *      2'b11: Interrupt */
55207 +               unsigned eptype:2;
55208 +
55209 +               /** Snoop Mode
55210 +                * OUT EPn/OUT EP0
55211 +                * IN EPn/IN EP0 - reserved */
55212 +               unsigned snp:1;
55213 +
55214 +               /** Stall Handshake */
55215 +               unsigned stall:1;
55216 +
55217 +               /** Tx Fifo Number
55218 +                * IN EPn/IN EP0
55219 +                * OUT EPn/OUT EP0 - reserved */
55220 +               unsigned txfnum:4;
55221 +
55222 +               /** Clear NAK */
55223 +               unsigned cnak:1;
55224 +               /** Set NAK */
55225 +               unsigned snak:1;
55226 +               /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
55227 +                * Writing to this field sets the Endpoint DPID (DPID)
55228 +                * field in this register to DATA0. Set Even
55229 +                * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
55230 +                * Writing to this field sets the Even/Odd
55231 +                * (micro)frame (EO_FrNum) field to even (micro)
55232 +                * frame.
55233 +                */
55234 +               unsigned setd0pid:1;
55235 +               /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
55236 +                * Writing to this field sets the Endpoint DPID (DPID)
55237 +                * field in this register to DATA1 Set Odd
55238 +                * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
55239 +                * Writing to this field sets the Even/Odd
55240 +                * (micro)frame (EO_FrNum) field to odd (micro) frame.
55241 +                */
55242 +               unsigned setd1pid:1;
55243 +
55244 +               /** Endpoint Disable */
55245 +               unsigned epdis:1;
55246 +               /** Endpoint Enable */
55247 +               unsigned epena:1;
55248 +       } b;
55249 +} depctl_data_t;
55250 +
55251 +/**
55252 + * This union represents the bit fields in the Device EP Transfer
55253 + * Size Register.  Read the register into the <i>d32</i> member then
55254 + * set/clear the bits using the <i>b</i>it elements.
55255 + */
55256 +typedef union deptsiz_data {
55257 +               /** raw register data */
55258 +       uint32_t d32;
55259 +               /** register bits */
55260 +       struct {
55261 +               /** Transfer size */
55262 +               unsigned xfersize:19;
55263 +/** Max packet count for EP (pow(2,10)-1) */
55264 +#define MAX_PKT_CNT 1023
55265 +               /** Packet Count */
55266 +               unsigned pktcnt:10;
55267 +               /** Multi Count - Periodic IN endpoints */
55268 +               unsigned mc:2;
55269 +               unsigned reserved:1;
55270 +       } b;
55271 +} deptsiz_data_t;
55272 +
55273 +/**
55274 + * This union represents the bit fields in the Device EP 0 Transfer
55275 + * Size Register.  Read the register into the <i>d32</i> member then
55276 + * set/clear the bits using the <i>b</i>it elements.
55277 + */
55278 +typedef union deptsiz0_data {
55279 +               /** raw register data */
55280 +       uint32_t d32;
55281 +               /** register bits */
55282 +       struct {
55283 +               /** Transfer size */
55284 +               unsigned xfersize:7;
55285 +                               /** Reserved */
55286 +               unsigned reserved7_18:12;
55287 +               /** Packet Count */
55288 +               unsigned pktcnt:2;
55289 +                               /** Reserved */
55290 +               unsigned reserved21_28:8;
55291 +                               /**Setup Packet Count (DOEPTSIZ0 Only) */
55292 +               unsigned supcnt:2;
55293 +               unsigned reserved31;
55294 +       } b;
55295 +} deptsiz0_data_t;
55296 +
55297 +/////////////////////////////////////////////////
55298 +// DMA Descriptor Specific Structures
55299 +//
55300 +
55301 +/** Buffer status definitions */
55302 +
55303 +#define BS_HOST_READY  0x0
55304 +#define BS_DMA_BUSY            0x1
55305 +#define BS_DMA_DONE            0x2
55306 +#define BS_HOST_BUSY   0x3
55307 +
55308 +/** Receive/Transmit status definitions */
55309 +
55310 +#define RTS_SUCCESS            0x0
55311 +#define RTS_BUFFLUSH   0x1
55312 +#define RTS_RESERVED   0x2
55313 +#define RTS_BUFERR             0x3
55314 +
55315 +/**
55316 + * This union represents the bit fields in the DMA Descriptor
55317 + * status quadlet. Read the quadlet into the <i>d32</i> member then
55318 + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
55319 + * <i>b_iso_in</i> elements.
55320 + */
55321 +typedef union dev_dma_desc_sts {
55322 +               /** raw register data */
55323 +       uint32_t d32;
55324 +               /** quadlet bits */
55325 +       struct {
55326 +               /** Received number of bytes */
55327 +               unsigned bytes:16;
55328 +               /** NAK bit - only for OUT EPs */
55329 +               unsigned nak:1;
55330 +               unsigned reserved17_22:6;
55331 +               /** Multiple Transfer - only for OUT EPs */
55332 +               unsigned mtrf:1;
55333 +               /** Setup Packet received - only for OUT EPs */
55334 +               unsigned sr:1;
55335 +               /** Interrupt On Complete */
55336 +               unsigned ioc:1;
55337 +               /** Short Packet */
55338 +               unsigned sp:1;
55339 +               /** Last */
55340 +               unsigned l:1;
55341 +               /** Receive Status */
55342 +               unsigned sts:2;
55343 +               /** Buffer Status */
55344 +               unsigned bs:2;
55345 +       } b;
55346 +
55347 +//#ifdef DWC_EN_ISOC
55348 +               /** iso out quadlet bits */
55349 +       struct {
55350 +               /** Received number of bytes */
55351 +               unsigned rxbytes:11;
55352 +
55353 +               unsigned reserved11:1;
55354 +               /** Frame Number */
55355 +               unsigned framenum:11;
55356 +               /** Received ISO Data PID */
55357 +               unsigned pid:2;
55358 +               /** Interrupt On Complete */
55359 +               unsigned ioc:1;
55360 +               /** Short Packet */
55361 +               unsigned sp:1;
55362 +               /** Last */
55363 +               unsigned l:1;
55364 +               /** Receive Status */
55365 +               unsigned rxsts:2;
55366 +               /** Buffer Status */
55367 +               unsigned bs:2;
55368 +       } b_iso_out;
55369 +
55370 +               /** iso in quadlet bits */
55371 +       struct {
55372 +               /** Transmited number of bytes */
55373 +               unsigned txbytes:12;
55374 +               /** Frame Number */
55375 +               unsigned framenum:11;
55376 +               /** Transmited ISO Data PID */
55377 +               unsigned pid:2;
55378 +               /** Interrupt On Complete */
55379 +               unsigned ioc:1;
55380 +               /** Short Packet */
55381 +               unsigned sp:1;
55382 +               /** Last */
55383 +               unsigned l:1;
55384 +               /** Transmit Status */
55385 +               unsigned txsts:2;
55386 +               /** Buffer Status */
55387 +               unsigned bs:2;
55388 +       } b_iso_in;
55389 +//#endif                                /* DWC_EN_ISOC */
55390 +} dev_dma_desc_sts_t;
55391 +
55392 +/**
55393 + * DMA Descriptor structure
55394 + *
55395 + * DMA Descriptor structure contains two quadlets:
55396 + * Status quadlet and Data buffer pointer.
55397 + */
55398 +typedef struct dwc_otg_dev_dma_desc {
55399 +       /** DMA Descriptor status quadlet */
55400 +       dev_dma_desc_sts_t status;
55401 +       /** DMA Descriptor data buffer pointer */
55402 +       uint32_t buf;
55403 +} dwc_otg_dev_dma_desc_t;
55404 +
55405 +/**
55406 + * The dwc_otg_dev_if structure contains information needed to manage
55407 + * the DWC_otg controller acting in device mode. It represents the
55408 + * programming view of the device-specific aspects of the controller.
55409 + */
55410 +typedef struct dwc_otg_dev_if {
55411 +       /** Pointer to device Global registers.
55412 +        * Device Global Registers starting at offset 800h
55413 +        */
55414 +       dwc_otg_device_global_regs_t *dev_global_regs;
55415 +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
55416 +
55417 +       /**
55418 +        * Device Logical IN Endpoint-Specific Registers 900h-AFCh
55419 +        */
55420 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
55421 +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
55422 +#define DWC_EP_REG_OFFSET 0x20
55423 +
55424 +       /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
55425 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
55426 +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
55427 +
55428 +       /* Device configuration information */
55429 +       uint8_t speed;                           /**< Device Speed      0: Unknown, 1: LS, 2:FS, 3: HS */
55430 +       uint8_t num_in_eps;              /**< Number # of Tx EP range: 0-15 exept ep0 */
55431 +       uint8_t num_out_eps;             /**< Number # of Rx EP range: 0-15 exept ep 0*/
55432 +
55433 +       /** Size of periodic FIFOs (Bytes) */
55434 +       uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
55435 +
55436 +       /** Size of Tx FIFOs (Bytes) */
55437 +       uint16_t tx_fifo_size[MAX_TX_FIFOS];
55438 +
55439 +       /** Thresholding enable flags and length varaiables **/
55440 +       uint16_t rx_thr_en;
55441 +       uint16_t iso_tx_thr_en;
55442 +       uint16_t non_iso_tx_thr_en;
55443 +
55444 +       uint16_t rx_thr_length;
55445 +       uint16_t tx_thr_length;
55446 +
55447 +       /**
55448 +        * Pointers to the DMA Descriptors for EP0 Control
55449 +        * transfers (virtual and physical)
55450 +        */
55451 +
55452 +       /** 2 descriptors for SETUP packets */
55453 +       dwc_dma_t dma_setup_desc_addr[2];
55454 +       dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
55455 +
55456 +       /** Pointer to Descriptor with latest SETUP packet */
55457 +       dwc_otg_dev_dma_desc_t *psetup;
55458 +
55459 +       /** Index of current SETUP handler descriptor */
55460 +       uint32_t setup_desc_index;
55461 +
55462 +       /** Descriptor for Data In or Status In phases */
55463 +       dwc_dma_t dma_in_desc_addr;
55464 +       dwc_otg_dev_dma_desc_t *in_desc_addr;
55465 +
55466 +       /** Descriptor for Data Out or Status Out phases */
55467 +       dwc_dma_t dma_out_desc_addr;
55468 +       dwc_otg_dev_dma_desc_t *out_desc_addr;
55469 +
55470 +       /** Setup Packet Detected - if set clear NAK when queueing */
55471 +       uint32_t spd;
55472 +       /** Isoc ep pointer on which incomplete happens */
55473 +       void *isoc_ep;
55474 +
55475 +} dwc_otg_dev_if_t;
55476 +
55477 +/////////////////////////////////////////////////
55478 +// Host Mode Register Structures
55479 +//
55480 +/**
55481 + * The Host Global Registers structure defines the size and relative
55482 + * field offsets for the Host Mode Global Registers.  Host Global
55483 + * Registers offsets 400h-7FFh.
55484 +*/
55485 +typedef struct dwc_otg_host_global_regs {
55486 +       /** Host Configuration Register.   <i>Offset: 400h</i> */
55487 +       volatile uint32_t hcfg;
55488 +       /** Host Frame Interval Register.       <i>Offset: 404h</i> */
55489 +       volatile uint32_t hfir;
55490 +       /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
55491 +       volatile uint32_t hfnum;
55492 +       /** Reserved.   <i>Offset: 40Ch</i> */
55493 +       uint32_t reserved40C;
55494 +       /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
55495 +       volatile uint32_t hptxsts;
55496 +       /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
55497 +       volatile uint32_t haint;
55498 +       /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
55499 +       volatile uint32_t haintmsk;
55500 +       /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
55501 +       volatile uint32_t hflbaddr;
55502 +} dwc_otg_host_global_regs_t;
55503 +
55504 +/**
55505 + * This union represents the bit fields in the Host Configuration Register.
55506 + * Read the register into the <i>d32</i> member then set/clear the bits using
55507 + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
55508 + */
55509 +typedef union hcfg_data {
55510 +       /** raw register data */
55511 +       uint32_t d32;
55512 +
55513 +       /** register bits */
55514 +       struct {
55515 +               /** FS/LS Phy Clock Select */
55516 +               unsigned fslspclksel:2;
55517 +#define DWC_HCFG_30_60_MHZ 0
55518 +#define DWC_HCFG_48_MHZ           1
55519 +#define DWC_HCFG_6_MHZ    2
55520 +
55521 +               /** FS/LS Only Support */
55522 +               unsigned fslssupp:1;
55523 +               unsigned reserved3_6:4;
55524 +               /** Enable 32-KHz Suspend Mode */
55525 +               unsigned ena32khzs:1;
55526 +               /** Resume Validation Periiod */
55527 +               unsigned resvalid:8;
55528 +               unsigned reserved16_22:7;
55529 +               /** Enable Scatter/gather DMA in Host mode */
55530 +               unsigned descdma:1;
55531 +               /** Frame List Entries */
55532 +               unsigned frlisten:2;
55533 +               /** Enable Periodic Scheduling */
55534 +               unsigned perschedena:1;
55535 +               unsigned reserved27_30:4;
55536 +               unsigned modechtimen:1;
55537 +       } b;
55538 +} hcfg_data_t;
55539 +
55540 +/**
55541 + * This union represents the bit fields in the Host Frame Remaing/Number
55542 + * Register.
55543 + */
55544 +typedef union hfir_data {
55545 +       /** raw register data */
55546 +       uint32_t d32;
55547 +
55548 +       /** register bits */
55549 +       struct {
55550 +               unsigned frint:16;
55551 +               unsigned hfirrldctrl:1;
55552 +               unsigned reserved:15;
55553 +       } b;
55554 +} hfir_data_t;
55555 +
55556 +/**
55557 + * This union represents the bit fields in the Host Frame Remaing/Number
55558 + * Register.
55559 + */
55560 +typedef union hfnum_data {
55561 +       /** raw register data */
55562 +       uint32_t d32;
55563 +
55564 +       /** register bits */
55565 +       struct {
55566 +               unsigned frnum:16;
55567 +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
55568 +               unsigned frrem:16;
55569 +       } b;
55570 +} hfnum_data_t;
55571 +
55572 +typedef union hptxsts_data {
55573 +       /** raw register data */
55574 +       uint32_t d32;
55575 +
55576 +       /** register bits */
55577 +       struct {
55578 +               unsigned ptxfspcavail:16;
55579 +               unsigned ptxqspcavail:8;
55580 +               /** Top of the Periodic Transmit Request Queue
55581 +                *      - bit 24 - Terminate (last entry for the selected channel)
55582 +                *      - bits 26:25 - Token Type
55583 +                *        - 2'b00 - Zero length
55584 +                *        - 2'b01 - Ping
55585 +                *        - 2'b10 - Disable
55586 +                *      - bits 30:27 - Channel Number
55587 +                *      - bit 31 - Odd/even microframe
55588 +                */
55589 +               unsigned ptxqtop_terminate:1;
55590 +               unsigned ptxqtop_token:2;
55591 +               unsigned ptxqtop_chnum:4;
55592 +               unsigned ptxqtop_odd:1;
55593 +       } b;
55594 +} hptxsts_data_t;
55595 +
55596 +/**
55597 + * This union represents the bit fields in the Host Port Control and Status
55598 + * Register. Read the register into the <i>d32</i> member then set/clear the
55599 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55600 + * hprt0 register.
55601 + */
55602 +typedef union hprt0_data {
55603 +       /** raw register data */
55604 +       uint32_t d32;
55605 +       /** register bits */
55606 +       struct {
55607 +               unsigned prtconnsts:1;
55608 +               unsigned prtconndet:1;
55609 +               unsigned prtena:1;
55610 +               unsigned prtenchng:1;
55611 +               unsigned prtovrcurract:1;
55612 +               unsigned prtovrcurrchng:1;
55613 +               unsigned prtres:1;
55614 +               unsigned prtsusp:1;
55615 +               unsigned prtrst:1;
55616 +               unsigned reserved9:1;
55617 +               unsigned prtlnsts:2;
55618 +               unsigned prtpwr:1;
55619 +               unsigned prttstctl:4;
55620 +               unsigned prtspd:2;
55621 +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
55622 +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
55623 +#define DWC_HPRT0_PRTSPD_LOW_SPEED     2
55624 +               unsigned reserved19_31:13;
55625 +       } b;
55626 +} hprt0_data_t;
55627 +
55628 +/**
55629 + * This union represents the bit fields in the Host All Interrupt
55630 + * Register.
55631 + */
55632 +typedef union haint_data {
55633 +       /** raw register data */
55634 +       uint32_t d32;
55635 +       /** register bits */
55636 +       struct {
55637 +               unsigned ch0:1;
55638 +               unsigned ch1:1;
55639 +               unsigned ch2:1;
55640 +               unsigned ch3:1;
55641 +               unsigned ch4:1;
55642 +               unsigned ch5:1;
55643 +               unsigned ch6:1;
55644 +               unsigned ch7:1;
55645 +               unsigned ch8:1;
55646 +               unsigned ch9:1;
55647 +               unsigned ch10:1;
55648 +               unsigned ch11:1;
55649 +               unsigned ch12:1;
55650 +               unsigned ch13:1;
55651 +               unsigned ch14:1;
55652 +               unsigned ch15:1;
55653 +               unsigned reserved:16;
55654 +       } b;
55655 +
55656 +       struct {
55657 +               unsigned chint:16;
55658 +               unsigned reserved:16;
55659 +       } b2;
55660 +} haint_data_t;
55661 +
55662 +/**
55663 + * This union represents the bit fields in the Host All Interrupt
55664 + * Register.
55665 + */
55666 +typedef union haintmsk_data {
55667 +       /** raw register data */
55668 +       uint32_t d32;
55669 +       /** register bits */
55670 +       struct {
55671 +               unsigned ch0:1;
55672 +               unsigned ch1:1;
55673 +               unsigned ch2:1;
55674 +               unsigned ch3:1;
55675 +               unsigned ch4:1;
55676 +               unsigned ch5:1;
55677 +               unsigned ch6:1;
55678 +               unsigned ch7:1;
55679 +               unsigned ch8:1;
55680 +               unsigned ch9:1;
55681 +               unsigned ch10:1;
55682 +               unsigned ch11:1;
55683 +               unsigned ch12:1;
55684 +               unsigned ch13:1;
55685 +               unsigned ch14:1;
55686 +               unsigned ch15:1;
55687 +               unsigned reserved:16;
55688 +       } b;
55689 +
55690 +       struct {
55691 +               unsigned chint:16;
55692 +               unsigned reserved:16;
55693 +       } b2;
55694 +} haintmsk_data_t;
55695 +
55696 +/**
55697 + * Host Channel Specific Registers. <i>500h-5FCh</i>
55698 + */
55699 +typedef struct dwc_otg_hc_regs {
55700 +       /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
55701 +       volatile uint32_t hcchar;
55702 +       /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
55703 +       volatile uint32_t hcsplt;
55704 +       /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
55705 +       volatile uint32_t hcint;
55706 +       /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
55707 +       volatile uint32_t hcintmsk;
55708 +       /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
55709 +       volatile uint32_t hctsiz;
55710 +       /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
55711 +       volatile uint32_t hcdma;
55712 +       volatile uint32_t reserved;
55713 +       /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
55714 +       volatile uint32_t hcdmab;
55715 +} dwc_otg_hc_regs_t;
55716 +
55717 +/**
55718 + * This union represents the bit fields in the Host Channel Characteristics
55719 + * Register. Read the register into the <i>d32</i> member then set/clear the
55720 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55721 + * hcchar register.
55722 + */
55723 +typedef union hcchar_data {
55724 +       /** raw register data */
55725 +       uint32_t d32;
55726 +
55727 +       /** register bits */
55728 +       struct {
55729 +               /** Maximum packet size in bytes */
55730 +               unsigned mps:11;
55731 +
55732 +               /** Endpoint number */
55733 +               unsigned epnum:4;
55734 +
55735 +               /** 0: OUT, 1: IN */
55736 +               unsigned epdir:1;
55737 +
55738 +               unsigned reserved:1;
55739 +
55740 +               /** 0: Full/high speed device, 1: Low speed device */
55741 +               unsigned lspddev:1;
55742 +
55743 +               /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
55744 +               unsigned eptype:2;
55745 +
55746 +               /** Packets per frame for periodic transfers. 0 is reserved. */
55747 +               unsigned multicnt:2;
55748 +
55749 +               /** Device address */
55750 +               unsigned devaddr:7;
55751 +
55752 +               /**
55753 +                * Frame to transmit periodic transaction.
55754 +                * 0: even, 1: odd
55755 +                */
55756 +               unsigned oddfrm:1;
55757 +
55758 +               /** Channel disable */
55759 +               unsigned chdis:1;
55760 +
55761 +               /** Channel enable */
55762 +               unsigned chen:1;
55763 +       } b;
55764 +} hcchar_data_t;
55765 +
55766 +typedef union hcsplt_data {
55767 +       /** raw register data */
55768 +       uint32_t d32;
55769 +
55770 +       /** register bits */
55771 +       struct {
55772 +               /** Port Address */
55773 +               unsigned prtaddr:7;
55774 +
55775 +               /** Hub Address */
55776 +               unsigned hubaddr:7;
55777 +
55778 +               /** Transaction Position */
55779 +               unsigned xactpos:2;
55780 +#define DWC_HCSPLIT_XACTPOS_MID 0
55781 +#define DWC_HCSPLIT_XACTPOS_END 1
55782 +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
55783 +#define DWC_HCSPLIT_XACTPOS_ALL 3
55784 +
55785 +               /** Do Complete Split */
55786 +               unsigned compsplt:1;
55787 +
55788 +               /** Reserved */
55789 +               unsigned reserved:14;
55790 +
55791 +               /** Split Enble */
55792 +               unsigned spltena:1;
55793 +       } b;
55794 +} hcsplt_data_t;
55795 +
55796 +/**
55797 + * This union represents the bit fields in the Host All Interrupt
55798 + * Register.
55799 + */
55800 +typedef union hcint_data {
55801 +       /** raw register data */
55802 +       uint32_t d32;
55803 +       /** register bits */
55804 +       struct {
55805 +               /** Transfer Complete */
55806 +               unsigned xfercomp:1;
55807 +               /** Channel Halted */
55808 +               unsigned chhltd:1;
55809 +               /** AHB Error */
55810 +               unsigned ahberr:1;
55811 +               /** STALL Response Received */
55812 +               unsigned stall:1;
55813 +               /** NAK Response Received */
55814 +               unsigned nak:1;
55815 +               /** ACK Response Received */
55816 +               unsigned ack:1;
55817 +               /** NYET Response Received */
55818 +               unsigned nyet:1;
55819 +               /** Transaction Err */
55820 +               unsigned xacterr:1;
55821 +               /** Babble Error */
55822 +               unsigned bblerr:1;
55823 +               /** Frame Overrun */
55824 +               unsigned frmovrun:1;
55825 +               /** Data Toggle Error */
55826 +               unsigned datatglerr:1;
55827 +               /** Buffer Not Available (only for DDMA mode) */
55828 +               unsigned bna:1;
55829 +               /** Exessive transaction error (only for DDMA mode) */
55830 +               unsigned xcs_xact:1;
55831 +               /** Frame List Rollover interrupt */
55832 +               unsigned frm_list_roll:1;
55833 +               /** Reserved */
55834 +               unsigned reserved14_31:18;
55835 +       } b;
55836 +} hcint_data_t;
55837 +
55838 +/**
55839 + * This union represents the bit fields in the Host Channel Interrupt Mask
55840 + * Register. Read the register into the <i>d32</i> member then set/clear the
55841 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55842 + * hcintmsk register.
55843 + */
55844 +typedef union hcintmsk_data {
55845 +       /** raw register data */
55846 +       uint32_t d32;
55847 +
55848 +       /** register bits */
55849 +       struct {
55850 +               unsigned xfercompl:1;
55851 +               unsigned chhltd:1;
55852 +               unsigned ahberr:1;
55853 +               unsigned stall:1;
55854 +               unsigned nak:1;
55855 +               unsigned ack:1;
55856 +               unsigned nyet:1;
55857 +               unsigned xacterr:1;
55858 +               unsigned bblerr:1;
55859 +               unsigned frmovrun:1;
55860 +               unsigned datatglerr:1;
55861 +               unsigned bna:1;
55862 +               unsigned xcs_xact:1;
55863 +               unsigned frm_list_roll:1;
55864 +               unsigned reserved14_31:18;
55865 +       } b;
55866 +} hcintmsk_data_t;
55867 +
55868 +/**
55869 + * This union represents the bit fields in the Host Channel Transfer Size
55870 + * Register. Read the register into the <i>d32</i> member then set/clear the
55871 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55872 + * hcchar register.
55873 + */
55874 +
55875 +typedef union hctsiz_data {
55876 +       /** raw register data */
55877 +       uint32_t d32;
55878 +
55879 +       /** register bits */
55880 +       struct {
55881 +               /** Total transfer size in bytes */
55882 +               unsigned xfersize:19;
55883 +
55884 +               /** Data packets to transfer */
55885 +               unsigned pktcnt:10;
55886 +
55887 +               /**
55888 +                * Packet ID for next data packet
55889 +                * 0: DATA0
55890 +                * 1: DATA2
55891 +                * 2: DATA1
55892 +                * 3: MDATA (non-Control), SETUP (Control)
55893 +                */
55894 +               unsigned pid:2;
55895 +#define DWC_HCTSIZ_DATA0 0
55896 +#define DWC_HCTSIZ_DATA1 2
55897 +#define DWC_HCTSIZ_DATA2 1
55898 +#define DWC_HCTSIZ_MDATA 3
55899 +#define DWC_HCTSIZ_SETUP 3
55900 +
55901 +               /** Do PING protocol when 1 */
55902 +               unsigned dopng:1;
55903 +       } b;
55904 +
55905 +       /** register bits */
55906 +       struct {
55907 +               /** Scheduling information */
55908 +               unsigned schinfo:8;
55909 +
55910 +               /** Number of transfer descriptors.
55911 +                * Max value:
55912 +                * 64 in general,
55913 +                * 256 only for HS isochronous endpoint.
55914 +                */
55915 +               unsigned ntd:8;
55916 +
55917 +               /** Data packets to transfer */
55918 +               unsigned reserved16_28:13;
55919 +
55920 +               /**
55921 +                * Packet ID for next data packet
55922 +                * 0: DATA0
55923 +                * 1: DATA2
55924 +                * 2: DATA1
55925 +                * 3: MDATA (non-Control)
55926 +                */
55927 +               unsigned pid:2;
55928 +
55929 +               /** Do PING protocol when 1 */
55930 +               unsigned dopng:1;
55931 +       } b_ddma;
55932 +} hctsiz_data_t;
55933 +
55934 +/**
55935 + * This union represents the bit fields in the Host DMA Address
55936 + * Register used in Descriptor DMA mode.
55937 + */
55938 +typedef union hcdma_data {
55939 +       /** raw register data */
55940 +       uint32_t d32;
55941 +       /** register bits */
55942 +       struct {
55943 +               unsigned reserved0_2:3;
55944 +               /** Current Transfer Descriptor. Not used for ISOC */
55945 +               unsigned ctd:8;
55946 +               /** Start Address of Descriptor List */
55947 +               unsigned dma_addr:21;
55948 +       } b;
55949 +} hcdma_data_t;
55950 +
55951 +/**
55952 + * This union represents the bit fields in the DMA Descriptor
55953 + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
55954 + * set/clear the bits using the <i>b</i>it elements.
55955 + */
55956 +typedef union host_dma_desc_sts {
55957 +       /** raw register data */
55958 +       uint32_t d32;
55959 +       /** quadlet bits */
55960 +
55961 +       /* for non-isochronous  */
55962 +       struct {
55963 +               /** Number of bytes */
55964 +               unsigned n_bytes:17;
55965 +               /** QTD offset to jump when Short Packet received - only for IN EPs */
55966 +               unsigned qtd_offset:6;
55967 +               /**
55968 +                * Set to request the core to jump to alternate QTD if
55969 +                * Short Packet received - only for IN EPs
55970 +                */
55971 +               unsigned a_qtd:1;
55972 +                /**
55973 +                 * Setup Packet bit. When set indicates that buffer contains
55974 +                 * setup packet.
55975 +                 */
55976 +               unsigned sup:1;
55977 +               /** Interrupt On Complete */
55978 +               unsigned ioc:1;
55979 +               /** End of List */
55980 +               unsigned eol:1;
55981 +               unsigned reserved27:1;
55982 +               /** Rx/Tx Status */
55983 +               unsigned sts:2;
55984 +#define DMA_DESC_STS_PKTERR    1
55985 +               unsigned reserved30:1;
55986 +               /** Active Bit */
55987 +               unsigned a:1;
55988 +       } b;
55989 +       /* for isochronous */
55990 +       struct {
55991 +               /** Number of bytes */
55992 +               unsigned n_bytes:12;
55993 +               unsigned reserved12_24:13;
55994 +               /** Interrupt On Complete */
55995 +               unsigned ioc:1;
55996 +               unsigned reserved26_27:2;
55997 +               /** Rx/Tx Status */
55998 +               unsigned sts:2;
55999 +               unsigned reserved30:1;
56000 +               /** Active Bit */
56001 +               unsigned a:1;
56002 +       } b_isoc;
56003 +} host_dma_desc_sts_t;
56004 +
56005 +#define        MAX_DMA_DESC_SIZE               131071
56006 +#define MAX_DMA_DESC_NUM_GENERIC       64
56007 +#define MAX_DMA_DESC_NUM_HS_ISOC       256
56008 +#define MAX_FRLIST_EN_NUM              64
56009 +/**
56010 + * Host-mode DMA Descriptor structure
56011 + *
56012 + * DMA Descriptor structure contains two quadlets:
56013 + * Status quadlet and Data buffer pointer.
56014 + */
56015 +typedef struct dwc_otg_host_dma_desc {
56016 +       /** DMA Descriptor status quadlet */
56017 +       host_dma_desc_sts_t status;
56018 +       /** DMA Descriptor data buffer pointer */
56019 +       uint32_t buf;
56020 +} dwc_otg_host_dma_desc_t;
56021 +
56022 +/** OTG Host Interface Structure.
56023 + *
56024 + * The OTG Host Interface Structure structure contains information
56025 + * needed to manage the DWC_otg controller acting in host mode. It
56026 + * represents the programming view of the host-specific aspects of the
56027 + * controller.
56028 + */
56029 +typedef struct dwc_otg_host_if {
56030 +       /** Host Global Registers starting at offset 400h.*/
56031 +       dwc_otg_host_global_regs_t *host_global_regs;
56032 +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
56033 +
56034 +       /** Host Port 0 Control and Status Register */
56035 +       volatile uint32_t *hprt0;
56036 +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
56037 +
56038 +       /** Host Channel Specific Registers at offsets 500h-5FCh. */
56039 +       dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
56040 +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
56041 +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
56042 +
56043 +       /* Host configuration information */
56044 +       /** Number of Host Channels (range: 1-16) */
56045 +       uint8_t num_host_channels;
56046 +       /** Periodic EPs supported (0: no, 1: yes) */
56047 +       uint8_t perio_eps_supported;
56048 +       /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
56049 +       uint16_t perio_tx_fifo_size;
56050 +
56051 +} dwc_otg_host_if_t;
56052 +
56053 +/**
56054 + * This union represents the bit fields in the Power and Clock Gating Control
56055 + * Register. Read the register into the <i>d32</i> member then set/clear the
56056 + * bits using the <i>b</i>it elements.
56057 + */
56058 +typedef union pcgcctl_data {
56059 +       /** raw register data */
56060 +       uint32_t d32;
56061 +
56062 +       /** register bits */
56063 +       struct {
56064 +               /** Stop Pclk */
56065 +               unsigned stoppclk:1;
56066 +               /** Gate Hclk */
56067 +               unsigned gatehclk:1;
56068 +               /** Power Clamp */
56069 +               unsigned pwrclmp:1;
56070 +               /** Reset Power Down Modules */
56071 +               unsigned rstpdwnmodule:1;
56072 +               /** Reserved */
56073 +               unsigned reserved:1;
56074 +               /** Enable Sleep Clock Gating (Enbl_L1Gating) */
56075 +               unsigned enbl_sleep_gating:1;
56076 +               /** PHY In Sleep (PhySleep) */
56077 +               unsigned phy_in_sleep:1;
56078 +               /** Deep Sleep*/
56079 +               unsigned deep_sleep:1;
56080 +               unsigned resetaftsusp:1;
56081 +               unsigned restoremode:1;
56082 +               unsigned enbl_extnd_hiber:1;
56083 +               unsigned extnd_hiber_pwrclmp:1;
56084 +               unsigned extnd_hiber_switch:1;
56085 +               unsigned ess_reg_restored:1;
56086 +               unsigned prt_clk_sel:2;
56087 +               unsigned port_power:1;
56088 +               unsigned max_xcvrselect:2;
56089 +               unsigned max_termsel:1;
56090 +               unsigned mac_dev_addr:7;
56091 +               unsigned p2hd_dev_enum_spd:2;
56092 +               unsigned p2hd_prt_spd:2;
56093 +               unsigned if_dev_mode:1;
56094 +       } b;
56095 +} pcgcctl_data_t;
56096 +
56097 +/**
56098 + * This union represents the bit fields in the Global Data FIFO Software
56099 + * Configuration Register. Read the register into the <i>d32</i> member then
56100 + * set/clear the bits using the <i>b</i>it elements.
56101 + */
56102 +typedef union gdfifocfg_data {
56103 +       /* raw register data */
56104 +       uint32_t d32;
56105 +       /** register bits */
56106 +       struct {
56107 +               /** OTG Data FIFO depth */
56108 +               unsigned gdfifocfg:16;
56109 +               /** Start address of EP info controller */
56110 +               unsigned epinfobase:16;
56111 +       } b;
56112 +} gdfifocfg_data_t;
56113 +
56114 +/**
56115 + * This union represents the bit fields in the Global Power Down Register
56116 + * Register. Read the register into the <i>d32</i> member then set/clear the
56117 + * bits using the <i>b</i>it elements.
56118 + */
56119 +typedef union gpwrdn_data {
56120 +       /* raw register data */
56121 +       uint32_t d32;
56122 +
56123 +       /** register bits */
56124 +       struct {
56125 +               /** PMU Interrupt Select */
56126 +               unsigned pmuintsel:1;
56127 +               /** PMU Active */
56128 +               unsigned pmuactv:1;
56129 +               /** Restore */
56130 +               unsigned restore:1;
56131 +               /** Power Down Clamp */
56132 +               unsigned pwrdnclmp:1;
56133 +               /** Power Down Reset */
56134 +               unsigned pwrdnrstn:1;
56135 +               /** Power Down Switch */
56136 +               unsigned pwrdnswtch:1;
56137 +               /** Disable VBUS */
56138 +               unsigned dis_vbus:1;
56139 +               /** Line State Change */
56140 +               unsigned lnstschng:1;
56141 +               /** Line state change mask */
56142 +               unsigned lnstchng_msk:1;
56143 +               /** Reset Detected */
56144 +               unsigned rst_det:1;
56145 +               /** Reset Detect mask */
56146 +               unsigned rst_det_msk:1;
56147 +               /** Disconnect Detected */
56148 +               unsigned disconn_det:1;
56149 +               /** Disconnect Detect mask */
56150 +               unsigned disconn_det_msk:1;
56151 +               /** Connect Detected*/
56152 +               unsigned connect_det:1;
56153 +               /** Connect Detected Mask*/
56154 +               unsigned connect_det_msk:1;
56155 +               /** SRP Detected */
56156 +               unsigned srp_det:1;
56157 +               /** SRP Detect mask */
56158 +               unsigned srp_det_msk:1;
56159 +               /** Status Change Interrupt */
56160 +               unsigned sts_chngint:1;
56161 +               /** Status Change Interrupt Mask */
56162 +               unsigned sts_chngint_msk:1;
56163 +               /** Line State */
56164 +               unsigned linestate:2;
56165 +               /** Indicates current mode(status of IDDIG signal) */
56166 +               unsigned idsts:1;
56167 +               /** B Session Valid signal status*/
56168 +               unsigned bsessvld:1;
56169 +               /** ADP Event Detected */
56170 +               unsigned adp_int:1;
56171 +               /** Multi Valued ID pin */
56172 +               unsigned mult_val_id_bc:5;
56173 +               /** Reserved 24_31 */
56174 +               unsigned reserved29_31:3;
56175 +       } b;
56176 +} gpwrdn_data_t;
56177 +
56178 +#endif
56179 --- /dev/null
56180 +++ b/drivers/usb/host/dwc_otg/test/Makefile
56181 @@ -0,0 +1,16 @@
56182 +
56183 +PERL=/usr/bin/perl
56184 +PL_TESTS=test_sysfs.pl test_mod_param.pl
56185 +
56186 +.PHONY : test
56187 +test : perl_tests
56188 +
56189 +perl_tests :
56190 +       @echo
56191 +       @echo Running perl tests
56192 +       @for test in $(PL_TESTS); do \
56193 +         if $(PERL) ./$$test ; then \
56194 +           echo "=======> $$test, PASSED" ; \
56195 +         else echo "=======> $$test, FAILED" ; \
56196 +         fi \
56197 +       done
56198 --- /dev/null
56199 +++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56200 @@ -0,0 +1,337 @@
56201 +package dwc_otg_test;
56202 +
56203 +use strict;
56204 +use Exporter ();
56205 +
56206 +use vars qw(@ISA @EXPORT
56207 +$sysfsdir $paramdir $errors $params
56208 +);
56209 +
56210 +@ISA = qw(Exporter);
56211 +
56212 +#
56213 +# Globals
56214 +#
56215 +$sysfsdir = "/sys/devices/lm0";
56216 +$paramdir = "/sys/module/dwc_otg";
56217 +$errors = 0;
56218 +
56219 +$params = [
56220 +          {
56221 +           NAME => "otg_cap",
56222 +           DEFAULT => 0,
56223 +           ENUM => [],
56224 +           LOW => 0,
56225 +           HIGH => 2
56226 +          },
56227 +          {
56228 +           NAME => "dma_enable",
56229 +           DEFAULT => 0,
56230 +           ENUM => [],
56231 +           LOW => 0,
56232 +           HIGH => 1
56233 +          },
56234 +          {
56235 +           NAME => "dma_burst_size",
56236 +           DEFAULT => 32,
56237 +           ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
56238 +           LOW => 1,
56239 +           HIGH => 256
56240 +          },
56241 +          {
56242 +           NAME => "host_speed",
56243 +           DEFAULT => 0,
56244 +           ENUM => [],
56245 +           LOW => 0,
56246 +           HIGH => 1
56247 +          },
56248 +          {
56249 +           NAME => "host_support_fs_ls_low_power",
56250 +           DEFAULT => 0,
56251 +           ENUM => [],
56252 +           LOW => 0,
56253 +           HIGH => 1
56254 +          },
56255 +          {
56256 +           NAME => "host_ls_low_power_phy_clk",
56257 +           DEFAULT => 0,
56258 +           ENUM => [],
56259 +           LOW => 0,
56260 +           HIGH => 1
56261 +          },
56262 +          {
56263 +           NAME => "dev_speed",
56264 +           DEFAULT => 0,
56265 +           ENUM => [],
56266 +           LOW => 0,
56267 +           HIGH => 1
56268 +          },
56269 +          {
56270 +           NAME => "enable_dynamic_fifo",
56271 +           DEFAULT => 1,
56272 +           ENUM => [],
56273 +           LOW => 0,
56274 +           HIGH => 1
56275 +          },
56276 +          {
56277 +           NAME => "data_fifo_size",
56278 +           DEFAULT => 8192,
56279 +           ENUM => [],
56280 +           LOW => 32,
56281 +           HIGH => 32768
56282 +          },
56283 +          {
56284 +           NAME => "dev_rx_fifo_size",
56285 +           DEFAULT => 1064,
56286 +           ENUM => [],
56287 +           LOW => 16,
56288 +           HIGH => 32768
56289 +          },
56290 +          {
56291 +           NAME => "dev_nperio_tx_fifo_size",
56292 +           DEFAULT => 1024,
56293 +           ENUM => [],
56294 +           LOW => 16,
56295 +           HIGH => 32768
56296 +          },
56297 +          {
56298 +           NAME => "dev_perio_tx_fifo_size_1",
56299 +           DEFAULT => 256,
56300 +           ENUM => [],
56301 +           LOW => 4,
56302 +           HIGH => 768
56303 +          },
56304 +          {
56305 +           NAME => "dev_perio_tx_fifo_size_2",
56306 +           DEFAULT => 256,
56307 +           ENUM => [],
56308 +           LOW => 4,
56309 +           HIGH => 768
56310 +          },
56311 +          {
56312 +           NAME => "dev_perio_tx_fifo_size_3",
56313 +           DEFAULT => 256,
56314 +           ENUM => [],
56315 +           LOW => 4,
56316 +           HIGH => 768
56317 +          },
56318 +          {
56319 +           NAME => "dev_perio_tx_fifo_size_4",
56320 +           DEFAULT => 256,
56321 +           ENUM => [],
56322 +           LOW => 4,
56323 +           HIGH => 768
56324 +          },
56325 +          {
56326 +           NAME => "dev_perio_tx_fifo_size_5",
56327 +           DEFAULT => 256,
56328 +           ENUM => [],
56329 +           LOW => 4,
56330 +           HIGH => 768
56331 +          },
56332 +          {
56333 +           NAME => "dev_perio_tx_fifo_size_6",
56334 +           DEFAULT => 256,
56335 +           ENUM => [],
56336 +           LOW => 4,
56337 +           HIGH => 768
56338 +          },
56339 +          {
56340 +           NAME => "dev_perio_tx_fifo_size_7",
56341 +           DEFAULT => 256,
56342 +           ENUM => [],
56343 +           LOW => 4,
56344 +           HIGH => 768
56345 +          },
56346 +          {
56347 +           NAME => "dev_perio_tx_fifo_size_8",
56348 +           DEFAULT => 256,
56349 +           ENUM => [],
56350 +           LOW => 4,
56351 +           HIGH => 768
56352 +          },
56353 +          {
56354 +           NAME => "dev_perio_tx_fifo_size_9",
56355 +           DEFAULT => 256,
56356 +           ENUM => [],
56357 +           LOW => 4,
56358 +           HIGH => 768
56359 +          },
56360 +          {
56361 +           NAME => "dev_perio_tx_fifo_size_10",
56362 +           DEFAULT => 256,
56363 +           ENUM => [],
56364 +           LOW => 4,
56365 +           HIGH => 768
56366 +          },
56367 +          {
56368 +           NAME => "dev_perio_tx_fifo_size_11",
56369 +           DEFAULT => 256,
56370 +           ENUM => [],
56371 +           LOW => 4,
56372 +           HIGH => 768
56373 +          },
56374 +          {
56375 +           NAME => "dev_perio_tx_fifo_size_12",
56376 +           DEFAULT => 256,
56377 +           ENUM => [],
56378 +           LOW => 4,
56379 +           HIGH => 768
56380 +          },
56381 +          {
56382 +           NAME => "dev_perio_tx_fifo_size_13",
56383 +           DEFAULT => 256,
56384 +           ENUM => [],
56385 +           LOW => 4,
56386 +           HIGH => 768
56387 +          },
56388 +          {
56389 +           NAME => "dev_perio_tx_fifo_size_14",
56390 +           DEFAULT => 256,
56391 +           ENUM => [],
56392 +           LOW => 4,
56393 +           HIGH => 768
56394 +          },
56395 +          {
56396 +           NAME => "dev_perio_tx_fifo_size_15",
56397 +           DEFAULT => 256,
56398 +           ENUM => [],
56399 +           LOW => 4,
56400 +           HIGH => 768
56401 +          },
56402 +          {
56403 +           NAME => "host_rx_fifo_size",
56404 +           DEFAULT => 1024,
56405 +           ENUM => [],
56406 +           LOW => 16,
56407 +           HIGH => 32768
56408 +          },
56409 +          {
56410 +           NAME => "host_nperio_tx_fifo_size",
56411 +           DEFAULT => 1024,
56412 +           ENUM => [],
56413 +           LOW => 16,
56414 +           HIGH => 32768
56415 +          },
56416 +          {
56417 +           NAME => "host_perio_tx_fifo_size",
56418 +           DEFAULT => 1024,
56419 +           ENUM => [],
56420 +           LOW => 16,
56421 +           HIGH => 32768
56422 +          },
56423 +          {
56424 +           NAME => "max_transfer_size",
56425 +           DEFAULT => 65535,
56426 +           ENUM => [],
56427 +           LOW => 2047,
56428 +           HIGH => 65535
56429 +          },
56430 +          {
56431 +           NAME => "max_packet_count",
56432 +           DEFAULT => 511,
56433 +           ENUM => [],
56434 +           LOW => 15,
56435 +           HIGH => 511
56436 +          },
56437 +          {
56438 +           NAME => "host_channels",
56439 +           DEFAULT => 12,
56440 +           ENUM => [],
56441 +           LOW => 1,
56442 +           HIGH => 16
56443 +          },
56444 +          {
56445 +           NAME => "dev_endpoints",
56446 +           DEFAULT => 6,
56447 +           ENUM => [],
56448 +           LOW => 1,
56449 +           HIGH => 15
56450 +          },
56451 +          {
56452 +           NAME => "phy_type",
56453 +           DEFAULT => 1,
56454 +           ENUM => [],
56455 +           LOW => 0,
56456 +           HIGH => 2
56457 +          },
56458 +          {
56459 +           NAME => "phy_utmi_width",
56460 +           DEFAULT => 16,
56461 +           ENUM => [8, 16],
56462 +           LOW => 8,
56463 +           HIGH => 16
56464 +          },
56465 +          {
56466 +           NAME => "phy_ulpi_ddr",
56467 +           DEFAULT => 0,
56468 +           ENUM => [],
56469 +           LOW => 0,
56470 +           HIGH => 1
56471 +          },
56472 +         ];
56473 +
56474 +
56475 +#
56476 +#
56477 +sub check_arch {
56478 +  $_ = `uname -m`;
56479 +  chomp;
56480 +  unless (m/armv4tl/) {
56481 +    warn "# \n# Can't execute on $_.  Run on integrator platform.\n# \n";
56482 +    return 0;
56483 +  }
56484 +  return 1;
56485 +}
56486 +
56487 +#
56488 +#
56489 +sub load_module {
56490 +  my $params = shift;
56491 +  print "\nRemoving Module\n";
56492 +  system "rmmod dwc_otg";
56493 +  print "Loading Module\n";
56494 +  if ($params ne "") {
56495 +    print "Module Parameters: $params\n";
56496 +  }
56497 +  if (system("modprobe dwc_otg $params")) {
56498 +    warn "Unable to load module\n";
56499 +    return 0;
56500 +  }
56501 +  return 1;
56502 +}
56503 +
56504 +#
56505 +#
56506 +sub test_status {
56507 +  my $arg = shift;
56508 +
56509 +  print "\n";
56510 +
56511 +  if (defined $arg) {
56512 +    warn "WARNING: $arg\n";
56513 +  }
56514 +
56515 +  if ($errors > 0) {
56516 +    warn "TEST FAILED with $errors errors\n";
56517 +    return 0;
56518 +  } else {
56519 +    print "TEST PASSED\n";
56520 +    return 0 if (defined $arg);
56521 +  }
56522 +  return 1;
56523 +}
56524 +
56525 +#
56526 +#
56527 +@EXPORT = qw(
56528 +$sysfsdir
56529 +$paramdir
56530 +$params
56531 +$errors
56532 +check_arch
56533 +load_module
56534 +test_status
56535 +);
56536 +
56537 +1;
56538 --- /dev/null
56539 +++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56540 @@ -0,0 +1,133 @@
56541 +#!/usr/bin/perl -w
56542 +#
56543 +# Run this program on the integrator.
56544 +#
56545 +# - Tests module parameter default values.
56546 +# - Tests setting of valid module parameter values via modprobe.
56547 +# - Tests invalid module parameter values.
56548 +# -----------------------------------------------------------------------------
56549 +use strict;
56550 +use dwc_otg_test;
56551 +
56552 +check_arch() or die;
56553 +
56554 +#
56555 +#
56556 +sub test {
56557 +  my ($param,$expected) = @_;
56558 +  my $value = get($param);
56559 +
56560 +  if ($value == $expected) {
56561 +    print "$param = $value, okay\n";
56562 +  }
56563 +
56564 +  else {
56565 +    warn "ERROR: value of $param != $expected, $value\n";
56566 +    $errors ++;
56567 +  }
56568 +}
56569 +
56570 +#
56571 +#
56572 +sub get {
56573 +  my $param = shift;
56574 +  my $tmp = `cat $paramdir/$param`;
56575 +  chomp $tmp;
56576 +  return $tmp;
56577 +}
56578 +
56579 +#
56580 +#
56581 +sub test_main {
56582 +
56583 +  print "\nTesting Module Parameters\n";
56584 +
56585 +  load_module("") or die;
56586 +
56587 +  # Test initial values
56588 +  print "\nTesting Default Values\n";
56589 +  foreach (@{$params}) {
56590 +    test ($_->{NAME}, $_->{DEFAULT});
56591 +  }
56592 +
56593 +  # Test low value
56594 +  print "\nTesting Low Value\n";
56595 +  my $cmd_params = "";
56596 +  foreach (@{$params}) {
56597 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
56598 +  }
56599 +  load_module($cmd_params) or die;
56600 +
56601 +  foreach (@{$params}) {
56602 +    test ($_->{NAME}, $_->{LOW});
56603 +  }
56604 +
56605 +  # Test high value
56606 +  print "\nTesting High Value\n";
56607 +  $cmd_params = "";
56608 +  foreach (@{$params}) {
56609 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
56610 +  }
56611 +  load_module($cmd_params) or die;
56612 +
56613 +  foreach (@{$params}) {
56614 +    test ($_->{NAME}, $_->{HIGH});
56615 +  }
56616 +
56617 +  # Test Enum
56618 +  print "\nTesting Enumerated\n";
56619 +  foreach (@{$params}) {
56620 +    if (defined $_->{ENUM}) {
56621 +      my $value;
56622 +      foreach $value (@{$_->{ENUM}}) {
56623 +       $cmd_params = "$_->{NAME}=$value";
56624 +       load_module($cmd_params) or die;
56625 +       test ($_->{NAME}, $value);
56626 +      }
56627 +    }
56628 +  }
56629 +
56630 +  # Test Invalid Values
56631 +  print "\nTesting Invalid Values\n";
56632 +  $cmd_params = "";
56633 +  foreach (@{$params}) {
56634 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
56635 +  }
56636 +  load_module($cmd_params) or die;
56637 +
56638 +  foreach (@{$params}) {
56639 +    test ($_->{NAME}, $_->{DEFAULT});
56640 +  }
56641 +
56642 +  $cmd_params = "";
56643 +  foreach (@{$params}) {
56644 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
56645 +  }
56646 +  load_module($cmd_params) or die;
56647 +
56648 +  foreach (@{$params}) {
56649 +    test ($_->{NAME}, $_->{DEFAULT});
56650 +  }
56651 +
56652 +  print "\nTesting Enumerated\n";
56653 +  foreach (@{$params}) {
56654 +    if (defined $_->{ENUM}) {
56655 +      my $value;
56656 +      foreach $value (@{$_->{ENUM}}) {
56657 +       $value = $value + 1;
56658 +       $cmd_params = "$_->{NAME}=$value";
56659 +       load_module($cmd_params) or die;
56660 +       test ($_->{NAME}, $_->{DEFAULT});
56661 +       $value = $value - 2;
56662 +       $cmd_params = "$_->{NAME}=$value";
56663 +       load_module($cmd_params) or die;
56664 +       test ($_->{NAME}, $_->{DEFAULT});
56665 +      }
56666 +    }
56667 +  }
56668 +
56669 +  test_status() or die;
56670 +}
56671 +
56672 +test_main();
56673 +0;
56674 --- /dev/null
56675 +++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
56676 @@ -0,0 +1,193 @@
56677 +#!/usr/bin/perl -w
56678 +#
56679 +# Run this program on the integrator
56680 +# - Tests select sysfs attributes.
56681 +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
56682 +# -----------------------------------------------------------------------------
56683 +use strict;
56684 +use dwc_otg_test;
56685 +
56686 +check_arch() or die;
56687 +
56688 +#
56689 +#
56690 +sub test {
56691 +  my ($attr,$expected) = @_;
56692 +  my $string = get($attr);
56693 +
56694 +  if ($string eq $expected) {
56695 +    printf("$attr = $string, okay\n");
56696 +  }
56697 +  else {
56698 +    warn "ERROR: value of $attr != $expected, $string\n";
56699 +    $errors ++;
56700 +  }
56701 +}
56702 +
56703 +#
56704 +#
56705 +sub set {
56706 +  my ($reg, $value) = @_;
56707 +  system "echo $value > $sysfsdir/$reg";
56708 +}
56709 +
56710 +#
56711 +#
56712 +sub get {
56713 +  my $attr = shift;
56714 +  my $string = `cat $sysfsdir/$attr`;
56715 +  chomp $string;
56716 +  if ($string =~ m/\s\=\s/) {
56717 +    my $tmp;
56718 +    ($tmp, $string) = split /\s=\s/, $string;
56719 +  }
56720 +  return $string;
56721 +}
56722 +
56723 +#
56724 +#
56725 +sub test_main {
56726 +  print("\nTesting Sysfs Attributes\n");
56727 +
56728 +  load_module("") or die;
56729 +
56730 +  # Test initial values of regoffset/regvalue/guid/gsnpsid
56731 +  print("\nTesting Default Values\n");
56732 +
56733 +  test("regoffset", "0xffffffff");
56734 +  test("regvalue", "invalid offset");
56735 +  test("guid", "0x12345678");  # this will fail if it has been changed
56736 +  test("gsnpsid", "0x4f54200a");
56737 +
56738 +  # Test operation of regoffset/regvalue
56739 +  print("\nTesting regoffset\n");
56740 +  set('regoffset', '5a5a5a5a');
56741 +  test("regoffset", "0xffffffff");
56742 +
56743 +  set('regoffset', '0');
56744 +  test("regoffset", "0x00000000");
56745 +
56746 +  set('regoffset', '40000');
56747 +  test("regoffset", "0x00000000");
56748 +
56749 +  set('regoffset', '3ffff');
56750 +  test("regoffset", "0x0003ffff");
56751 +
56752 +  set('regoffset', '1');
56753 +  test("regoffset", "0x00000001");
56754 +
56755 +  print("\nTesting regvalue\n");
56756 +  set('regoffset', '3c');
56757 +  test("regvalue", "0x12345678");
56758 +  set('regvalue', '5a5a5a5a');
56759 +  test("regvalue", "0x5a5a5a5a");
56760 +  set('regvalue','a5a5a5a5');
56761 +  test("regvalue", "0xa5a5a5a5");
56762 +  set('guid','12345678');
56763 +
56764 +  # Test HNP Capable
56765 +  print("\nTesting HNP Capable bit\n");
56766 +  set('hnpcapable', '1');
56767 +  test("hnpcapable", "0x1");
56768 +  set('hnpcapable','0');
56769 +  test("hnpcapable", "0x0");
56770 +
56771 +  set('regoffset','0c');
56772 +
56773 +  my $old = get('gusbcfg');
56774 +  print("setting hnpcapable\n");
56775 +  set('hnpcapable', '1');
56776 +  test("hnpcapable", "0x1");
56777 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
56778 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
56779 +
56780 +  $old = get('gusbcfg');
56781 +  print("clearing hnpcapable\n");
56782 +  set('hnpcapable', '0');
56783 +  test("hnpcapable", "0x0");
56784 +  test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56785 +  test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56786 +
56787 +  # Test SRP Capable
56788 +  print("\nTesting SRP Capable bit\n");
56789 +  set('srpcapable', '1');
56790 +  test("srpcapable", "0x1");
56791 +  set('srpcapable','0');
56792 +  test("srpcapable", "0x0");
56793 +
56794 +  set('regoffset','0c');
56795 +
56796 +  $old = get('gusbcfg');
56797 +  print("setting srpcapable\n");
56798 +  set('srpcapable', '1');
56799 +  test("srpcapable", "0x1");
56800 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
56801 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
56802 +
56803 +  $old = get('gusbcfg');
56804 +  print("clearing srpcapable\n");
56805 +  set('srpcapable', '0');
56806 +  test("srpcapable", "0x0");
56807 +  test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
56808 +  test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
56809 +
56810 +  # Test GGPIO
56811 +  print("\nTesting GGPIO\n");
56812 +  set('ggpio','5a5a5a5a');
56813 +  test('ggpio','0x5a5a0000');
56814 +  set('ggpio','a5a5a5a5');
56815 +  test('ggpio','0xa5a50000');
56816 +  set('ggpio','11110000');
56817 +  test('ggpio','0x11110000');
56818 +  set('ggpio','00001111');
56819 +  test('ggpio','0x00000000');
56820 +
56821 +  # Test DEVSPEED
56822 +  print("\nTesting DEVSPEED\n");
56823 +  set('regoffset','800');
56824 +  $old = get('regvalue');
56825 +  set('devspeed','0');
56826 +  test('devspeed','0x0');
56827 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
56828 +  set('devspeed','1');
56829 +  test('devspeed','0x1');
56830 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
56831 +  set('devspeed','2');
56832 +  test('devspeed','0x2');
56833 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
56834 +  set('devspeed','3');
56835 +  test('devspeed','0x3');
56836 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
56837 +  set('devspeed','4');
56838 +  test('devspeed','0x0');
56839 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
56840 +  set('devspeed','5');
56841 +  test('devspeed','0x1');
56842 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
56843 +
56844 +
56845 +  #  mode      Returns the current mode:0 for device mode1 for host mode       Read
56846 +  #  hnp       Initiate the Host Negotiation Protocol.  Read returns the status.       Read/Write
56847 +  #  srp       Initiate the Session Request Protocol.  Read returns the status.        Read/Write
56848 +  #  buspower  Get or Set the Power State of the bus (0 - Off or 1 - On)       Read/Write
56849 +  #  bussuspend        Suspend the USB bus.    Read/Write
56850 +  #  busconnected      Get the connection status of the bus    Read
56851 +
56852 +  #  gotgctl   Get or set the Core Control Status Register.    Read/Write
56853 +  ##  gusbcfg  Get or set the Core USB Configuration Register  Read/Write
56854 +  #  grxfsiz   Get or set the Receive FIFO Size Register       Read/Write
56855 +  #  gnptxfsiz Get or set the non-periodic Transmit Size Register      Read/Write
56856 +  #  gpvndctl  Get or set the PHY Vendor Control Register      Read/Write
56857 +  ##  ggpio    Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
56858 +  ##  guid     Get or set the value of the User ID Register    Read/Write
56859 +  ##  gsnpsid  Get the value of the Synopsys ID Regester       Read
56860 +  ##  devspeed Get or set the device speed setting in the DCFG register        Read/Write
56861 +  #  enumspeed Gets the device enumeration Speed.      Read
56862 +  #  hptxfsiz  Get the value of the Host Periodic Transmit FIFO        Read
56863 +  #  hprt0     Get or Set the value in the Host Port Control and Status Register       Read/Write
56864 +
56865 +  test_status("TEST NYI") or die;
56866 +}
56867 +
56868 +test_main();
56869 +0;