0bc5bce41d6f310cef81cf6c490856111d24b15d
[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 diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
141 index d7be717..f48b630 100644
142 --- a/drivers/usb/Makefile
143 +++ b/drivers/usb/Makefile
144 @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_U132_HCD)    += host/
145  obj-$(CONFIG_USB_R8A66597_HCD) += host/
146  obj-$(CONFIG_USB_HWA_HCD)      += host/
147  obj-$(CONFIG_USB_ISP1760_HCD)  += host/
148 +obj-$(CONFIG_USB_DWCOTG)       += host/
149  obj-$(CONFIG_USB_IMX21_HCD)    += host/
150  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += host/
151  obj-$(CONFIG_USB_FUSBH200_HCD) += host/
152 diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
153 index 358ca8d..abaac7c 100644
154 --- a/drivers/usb/core/generic.c
155 +++ b/drivers/usb/core/generic.c
156 @@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_device *udev)
157                 dev_warn(&udev->dev,
158                         "no configuration chosen from %d choice%s\n",
159                         num_configs, plural(num_configs));
160 +               dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
161         }
162         return i;
163  }
164 diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
165 index f7b7713..5423d18 100644
166 --- a/drivers/usb/core/message.c
167 +++ b/drivers/usb/core/message.c
168 @@ -1889,6 +1889,85 @@ free_interfaces:
169         if (cp->string == NULL &&
170                         !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
171                 cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
172 +/* Uncomment this define to enable the HS Electrical Test support */
173 +#define DWC_HS_ELECT_TST 1
174 +#ifdef DWC_HS_ELECT_TST
175 +               /* Here we implement the HS Electrical Test support. The
176 +                * tester uses a vendor ID of 0x1A0A to indicate we should
177 +                * run a special test sequence. The product ID tells us
178 +                * which sequence to run. We invoke the test sequence by
179 +                * sending a non-standard SetFeature command to our root
180 +                * hub port. Our dwc_otg_hcd_hub_control() routine will
181 +                * recognize the command and perform the desired test
182 +                * sequence.
183 +                */
184 +               if (dev->descriptor.idVendor == 0x1A0A) {
185 +                       /* HSOTG Electrical Test */
186 +                       dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
187 +
188 +                       if (dev->bus && dev->bus->root_hub) {
189 +                               struct usb_device *hdev = dev->bus->root_hub;
190 +                               dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
191 +
192 +                               switch (dev->descriptor.idProduct) {
193 +                               case 0x0101:    /* TEST_SE0_NAK */
194 +                                       dev_warn(&dev->dev, "TEST_SE0_NAK\n");
195 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
196 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
197 +                                                       USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
198 +                                       break;
199 +
200 +                               case 0x0102:    /* TEST_J */
201 +                                       dev_warn(&dev->dev, "TEST_J\n");
202 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
203 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
204 +                                                       USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
205 +                                       break;
206 +
207 +                               case 0x0103:    /* TEST_K */
208 +                                       dev_warn(&dev->dev, "TEST_K\n");
209 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
210 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
211 +                                                       USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
212 +                                       break;
213 +
214 +                               case 0x0104:    /* TEST_PACKET */
215 +                                       dev_warn(&dev->dev, "TEST_PACKET\n");
216 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
217 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
218 +                                                       USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
219 +                                       break;
220 +
221 +                               case 0x0105:    /* TEST_FORCE_ENABLE */
222 +                                       dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
223 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
224 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
225 +                                                       USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
226 +                                       break;
227 +
228 +                               case 0x0106:    /* HS_HOST_PORT_SUSPEND_RESUME */
229 +                                       dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
230 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
231 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
232 +                                                       USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
233 +                                       break;
234 +
235 +                               case 0x0107:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
236 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
237 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
238 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
239 +                                                       USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
240 +                                       break;
241 +
242 +                               case 0x0108:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
243 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
244 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
245 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
246 +                                                       USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
247 +                               }
248 +                       }
249 +               }
250 +#endif /* DWC_HS_ELECT_TST */
251  
252         /* Now that the interfaces are installed, re-enable LPM. */
253         usb_unlocked_enable_lpm(dev);
254 diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
255 index a6315ab..165dd53 100644
256 --- a/drivers/usb/core/otg_whitelist.h
257 +++ b/drivers/usb/core/otg_whitelist.h
258 @@ -19,33 +19,82 @@
259  static struct usb_device_id whitelist_table [] = {
260  
261  /* hubs are optional in OTG, but very handy ... */
262 +#define CERT_WITHOUT_HUBS
263 +#if defined(CERT_WITHOUT_HUBS)
264 +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
265 +#else
266  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
267  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
268 +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
269 +#endif
270  
271  #ifdef CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
272  /* FIXME actually, printers are NOT supposed to use device classes;
273   * they're supposed to use interface classes...
274   */
275 -{ USB_DEVICE_INFO(7, 1, 1) },
276 -{ USB_DEVICE_INFO(7, 1, 2) },
277 -{ USB_DEVICE_INFO(7, 1, 3) },
278 +//{ USB_DEVICE_INFO(7, 1, 1) },
279 +//{ USB_DEVICE_INFO(7, 1, 2) },
280 +//{ USB_DEVICE_INFO(7, 1, 3) },
281  #endif
282  
283  #ifdef CONFIG_USB_NET_CDCETHER
284  /* Linux-USB CDC Ethernet gadget */
285 -{ USB_DEVICE(0x0525, 0xa4a1), },
286 +//{ USB_DEVICE(0x0525, 0xa4a1), },
287  /* Linux-USB CDC Ethernet + RNDIS gadget */
288 -{ USB_DEVICE(0x0525, 0xa4a2), },
289 +//{ USB_DEVICE(0x0525, 0xa4a2), },
290  #endif
291  
292  #if    defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
293  /* gadget zero, for testing */
294 -{ USB_DEVICE(0x0525, 0xa4a0), },
295 +//{ USB_DEVICE(0x0525, 0xa4a0), },
296  #endif
297  
298 +/* OPT Tester */
299 +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
300 +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
301 +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
302 +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
303 +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
304 +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */
305 +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
306 +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
307 +
308 +/* Sony cameras */
309 +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
310 +
311 +/* Memory Devices */
312 +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
313 +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
314 +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
315 +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */
316 +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
317 +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
318 +
319 +/* HP Printers */
320 +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
321 +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
322 +
323 +/* Speakers */
324 +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
325 +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
326 +
327  { }    /* Terminating entry */
328  };
329  
330 +static inline void report_errors(struct usb_device *dev)
331 +{
332 +       /* OTG MESSAGE: report errors here, customize to match your product */
333 +       dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
334 +                le16_to_cpu(dev->descriptor.idVendor),
335 +                le16_to_cpu(dev->descriptor.idProduct));
336 +        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
337 +                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
338 +        } else {
339 +                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
340 +        }
341 +}
342 +
343 +
344  static int is_targeted(struct usb_device *dev)
345  {
346         struct usb_device_id    *id = whitelist_table;
347 @@ -95,16 +144,57 @@ static int is_targeted(struct usb_device *dev)
348                         continue;
349  
350                 return 1;
351 -       }
352 +               /* NOTE: can't use usb_match_id() since interface caches
353 +                * aren't set up yet. this is cut/paste from that code.
354 +                */
355 +               for (id = whitelist_table; id->match_flags; id++) {
356 +#ifdef DEBUG
357 +                       dev_dbg(&dev->dev,
358 +                               "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
359 +                               id->idVendor,
360 +                               id->idProduct,
361 +                               id->bDeviceClass,
362 +                               id->bDeviceSubClass,
363 +                               id->bDeviceProtocol);
364 +#endif
365  
366 -       /* add other match criteria here ... */
367 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
368 +                           id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
369 +                               continue;
370  
371 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
372 +                           id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
373 +                               continue;
374  
375 -       /* OTG MESSAGE: report errors here, customize to match your product */
376 -       dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
377 -               le16_to_cpu(dev->descriptor.idVendor),
378 -               le16_to_cpu(dev->descriptor.idProduct));
379 +                       /* No need to test id->bcdDevice_lo != 0, since 0 is never
380 +                          greater than any unsigned number. */
381 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
382 +                           (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
383 +                               continue;
384 +
385 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
386 +                           (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
387 +                               continue;
388 +
389 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
390 +                           (id->bDeviceClass != dev->descriptor.bDeviceClass))
391 +                               continue;
392 +
393 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
394 +                           (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
395 +                               continue;
396 +
397 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
398 +                           (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
399 +                               continue;
400 +
401 +                       return 1;
402 +               }
403 +       }
404 +
405 +       /* add other match criteria here ... */
406  
407 +       report_errors(dev);
408         return 0;
409  }
410  
411 diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
412 new file mode 100644
413 index 0000000..a896d73
414 --- /dev/null
415 +++ b/drivers/usb/gadget/file_storage.c
416 @@ -0,0 +1,3676 @@
417 +/*
418 + * file_storage.c -- File-backed USB Storage Gadget, for USB development
419 + *
420 + * Copyright (C) 2003-2008 Alan Stern
421 + * All rights reserved.
422 + *
423 + * Redistribution and use in source and binary forms, with or without
424 + * modification, are permitted provided that the following conditions
425 + * are met:
426 + * 1. Redistributions of source code must retain the above copyright
427 + *    notice, this list of conditions, and the following disclaimer,
428 + *    without modification.
429 + * 2. Redistributions in binary form must reproduce the above copyright
430 + *    notice, this list of conditions and the following disclaimer in the
431 + *    documentation and/or other materials provided with the distribution.
432 + * 3. The names of the above-listed copyright holders may not be used
433 + *    to endorse or promote products derived from this software without
434 + *    specific prior written permission.
435 + *
436 + * ALTERNATIVELY, this software may be distributed under the terms of the
437 + * GNU General Public License ("GPL") as published by the Free Software
438 + * Foundation, either version 2 of that License or (at your option) any
439 + * later version.
440 + *
441 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
442 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
443 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
444 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
445 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
446 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
447 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
448 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
449 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
450 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
451 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
452 + */
453 +
454 +
455 +/*
456 + * The File-backed Storage Gadget acts as a USB Mass Storage device,
457 + * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
458 + * to providing an example of a genuinely useful gadget driver for a USB
459 + * device, it also illustrates a technique of double-buffering for increased
460 + * throughput.  Last but not least, it gives an easy way to probe the
461 + * behavior of the Mass Storage drivers in a USB host.
462 + *
463 + * Backing storage is provided by a regular file or a block device, specified
464 + * by the "file" module parameter.  Access can be limited to read-only by
465 + * setting the optional "ro" module parameter.  (For CD-ROM emulation,
466 + * access is always read-only.)  The gadget will indicate that it has
467 + * removable media if the optional "removable" module parameter is set.
468 + *
469 + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
470 + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
471 + * by the optional "transport" module parameter.  It also supports the
472 + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
473 + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
474 + * the optional "protocol" module parameter.  In addition, the default
475 + * Vendor ID, Product ID, release number and serial number can be overridden.
476 + *
477 + * There is support for multiple logical units (LUNs), each of which has
478 + * its own backing file.  The number of LUNs can be set using the optional
479 + * "luns" module parameter (anywhere from 1 to 8), and the corresponding
480 + * files are specified using comma-separated lists for "file" and "ro".
481 + * The default number of LUNs is taken from the number of "file" elements;
482 + * it is 1 if "file" is not given.  If "removable" is not set then a backing
483 + * file must be specified for each LUN.  If it is set, then an unspecified
484 + * or empty backing filename means the LUN's medium is not loaded.  Ideally
485 + * each LUN would be settable independently as a disk drive or a CD-ROM
486 + * drive, but currently all LUNs have to be the same type.  The CD-ROM
487 + * emulation includes a single data track and no audio tracks; hence there
488 + * need be only one backing file per LUN.
489 + *
490 + * Requirements are modest; only a bulk-in and a bulk-out endpoint are
491 + * needed (an interrupt-out endpoint is also needed for CBI).  The memory
492 + * requirement amounts to two 16K buffers, size configurable by a parameter.
493 + * Support is included for both full-speed and high-speed operation.
494 + *
495 + * Note that the driver is slightly non-portable in that it assumes a
496 + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
497 + * interrupt-in endpoints.  With most device controllers this isn't an
498 + * issue, but there may be some with hardware restrictions that prevent
499 + * a buffer from being used by more than one endpoint.
500 + *
501 + * Module options:
502 + *
503 + *     file=filename[,filename...]
504 + *                             Required if "removable" is not set, names of
505 + *                                     the files or block devices used for
506 + *                                     backing storage
507 + *     serial=HHHH...          Required serial number (string of hex chars)
508 + *     ro=b[,b...]             Default false, booleans for read-only access
509 + *     removable               Default false, boolean for removable media
510 + *     luns=N                  Default N = number of filenames, number of
511 + *                                     LUNs to support
512 + *     nofua=b[,b...]          Default false, booleans for ignore FUA flag
513 + *                                     in SCSI WRITE(10,12) commands
514 + *     stall                   Default determined according to the type of
515 + *                                     USB device controller (usually true),
516 + *                                     boolean to permit the driver to halt
517 + *                                     bulk endpoints
518 + *     cdrom                   Default false, boolean for whether to emulate
519 + *                                     a CD-ROM drive
520 + *     transport=XXX           Default BBB, transport name (CB, CBI, or BBB)
521 + *     protocol=YYY            Default SCSI, protocol name (RBC, 8020 or
522 + *                                     ATAPI, QIC, UFI, 8070, or SCSI;
523 + *                                     also 1 - 6)
524 + *     vendor=0xVVVV           Default 0x0525 (NetChip), USB Vendor ID
525 + *     product=0xPPPP          Default 0xa4a5 (FSG), USB Product ID
526 + *     release=0xRRRR          Override the USB release number (bcdDevice)
527 + *     buflen=N                Default N=16384, buffer size used (will be
528 + *                                     rounded down to a multiple of
529 + *                                     PAGE_CACHE_SIZE)
530 + *
531 + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
532 + * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
533 + * default values are used for everything else.
534 + *
535 + * The pathnames of the backing files and the ro settings are available in
536 + * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
537 + * the gadget's sysfs directory.  If the "removable" option is set, writing to
538 + * these files will simulate ejecting/loading the medium (writing an empty
539 + * line means eject) and adjusting a write-enable tab.  Changes to the ro
540 + * setting are not allowed when the medium is loaded or if CD-ROM emulation
541 + * is being used.
542 + *
543 + * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
544 + * The driver's SCSI command interface was based on the "Information
545 + * technology - Small Computer System Interface - 2" document from
546 + * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
547 + * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
548 + * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
549 + * "Universal Serial Bus Mass Storage Class UFI Command Specification"
550 + * document, Revision 1.0, December 14, 1998, available at
551 + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
552 + */
553 +
554 +
555 +/*
556 + *                             Driver Design
557 + *
558 + * The FSG driver is fairly straightforward.  There is a main kernel
559 + * thread that handles most of the work.  Interrupt routines field
560 + * callbacks from the controller driver: bulk- and interrupt-request
561 + * completion notifications, endpoint-0 events, and disconnect events.
562 + * Completion events are passed to the main thread by wakeup calls.  Many
563 + * ep0 requests are handled at interrupt time, but SetInterface,
564 + * SetConfiguration, and device reset requests are forwarded to the
565 + * thread in the form of "exceptions" using SIGUSR1 signals (since they
566 + * should interrupt any ongoing file I/O operations).
567 + *
568 + * The thread's main routine implements the standard command/data/status
569 + * parts of a SCSI interaction.  It and its subroutines are full of tests
570 + * for pending signals/exceptions -- all this polling is necessary since
571 + * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
572 + * indication that the driver really wants to be running in userspace.)
573 + * An important point is that so long as the thread is alive it keeps an
574 + * open reference to the backing file.  This will prevent unmounting
575 + * the backing file's underlying filesystem and could cause problems
576 + * during system shutdown, for example.  To prevent such problems, the
577 + * thread catches INT, TERM, and KILL signals and converts them into
578 + * an EXIT exception.
579 + *
580 + * In normal operation the main thread is started during the gadget's
581 + * fsg_bind() callback and stopped during fsg_unbind().  But it can also
582 + * exit when it receives a signal, and there's no point leaving the
583 + * gadget running when the thread is dead.  So just before the thread
584 + * exits, it deregisters the gadget driver.  This makes things a little
585 + * tricky: The driver is deregistered at two places, and the exiting
586 + * thread can indirectly call fsg_unbind() which in turn can tell the
587 + * thread to exit.  The first problem is resolved through the use of the
588 + * REGISTERED atomic bitflag; the driver will only be deregistered once.
589 + * The second problem is resolved by having fsg_unbind() check
590 + * fsg->state; it won't try to stop the thread if the state is already
591 + * FSG_STATE_TERMINATED.
592 + *
593 + * To provide maximum throughput, the driver uses a circular pipeline of
594 + * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
595 + * arbitrarily long; in practice the benefits don't justify having more
596 + * than 2 stages (i.e., double buffering).  But it helps to think of the
597 + * pipeline as being a long one.  Each buffer head contains a bulk-in and
598 + * a bulk-out request pointer (since the buffer can be used for both
599 + * output and input -- directions always are given from the host's
600 + * point of view) as well as a pointer to the buffer and various state
601 + * variables.
602 + *
603 + * Use of the pipeline follows a simple protocol.  There is a variable
604 + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
605 + * At any time that buffer head may still be in use from an earlier
606 + * request, so each buffer head has a state variable indicating whether
607 + * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
608 + * buffer head to be EMPTY, filling the buffer either by file I/O or by
609 + * USB I/O (during which the buffer head is BUSY), and marking the buffer
610 + * head FULL when the I/O is complete.  Then the buffer will be emptied
611 + * (again possibly by USB I/O, during which it is marked BUSY) and
612 + * finally marked EMPTY again (possibly by a completion routine).
613 + *
614 + * A module parameter tells the driver to avoid stalling the bulk
615 + * endpoints wherever the transport specification allows.  This is
616 + * necessary for some UDCs like the SuperH, which cannot reliably clear a
617 + * halt on a bulk endpoint.  However, under certain circumstances the
618 + * Bulk-only specification requires a stall.  In such cases the driver
619 + * will halt the endpoint and set a flag indicating that it should clear
620 + * the halt in software during the next device reset.  Hopefully this
621 + * will permit everything to work correctly.  Furthermore, although the
622 + * specification allows the bulk-out endpoint to halt when the host sends
623 + * too much data, implementing this would cause an unavoidable race.
624 + * The driver will always use the "no-stall" approach for OUT transfers.
625 + *
626 + * One subtle point concerns sending status-stage responses for ep0
627 + * requests.  Some of these requests, such as device reset, can involve
628 + * interrupting an ongoing file I/O operation, which might take an
629 + * arbitrarily long time.  During that delay the host might give up on
630 + * the original ep0 request and issue a new one.  When that happens the
631 + * driver should not notify the host about completion of the original
632 + * request, as the host will no longer be waiting for it.  So the driver
633 + * assigns to each ep0 request a unique tag, and it keeps track of the
634 + * tag value of the request associated with a long-running exception
635 + * (device-reset, interface-change, or configuration-change).  When the
636 + * exception handler is finished, the status-stage response is submitted
637 + * only if the current ep0 request tag is equal to the exception request
638 + * tag.  Thus only the most recently received ep0 request will get a
639 + * status-stage response.
640 + *
641 + * Warning: This driver source file is too long.  It ought to be split up
642 + * into a header file plus about 3 separate .c files, to handle the details
643 + * of the Gadget, USB Mass Storage, and SCSI protocols.
644 + */
645 +
646 +
647 +/* #define VERBOSE_DEBUG */
648 +/* #define DUMP_MSGS */
649 +
650 +
651 +#include <linux/blkdev.h>
652 +#include <linux/completion.h>
653 +#include <linux/dcache.h>
654 +#include <linux/delay.h>
655 +#include <linux/device.h>
656 +#include <linux/fcntl.h>
657 +#include <linux/file.h>
658 +#include <linux/fs.h>
659 +#include <linux/kref.h>
660 +#include <linux/kthread.h>
661 +#include <linux/limits.h>
662 +#include <linux/module.h>
663 +#include <linux/rwsem.h>
664 +#include <linux/slab.h>
665 +#include <linux/spinlock.h>
666 +#include <linux/string.h>
667 +#include <linux/freezer.h>
668 +#include <linux/utsname.h>
669 +
670 +#include <linux/usb/ch9.h>
671 +#include <linux/usb/gadget.h>
672 +
673 +#include "gadget_chips.h"
674 +
675 +
676 +
677 +/*
678 + * Kbuild is not very cooperative with respect to linking separately
679 + * compiled library objects into one module.  So for now we won't use
680 + * separate compilation ... ensuring init/exit sections work to shrink
681 + * the runtime footprint, and giving us at least some parts of what
682 + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
683 + */
684 +#include "usbstring.c"
685 +#include "config.c"
686 +#include "epautoconf.c"
687 +
688 +/*-------------------------------------------------------------------------*/
689 +
690 +#define DRIVER_DESC            "File-backed Storage Gadget"
691 +#define DRIVER_NAME            "g_file_storage"
692 +#define DRIVER_VERSION         "1 September 2010"
693 +
694 +static       char fsg_string_manufacturer[64];
695 +static const char fsg_string_product[] = DRIVER_DESC;
696 +static const char fsg_string_config[] = "Self-powered";
697 +static const char fsg_string_interface[] = "Mass Storage";
698 +
699 +
700 +#include "storage_common.c"
701 +
702 +
703 +MODULE_DESCRIPTION(DRIVER_DESC);
704 +MODULE_AUTHOR("Alan Stern");
705 +MODULE_LICENSE("Dual BSD/GPL");
706 +
707 +/*
708 + * This driver assumes self-powered hardware and has no way for users to
709 + * trigger remote wakeup.  It uses autoconfiguration to select endpoints
710 + * and endpoint addresses.
711 + */
712 +
713 +
714 +/*-------------------------------------------------------------------------*/
715 +
716 +
717 +/* Encapsulate the module parameter settings */
718 +
719 +static struct {
720 +       char            *file[FSG_MAX_LUNS];
721 +       char            *serial;
722 +       bool            ro[FSG_MAX_LUNS];
723 +       bool            nofua[FSG_MAX_LUNS];
724 +       unsigned int    num_filenames;
725 +       unsigned int    num_ros;
726 +       unsigned int    num_nofuas;
727 +       unsigned int    nluns;
728 +
729 +       bool            removable;
730 +       bool            can_stall;
731 +       bool            cdrom;
732 +
733 +       char            *transport_parm;
734 +       char            *protocol_parm;
735 +       unsigned short  vendor;
736 +       unsigned short  product;
737 +       unsigned short  release;
738 +       unsigned int    buflen;
739 +
740 +       int             transport_type;
741 +       char            *transport_name;
742 +       int             protocol_type;
743 +       char            *protocol_name;
744 +
745 +} mod_data = {                                 // Default values
746 +       .transport_parm         = "BBB",
747 +       .protocol_parm          = "SCSI",
748 +       .removable              = 0,
749 +       .can_stall              = 1,
750 +       .cdrom                  = 0,
751 +       .vendor                 = FSG_VENDOR_ID,
752 +       .product                = FSG_PRODUCT_ID,
753 +       .release                = 0xffff,       // Use controller chip type
754 +       .buflen                 = 16384,
755 +       };
756 +
757 +
758 +module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
759 +               S_IRUGO);
760 +MODULE_PARM_DESC(file, "names of backing files or devices");
761 +
762 +module_param_named(serial, mod_data.serial, charp, S_IRUGO);
763 +MODULE_PARM_DESC(serial, "USB serial number");
764 +
765 +module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
766 +MODULE_PARM_DESC(ro, "true to force read-only");
767 +
768 +module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
769 +               S_IRUGO);
770 +MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
771 +
772 +module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
773 +MODULE_PARM_DESC(luns, "number of LUNs");
774 +
775 +module_param_named(removable, mod_data.removable, bool, S_IRUGO);
776 +MODULE_PARM_DESC(removable, "true to simulate removable media");
777 +
778 +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
779 +MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
780 +
781 +module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
782 +MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
783 +
784 +/* In the non-TEST version, only the module parameters listed above
785 + * are available. */
786 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
787 +
788 +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
789 +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
790 +
791 +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
792 +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
793 +               "8070, or SCSI)");
794 +
795 +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
796 +MODULE_PARM_DESC(vendor, "USB Vendor ID");
797 +
798 +module_param_named(product, mod_data.product, ushort, S_IRUGO);
799 +MODULE_PARM_DESC(product, "USB Product ID");
800 +
801 +module_param_named(release, mod_data.release, ushort, S_IRUGO);
802 +MODULE_PARM_DESC(release, "USB release number");
803 +
804 +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
805 +MODULE_PARM_DESC(buflen, "I/O buffer size");
806 +
807 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
808 +
809 +
810 +/*
811 + * These definitions will permit the compiler to avoid generating code for
812 + * parts of the driver that aren't used in the non-TEST version.  Even gcc
813 + * can recognize when a test of a constant expression yields a dead code
814 + * path.
815 + */
816 +
817 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
818 +
819 +#define transport_is_bbb()     (mod_data.transport_type == USB_PR_BULK)
820 +#define transport_is_cbi()     (mod_data.transport_type == USB_PR_CBI)
821 +#define protocol_is_scsi()     (mod_data.protocol_type == USB_SC_SCSI)
822 +
823 +#else
824 +
825 +#define transport_is_bbb()     1
826 +#define transport_is_cbi()     0
827 +#define protocol_is_scsi()     1
828 +
829 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
830 +
831 +
832 +/*-------------------------------------------------------------------------*/
833 +
834 +
835 +struct fsg_dev {
836 +       /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
837 +       spinlock_t              lock;
838 +       struct usb_gadget       *gadget;
839 +
840 +       /* filesem protects: backing files in use */
841 +       struct rw_semaphore     filesem;
842 +
843 +       /* reference counting: wait until all LUNs are released */
844 +       struct kref             ref;
845 +
846 +       struct usb_ep           *ep0;           // Handy copy of gadget->ep0
847 +       struct usb_request      *ep0req;        // For control responses
848 +       unsigned int            ep0_req_tag;
849 +       const char              *ep0req_name;
850 +
851 +       struct usb_request      *intreq;        // For interrupt responses
852 +       int                     intreq_busy;
853 +       struct fsg_buffhd       *intr_buffhd;
854 +
855 +       unsigned int            bulk_out_maxpacket;
856 +       enum fsg_state          state;          // For exception handling
857 +       unsigned int            exception_req_tag;
858 +
859 +       u8                      config, new_config;
860 +
861 +       unsigned int            running : 1;
862 +       unsigned int            bulk_in_enabled : 1;
863 +       unsigned int            bulk_out_enabled : 1;
864 +       unsigned int            intr_in_enabled : 1;
865 +       unsigned int            phase_error : 1;
866 +       unsigned int            short_packet_received : 1;
867 +       unsigned int            bad_lun_okay : 1;
868 +
869 +       unsigned long           atomic_bitflags;
870 +#define REGISTERED             0
871 +#define IGNORE_BULK_OUT                1
872 +#define SUSPENDED              2
873 +
874 +       struct usb_ep           *bulk_in;
875 +       struct usb_ep           *bulk_out;
876 +       struct usb_ep           *intr_in;
877 +
878 +       struct fsg_buffhd       *next_buffhd_to_fill;
879 +       struct fsg_buffhd       *next_buffhd_to_drain;
880 +
881 +       int                     thread_wakeup_needed;
882 +       struct completion       thread_notifier;
883 +       struct task_struct      *thread_task;
884 +
885 +       int                     cmnd_size;
886 +       u8                      cmnd[MAX_COMMAND_SIZE];
887 +       enum data_direction     data_dir;
888 +       u32                     data_size;
889 +       u32                     data_size_from_cmnd;
890 +       u32                     tag;
891 +       unsigned int            lun;
892 +       u32                     residue;
893 +       u32                     usb_amount_left;
894 +
895 +       /* The CB protocol offers no way for a host to know when a command
896 +        * has completed.  As a result the next command may arrive early,
897 +        * and we will still have to handle it.  For that reason we need
898 +        * a buffer to store new commands when using CB (or CBI, which
899 +        * does not oblige a host to wait for command completion either). */
900 +       int                     cbbuf_cmnd_size;
901 +       u8                      cbbuf_cmnd[MAX_COMMAND_SIZE];
902 +
903 +       unsigned int            nluns;
904 +       struct fsg_lun          *luns;
905 +       struct fsg_lun          *curlun;
906 +       /* Must be the last entry */
907 +       struct fsg_buffhd       buffhds[];
908 +};
909 +
910 +typedef void (*fsg_routine_t)(struct fsg_dev *);
911 +
912 +static int exception_in_progress(struct fsg_dev *fsg)
913 +{
914 +       return (fsg->state > FSG_STATE_IDLE);
915 +}
916 +
917 +/* Make bulk-out requests be divisible by the maxpacket size */
918 +static void set_bulk_out_req_length(struct fsg_dev *fsg,
919 +               struct fsg_buffhd *bh, unsigned int length)
920 +{
921 +       unsigned int    rem;
922 +
923 +       bh->bulk_out_intended_length = length;
924 +       rem = length % fsg->bulk_out_maxpacket;
925 +       if (rem > 0)
926 +               length += fsg->bulk_out_maxpacket - rem;
927 +       bh->outreq->length = length;
928 +}
929 +
930 +static struct fsg_dev                  *the_fsg;
931 +static struct usb_gadget_driver                fsg_driver;
932 +
933 +
934 +/*-------------------------------------------------------------------------*/
935 +
936 +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
937 +{
938 +       const char      *name;
939 +
940 +       if (ep == fsg->bulk_in)
941 +               name = "bulk-in";
942 +       else if (ep == fsg->bulk_out)
943 +               name = "bulk-out";
944 +       else
945 +               name = ep->name;
946 +       DBG(fsg, "%s set halt\n", name);
947 +       return usb_ep_set_halt(ep);
948 +}
949 +
950 +
951 +/*-------------------------------------------------------------------------*/
952 +
953 +/*
954 + * DESCRIPTORS ... most are static, but strings and (full) configuration
955 + * descriptors are built on demand.  Also the (static) config and interface
956 + * descriptors are adjusted during fsg_bind().
957 + */
958 +
959 +/* There is only one configuration. */
960 +#define        CONFIG_VALUE            1
961 +
962 +static struct usb_device_descriptor
963 +device_desc = {
964 +       .bLength =              sizeof device_desc,
965 +       .bDescriptorType =      USB_DT_DEVICE,
966 +
967 +       .bcdUSB =               cpu_to_le16(0x0200),
968 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
969 +
970 +       /* The next three values can be overridden by module parameters */
971 +       .idVendor =             cpu_to_le16(FSG_VENDOR_ID),
972 +       .idProduct =            cpu_to_le16(FSG_PRODUCT_ID),
973 +       .bcdDevice =            cpu_to_le16(0xffff),
974 +
975 +       .iManufacturer =        FSG_STRING_MANUFACTURER,
976 +       .iProduct =             FSG_STRING_PRODUCT,
977 +       .iSerialNumber =        FSG_STRING_SERIAL,
978 +       .bNumConfigurations =   1,
979 +};
980 +
981 +static struct usb_config_descriptor
982 +config_desc = {
983 +       .bLength =              sizeof config_desc,
984 +       .bDescriptorType =      USB_DT_CONFIG,
985 +
986 +       /* wTotalLength computed by usb_gadget_config_buf() */
987 +       .bNumInterfaces =       1,
988 +       .bConfigurationValue =  CONFIG_VALUE,
989 +       .iConfiguration =       FSG_STRING_CONFIG,
990 +       .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
991 +       .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
992 +};
993 +
994 +
995 +static struct usb_qualifier_descriptor
996 +dev_qualifier = {
997 +       .bLength =              sizeof dev_qualifier,
998 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
999 +
1000 +       .bcdUSB =               cpu_to_le16(0x0200),
1001 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
1002 +
1003 +       .bNumConfigurations =   1,
1004 +};
1005 +
1006 +static int populate_bos(struct fsg_dev *fsg, u8 *buf)
1007 +{
1008 +       memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
1009 +       buf += USB_DT_BOS_SIZE;
1010 +
1011 +       memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
1012 +       buf += USB_DT_USB_EXT_CAP_SIZE;
1013 +
1014 +       memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
1015 +
1016 +       return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
1017 +               + USB_DT_USB_EXT_CAP_SIZE;
1018 +}
1019 +
1020 +/*
1021 + * Config descriptors must agree with the code that sets configurations
1022 + * and with code managing interfaces and their altsettings.  They must
1023 + * also handle different speeds and other-speed requests.
1024 + */
1025 +static int populate_config_buf(struct usb_gadget *gadget,
1026 +               u8 *buf, u8 type, unsigned index)
1027 +{
1028 +       enum usb_device_speed                   speed = gadget->speed;
1029 +       int                                     len;
1030 +       const struct usb_descriptor_header      **function;
1031 +
1032 +       if (index > 0)
1033 +               return -EINVAL;
1034 +
1035 +       if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
1036 +               speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
1037 +       function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
1038 +               ? (const struct usb_descriptor_header **)fsg_hs_function
1039 +               : (const struct usb_descriptor_header **)fsg_fs_function;
1040 +
1041 +       /* for now, don't advertise srp-only devices */
1042 +       if (!gadget_is_otg(gadget))
1043 +               function++;
1044 +
1045 +       len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
1046 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
1047 +       return len;
1048 +}
1049 +
1050 +
1051 +/*-------------------------------------------------------------------------*/
1052 +
1053 +/* These routines may be called in process context or in_irq */
1054 +
1055 +/* Caller must hold fsg->lock */
1056 +static void wakeup_thread(struct fsg_dev *fsg)
1057 +{
1058 +       /* Tell the main thread that something has happened */
1059 +       fsg->thread_wakeup_needed = 1;
1060 +       if (fsg->thread_task)
1061 +               wake_up_process(fsg->thread_task);
1062 +}
1063 +
1064 +
1065 +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
1066 +{
1067 +       unsigned long           flags;
1068 +
1069 +       /* Do nothing if a higher-priority exception is already in progress.
1070 +        * If a lower-or-equal priority exception is in progress, preempt it
1071 +        * and notify the main thread by sending it a signal. */
1072 +       spin_lock_irqsave(&fsg->lock, flags);
1073 +       if (fsg->state <= new_state) {
1074 +               fsg->exception_req_tag = fsg->ep0_req_tag;
1075 +               fsg->state = new_state;
1076 +               if (fsg->thread_task)
1077 +                       send_sig_info(SIGUSR1, SEND_SIG_FORCED,
1078 +                                       fsg->thread_task);
1079 +       }
1080 +       spin_unlock_irqrestore(&fsg->lock, flags);
1081 +}
1082 +
1083 +
1084 +/*-------------------------------------------------------------------------*/
1085 +
1086 +/* The disconnect callback and ep0 routines.  These always run in_irq,
1087 + * except that ep0_queue() is called in the main thread to acknowledge
1088 + * completion of various requests: set config, set interface, and
1089 + * Bulk-only device reset. */
1090 +
1091 +static void fsg_disconnect(struct usb_gadget *gadget)
1092 +{
1093 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1094 +
1095 +       DBG(fsg, "disconnect or port reset\n");
1096 +       raise_exception(fsg, FSG_STATE_DISCONNECT);
1097 +}
1098 +
1099 +
1100 +static int ep0_queue(struct fsg_dev *fsg)
1101 +{
1102 +       int     rc;
1103 +
1104 +       rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
1105 +       if (rc != 0 && rc != -ESHUTDOWN) {
1106 +
1107 +               /* We can't do much more than wait for a reset */
1108 +               WARNING(fsg, "error in submission: %s --> %d\n",
1109 +                               fsg->ep0->name, rc);
1110 +       }
1111 +       return rc;
1112 +}
1113 +
1114 +static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
1115 +{
1116 +       struct fsg_dev          *fsg = ep->driver_data;
1117 +
1118 +       if (req->actual > 0)
1119 +               dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
1120 +       if (req->status || req->actual != req->length)
1121 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1122 +                               req->status, req->actual, req->length);
1123 +       if (req->status == -ECONNRESET)         // Request was cancelled
1124 +               usb_ep_fifo_flush(ep);
1125 +
1126 +       if (req->status == 0 && req->context)
1127 +               ((fsg_routine_t) (req->context))(fsg);
1128 +}
1129 +
1130 +
1131 +/*-------------------------------------------------------------------------*/
1132 +
1133 +/* Bulk and interrupt endpoint completion handlers.
1134 + * These always run in_irq. */
1135 +
1136 +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
1137 +{
1138 +       struct fsg_dev          *fsg = ep->driver_data;
1139 +       struct fsg_buffhd       *bh = req->context;
1140 +
1141 +       if (req->status || req->actual != req->length)
1142 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1143 +                               req->status, req->actual, req->length);
1144 +       if (req->status == -ECONNRESET)         // Request was cancelled
1145 +               usb_ep_fifo_flush(ep);
1146 +
1147 +       /* Hold the lock while we update the request and buffer states */
1148 +       smp_wmb();
1149 +       spin_lock(&fsg->lock);
1150 +       bh->inreq_busy = 0;
1151 +       bh->state = BUF_STATE_EMPTY;
1152 +       wakeup_thread(fsg);
1153 +       spin_unlock(&fsg->lock);
1154 +}
1155 +
1156 +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
1157 +{
1158 +       struct fsg_dev          *fsg = ep->driver_data;
1159 +       struct fsg_buffhd       *bh = req->context;
1160 +
1161 +       dump_msg(fsg, "bulk-out", req->buf, req->actual);
1162 +       if (req->status || req->actual != bh->bulk_out_intended_length)
1163 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1164 +                               req->status, req->actual,
1165 +                               bh->bulk_out_intended_length);
1166 +       if (req->status == -ECONNRESET)         // Request was cancelled
1167 +               usb_ep_fifo_flush(ep);
1168 +
1169 +       /* Hold the lock while we update the request and buffer states */
1170 +       smp_wmb();
1171 +       spin_lock(&fsg->lock);
1172 +       bh->outreq_busy = 0;
1173 +       bh->state = BUF_STATE_FULL;
1174 +       wakeup_thread(fsg);
1175 +       spin_unlock(&fsg->lock);
1176 +}
1177 +
1178 +
1179 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1180 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1181 +{
1182 +       struct fsg_dev          *fsg = ep->driver_data;
1183 +       struct fsg_buffhd       *bh = req->context;
1184 +
1185 +       if (req->status || req->actual != req->length)
1186 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1187 +                               req->status, req->actual, req->length);
1188 +       if (req->status == -ECONNRESET)         // Request was cancelled
1189 +               usb_ep_fifo_flush(ep);
1190 +
1191 +       /* Hold the lock while we update the request and buffer states */
1192 +       smp_wmb();
1193 +       spin_lock(&fsg->lock);
1194 +       fsg->intreq_busy = 0;
1195 +       bh->state = BUF_STATE_EMPTY;
1196 +       wakeup_thread(fsg);
1197 +       spin_unlock(&fsg->lock);
1198 +}
1199 +
1200 +#else
1201 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1202 +{}
1203 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1204 +
1205 +
1206 +/*-------------------------------------------------------------------------*/
1207 +
1208 +/* Ep0 class-specific handlers.  These always run in_irq. */
1209 +
1210 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1211 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1212 +{
1213 +       struct usb_request      *req = fsg->ep0req;
1214 +       static u8               cbi_reset_cmnd[6] = {
1215 +                       SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
1216 +
1217 +       /* Error in command transfer? */
1218 +       if (req->status || req->length != req->actual ||
1219 +                       req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
1220 +
1221 +               /* Not all controllers allow a protocol stall after
1222 +                * receiving control-out data, but we'll try anyway. */
1223 +               fsg_set_halt(fsg, fsg->ep0);
1224 +               return;                 // Wait for reset
1225 +       }
1226 +
1227 +       /* Is it the special reset command? */
1228 +       if (req->actual >= sizeof cbi_reset_cmnd &&
1229 +                       memcmp(req->buf, cbi_reset_cmnd,
1230 +                               sizeof cbi_reset_cmnd) == 0) {
1231 +
1232 +               /* Raise an exception to stop the current operation
1233 +                * and reinitialize our state. */
1234 +               DBG(fsg, "cbi reset request\n");
1235 +               raise_exception(fsg, FSG_STATE_RESET);
1236 +               return;
1237 +       }
1238 +
1239 +       VDBG(fsg, "CB[I] accept device-specific command\n");
1240 +       spin_lock(&fsg->lock);
1241 +
1242 +       /* Save the command for later */
1243 +       if (fsg->cbbuf_cmnd_size)
1244 +               WARNING(fsg, "CB[I] overwriting previous command\n");
1245 +       fsg->cbbuf_cmnd_size = req->actual;
1246 +       memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
1247 +
1248 +       wakeup_thread(fsg);
1249 +       spin_unlock(&fsg->lock);
1250 +}
1251 +
1252 +#else
1253 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1254 +{}
1255 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1256 +
1257 +
1258 +static int class_setup_req(struct fsg_dev *fsg,
1259 +               const struct usb_ctrlrequest *ctrl)
1260 +{
1261 +       struct usb_request      *req = fsg->ep0req;
1262 +       int                     value = -EOPNOTSUPP;
1263 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1264 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1265 +       u16                     w_length = le16_to_cpu(ctrl->wLength);
1266 +
1267 +       if (!fsg->config)
1268 +               return value;
1269 +
1270 +       /* Handle Bulk-only class-specific requests */
1271 +       if (transport_is_bbb()) {
1272 +               switch (ctrl->bRequest) {
1273 +
1274 +               case US_BULK_RESET_REQUEST:
1275 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1276 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1277 +                               break;
1278 +                       if (w_index != 0 || w_value != 0 || w_length != 0) {
1279 +                               value = -EDOM;
1280 +                               break;
1281 +                       }
1282 +
1283 +                       /* Raise an exception to stop the current operation
1284 +                        * and reinitialize our state. */
1285 +                       DBG(fsg, "bulk reset request\n");
1286 +                       raise_exception(fsg, FSG_STATE_RESET);
1287 +                       value = DELAYED_STATUS;
1288 +                       break;
1289 +
1290 +               case US_BULK_GET_MAX_LUN:
1291 +                       if (ctrl->bRequestType != (USB_DIR_IN |
1292 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1293 +                               break;
1294 +                       if (w_index != 0 || w_value != 0 || w_length != 1) {
1295 +                               value = -EDOM;
1296 +                               break;
1297 +                       }
1298 +                       VDBG(fsg, "get max LUN\n");
1299 +                       *(u8 *) req->buf = fsg->nluns - 1;
1300 +                       value = 1;
1301 +                       break;
1302 +               }
1303 +       }
1304 +
1305 +       /* Handle CBI class-specific requests */
1306 +       else {
1307 +               switch (ctrl->bRequest) {
1308 +
1309 +               case USB_CBI_ADSC_REQUEST:
1310 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1311 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1312 +                               break;
1313 +                       if (w_index != 0 || w_value != 0) {
1314 +                               value = -EDOM;
1315 +                               break;
1316 +                       }
1317 +                       if (w_length > MAX_COMMAND_SIZE) {
1318 +                               value = -EOVERFLOW;
1319 +                               break;
1320 +                       }
1321 +                       value = w_length;
1322 +                       fsg->ep0req->context = received_cbi_adsc;
1323 +                       break;
1324 +               }
1325 +       }
1326 +
1327 +       if (value == -EOPNOTSUPP)
1328 +               VDBG(fsg,
1329 +                       "unknown class-specific control req "
1330 +                       "%02x.%02x v%04x i%04x l%u\n",
1331 +                       ctrl->bRequestType, ctrl->bRequest,
1332 +                       le16_to_cpu(ctrl->wValue), w_index, w_length);
1333 +       return value;
1334 +}
1335 +
1336 +
1337 +/*-------------------------------------------------------------------------*/
1338 +
1339 +/* Ep0 standard request handlers.  These always run in_irq. */
1340 +
1341 +static int standard_setup_req(struct fsg_dev *fsg,
1342 +               const struct usb_ctrlrequest *ctrl)
1343 +{
1344 +       struct usb_request      *req = fsg->ep0req;
1345 +       int                     value = -EOPNOTSUPP;
1346 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1347 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1348 +
1349 +       /* Usually this just stores reply data in the pre-allocated ep0 buffer,
1350 +        * but config change events will also reconfigure hardware. */
1351 +       switch (ctrl->bRequest) {
1352 +
1353 +       case USB_REQ_GET_DESCRIPTOR:
1354 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1355 +                               USB_RECIP_DEVICE))
1356 +                       break;
1357 +               switch (w_value >> 8) {
1358 +
1359 +               case USB_DT_DEVICE:
1360 +                       VDBG(fsg, "get device descriptor\n");
1361 +                       device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
1362 +                       value = sizeof device_desc;
1363 +                       memcpy(req->buf, &device_desc, value);
1364 +                       break;
1365 +               case USB_DT_DEVICE_QUALIFIER:
1366 +                       VDBG(fsg, "get device qualifier\n");
1367 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1368 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1369 +                               break;
1370 +                       /*
1371 +                        * Assume ep0 uses the same maxpacket value for both
1372 +                        * speeds
1373 +                        */
1374 +                       dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
1375 +                       value = sizeof dev_qualifier;
1376 +                       memcpy(req->buf, &dev_qualifier, value);
1377 +                       break;
1378 +
1379 +               case USB_DT_OTHER_SPEED_CONFIG:
1380 +                       VDBG(fsg, "get other-speed config descriptor\n");
1381 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1382 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1383 +                               break;
1384 +                       goto get_config;
1385 +               case USB_DT_CONFIG:
1386 +                       VDBG(fsg, "get configuration descriptor\n");
1387 +get_config:
1388 +                       value = populate_config_buf(fsg->gadget,
1389 +                                       req->buf,
1390 +                                       w_value >> 8,
1391 +                                       w_value & 0xff);
1392 +                       break;
1393 +
1394 +               case USB_DT_STRING:
1395 +                       VDBG(fsg, "get string descriptor\n");
1396 +
1397 +                       /* wIndex == language code */
1398 +                       value = usb_gadget_get_string(&fsg_stringtab,
1399 +                                       w_value & 0xff, req->buf);
1400 +                       break;
1401 +
1402 +               case USB_DT_BOS:
1403 +                       VDBG(fsg, "get bos descriptor\n");
1404 +
1405 +                       if (gadget_is_superspeed(fsg->gadget))
1406 +                               value = populate_bos(fsg, req->buf);
1407 +                       break;
1408 +               }
1409 +
1410 +               break;
1411 +
1412 +       /* One config, two speeds */
1413 +       case USB_REQ_SET_CONFIGURATION:
1414 +               if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
1415 +                               USB_RECIP_DEVICE))
1416 +                       break;
1417 +               VDBG(fsg, "set configuration\n");
1418 +               if (w_value == CONFIG_VALUE || w_value == 0) {
1419 +                       fsg->new_config = w_value;
1420 +
1421 +                       /* Raise an exception to wipe out previous transaction
1422 +                        * state (queued bufs, etc) and set the new config. */
1423 +                       raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
1424 +                       value = DELAYED_STATUS;
1425 +               }
1426 +               break;
1427 +       case USB_REQ_GET_CONFIGURATION:
1428 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1429 +                               USB_RECIP_DEVICE))
1430 +                       break;
1431 +               VDBG(fsg, "get configuration\n");
1432 +               *(u8 *) req->buf = fsg->config;
1433 +               value = 1;
1434 +               break;
1435 +
1436 +       case USB_REQ_SET_INTERFACE:
1437 +               if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
1438 +                               USB_RECIP_INTERFACE))
1439 +                       break;
1440 +               if (fsg->config && w_index == 0) {
1441 +
1442 +                       /* Raise an exception to wipe out previous transaction
1443 +                        * state (queued bufs, etc) and install the new
1444 +                        * interface altsetting. */
1445 +                       raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
1446 +                       value = DELAYED_STATUS;
1447 +               }
1448 +               break;
1449 +       case USB_REQ_GET_INTERFACE:
1450 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1451 +                               USB_RECIP_INTERFACE))
1452 +                       break;
1453 +               if (!fsg->config)
1454 +                       break;
1455 +               if (w_index != 0) {
1456 +                       value = -EDOM;
1457 +                       break;
1458 +               }
1459 +               VDBG(fsg, "get interface\n");
1460 +               *(u8 *) req->buf = 0;
1461 +               value = 1;
1462 +               break;
1463 +
1464 +       default:
1465 +               VDBG(fsg,
1466 +                       "unknown control req %02x.%02x v%04x i%04x l%u\n",
1467 +                       ctrl->bRequestType, ctrl->bRequest,
1468 +                       w_value, w_index, le16_to_cpu(ctrl->wLength));
1469 +       }
1470 +
1471 +       return value;
1472 +}
1473 +
1474 +
1475 +static int fsg_setup(struct usb_gadget *gadget,
1476 +               const struct usb_ctrlrequest *ctrl)
1477 +{
1478 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1479 +       int                     rc;
1480 +       int                     w_length = le16_to_cpu(ctrl->wLength);
1481 +
1482 +       ++fsg->ep0_req_tag;             // Record arrival of a new request
1483 +       fsg->ep0req->context = NULL;
1484 +       fsg->ep0req->length = 0;
1485 +       dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
1486 +
1487 +       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
1488 +               rc = class_setup_req(fsg, ctrl);
1489 +       else
1490 +               rc = standard_setup_req(fsg, ctrl);
1491 +
1492 +       /* Respond with data/status or defer until later? */
1493 +       if (rc >= 0 && rc != DELAYED_STATUS) {
1494 +               rc = min(rc, w_length);
1495 +               fsg->ep0req->length = rc;
1496 +               fsg->ep0req->zero = rc < w_length;
1497 +               fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
1498 +                               "ep0-in" : "ep0-out");
1499 +               rc = ep0_queue(fsg);
1500 +       }
1501 +
1502 +       /* Device either stalls (rc < 0) or reports success */
1503 +       return rc;
1504 +}
1505 +
1506 +
1507 +/*-------------------------------------------------------------------------*/
1508 +
1509 +/* All the following routines run in process context */
1510 +
1511 +
1512 +/* Use this for bulk or interrupt transfers, not ep0 */
1513 +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
1514 +               struct usb_request *req, int *pbusy,
1515 +               enum fsg_buffer_state *state)
1516 +{
1517 +       int     rc;
1518 +
1519 +       if (ep == fsg->bulk_in)
1520 +               dump_msg(fsg, "bulk-in", req->buf, req->length);
1521 +       else if (ep == fsg->intr_in)
1522 +               dump_msg(fsg, "intr-in", req->buf, req->length);
1523 +
1524 +       spin_lock_irq(&fsg->lock);
1525 +       *pbusy = 1;
1526 +       *state = BUF_STATE_BUSY;
1527 +       spin_unlock_irq(&fsg->lock);
1528 +       rc = usb_ep_queue(ep, req, GFP_KERNEL);
1529 +       if (rc != 0) {
1530 +               *pbusy = 0;
1531 +               *state = BUF_STATE_EMPTY;
1532 +
1533 +               /* We can't do much more than wait for a reset */
1534 +
1535 +               /* Note: currently the net2280 driver fails zero-length
1536 +                * submissions if DMA is enabled. */
1537 +               if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
1538 +                                               req->length == 0))
1539 +                       WARNING(fsg, "error in submission: %s --> %d\n",
1540 +                                       ep->name, rc);
1541 +       }
1542 +}
1543 +
1544 +
1545 +static int sleep_thread(struct fsg_dev *fsg)
1546 +{
1547 +       int     rc = 0;
1548 +
1549 +       /* Wait until a signal arrives or we are woken up */
1550 +       for (;;) {
1551 +               try_to_freeze();
1552 +               set_current_state(TASK_INTERRUPTIBLE);
1553 +               if (signal_pending(current)) {
1554 +                       rc = -EINTR;
1555 +                       break;
1556 +               }
1557 +               if (fsg->thread_wakeup_needed)
1558 +                       break;
1559 +               schedule();
1560 +       }
1561 +       __set_current_state(TASK_RUNNING);
1562 +       fsg->thread_wakeup_needed = 0;
1563 +       return rc;
1564 +}
1565 +
1566 +
1567 +/*-------------------------------------------------------------------------*/
1568 +
1569 +static int do_read(struct fsg_dev *fsg)
1570 +{
1571 +       struct fsg_lun          *curlun = fsg->curlun;
1572 +       u32                     lba;
1573 +       struct fsg_buffhd       *bh;
1574 +       int                     rc;
1575 +       u32                     amount_left;
1576 +       loff_t                  file_offset, file_offset_tmp;
1577 +       unsigned int            amount;
1578 +       ssize_t                 nread;
1579 +
1580 +       /* Get the starting Logical Block Address and check that it's
1581 +        * not too big */
1582 +       if (fsg->cmnd[0] == READ_6)
1583 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1584 +       else {
1585 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1586 +
1587 +               /* We allow DPO (Disable Page Out = don't save data in the
1588 +                * cache) and FUA (Force Unit Access = don't read from the
1589 +                * cache), but we don't implement them. */
1590 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1591 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1592 +                       return -EINVAL;
1593 +               }
1594 +       }
1595 +       if (lba >= curlun->num_sectors) {
1596 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1597 +               return -EINVAL;
1598 +       }
1599 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1600 +
1601 +       /* Carry out the file reads */
1602 +       amount_left = fsg->data_size_from_cmnd;
1603 +       if (unlikely(amount_left == 0))
1604 +               return -EIO;            // No default reply
1605 +
1606 +       for (;;) {
1607 +
1608 +               /* Figure out how much we need to read:
1609 +                * Try to read the remaining amount.
1610 +                * But don't read more than the buffer size.
1611 +                * And don't try to read past the end of the file.
1612 +                */
1613 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1614 +               amount = min((loff_t) amount,
1615 +                               curlun->file_length - file_offset);
1616 +
1617 +               /* Wait for the next buffer to become available */
1618 +               bh = fsg->next_buffhd_to_fill;
1619 +               while (bh->state != BUF_STATE_EMPTY) {
1620 +                       rc = sleep_thread(fsg);
1621 +                       if (rc)
1622 +                               return rc;
1623 +               }
1624 +
1625 +               /* If we were asked to read past the end of file,
1626 +                * end with an empty buffer. */
1627 +               if (amount == 0) {
1628 +                       curlun->sense_data =
1629 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1630 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1631 +                       curlun->info_valid = 1;
1632 +                       bh->inreq->length = 0;
1633 +                       bh->state = BUF_STATE_FULL;
1634 +                       break;
1635 +               }
1636 +
1637 +               /* Perform the read */
1638 +               file_offset_tmp = file_offset;
1639 +               nread = vfs_read(curlun->filp,
1640 +                               (char __user *) bh->buf,
1641 +                               amount, &file_offset_tmp);
1642 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1643 +                               (unsigned long long) file_offset,
1644 +                               (int) nread);
1645 +               if (signal_pending(current))
1646 +                       return -EINTR;
1647 +
1648 +               if (nread < 0) {
1649 +                       LDBG(curlun, "error in file read: %d\n",
1650 +                                       (int) nread);
1651 +                       nread = 0;
1652 +               } else if (nread < amount) {
1653 +                       LDBG(curlun, "partial file read: %d/%u\n",
1654 +                                       (int) nread, amount);
1655 +                       nread = round_down(nread, curlun->blksize);
1656 +               }
1657 +               file_offset  += nread;
1658 +               amount_left  -= nread;
1659 +               fsg->residue -= nread;
1660 +
1661 +               /* Except at the end of the transfer, nread will be
1662 +                * equal to the buffer size, which is divisible by the
1663 +                * bulk-in maxpacket size.
1664 +                */
1665 +               bh->inreq->length = nread;
1666 +               bh->state = BUF_STATE_FULL;
1667 +
1668 +               /* If an error occurred, report it and its position */
1669 +               if (nread < amount) {
1670 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1671 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1672 +                       curlun->info_valid = 1;
1673 +                       break;
1674 +               }
1675 +
1676 +               if (amount_left == 0)
1677 +                       break;          // No more left to read
1678 +
1679 +               /* Send this buffer and go read some more */
1680 +               bh->inreq->zero = 0;
1681 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
1682 +                               &bh->inreq_busy, &bh->state);
1683 +               fsg->next_buffhd_to_fill = bh->next;
1684 +       }
1685 +
1686 +       return -EIO;            // No default reply
1687 +}
1688 +
1689 +
1690 +/*-------------------------------------------------------------------------*/
1691 +
1692 +static int do_write(struct fsg_dev *fsg)
1693 +{
1694 +       struct fsg_lun          *curlun = fsg->curlun;
1695 +       u32                     lba;
1696 +       struct fsg_buffhd       *bh;
1697 +       int                     get_some_more;
1698 +       u32                     amount_left_to_req, amount_left_to_write;
1699 +       loff_t                  usb_offset, file_offset, file_offset_tmp;
1700 +       unsigned int            amount;
1701 +       ssize_t                 nwritten;
1702 +       int                     rc;
1703 +
1704 +       if (curlun->ro) {
1705 +               curlun->sense_data = SS_WRITE_PROTECTED;
1706 +               return -EINVAL;
1707 +       }
1708 +       spin_lock(&curlun->filp->f_lock);
1709 +       curlun->filp->f_flags &= ~O_SYNC;       // Default is not to wait
1710 +       spin_unlock(&curlun->filp->f_lock);
1711 +
1712 +       /* Get the starting Logical Block Address and check that it's
1713 +        * not too big */
1714 +       if (fsg->cmnd[0] == WRITE_6)
1715 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1716 +       else {
1717 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1718 +
1719 +               /* We allow DPO (Disable Page Out = don't save data in the
1720 +                * cache) and FUA (Force Unit Access = write directly to the
1721 +                * medium).  We don't implement DPO; we implement FUA by
1722 +                * performing synchronous output. */
1723 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1724 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1725 +                       return -EINVAL;
1726 +               }
1727 +               /* FUA */
1728 +               if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
1729 +                       spin_lock(&curlun->filp->f_lock);
1730 +                       curlun->filp->f_flags |= O_DSYNC;
1731 +                       spin_unlock(&curlun->filp->f_lock);
1732 +               }
1733 +       }
1734 +       if (lba >= curlun->num_sectors) {
1735 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1736 +               return -EINVAL;
1737 +       }
1738 +
1739 +       /* Carry out the file writes */
1740 +       get_some_more = 1;
1741 +       file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
1742 +       amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
1743 +
1744 +       while (amount_left_to_write > 0) {
1745 +
1746 +               /* Queue a request for more data from the host */
1747 +               bh = fsg->next_buffhd_to_fill;
1748 +               if (bh->state == BUF_STATE_EMPTY && get_some_more) {
1749 +
1750 +                       /* Figure out how much we want to get:
1751 +                        * Try to get the remaining amount,
1752 +                        * but not more than the buffer size.
1753 +                        */
1754 +                       amount = min(amount_left_to_req, mod_data.buflen);
1755 +
1756 +                       /* Beyond the end of the backing file? */
1757 +                       if (usb_offset >= curlun->file_length) {
1758 +                               get_some_more = 0;
1759 +                               curlun->sense_data =
1760 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1761 +                               curlun->sense_data_info = usb_offset >> curlun->blkbits;
1762 +                               curlun->info_valid = 1;
1763 +                               continue;
1764 +                       }
1765 +
1766 +                       /* Get the next buffer */
1767 +                       usb_offset += amount;
1768 +                       fsg->usb_amount_left -= amount;
1769 +                       amount_left_to_req -= amount;
1770 +                       if (amount_left_to_req == 0)
1771 +                               get_some_more = 0;
1772 +
1773 +                       /* Except at the end of the transfer, amount will be
1774 +                        * equal to the buffer size, which is divisible by
1775 +                        * the bulk-out maxpacket size.
1776 +                        */
1777 +                       set_bulk_out_req_length(fsg, bh, amount);
1778 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
1779 +                                       &bh->outreq_busy, &bh->state);
1780 +                       fsg->next_buffhd_to_fill = bh->next;
1781 +                       continue;
1782 +               }
1783 +
1784 +               /* Write the received data to the backing file */
1785 +               bh = fsg->next_buffhd_to_drain;
1786 +               if (bh->state == BUF_STATE_EMPTY && !get_some_more)
1787 +                       break;                  // We stopped early
1788 +               if (bh->state == BUF_STATE_FULL) {
1789 +                       smp_rmb();
1790 +                       fsg->next_buffhd_to_drain = bh->next;
1791 +                       bh->state = BUF_STATE_EMPTY;
1792 +
1793 +                       /* Did something go wrong with the transfer? */
1794 +                       if (bh->outreq->status != 0) {
1795 +                               curlun->sense_data = SS_COMMUNICATION_FAILURE;
1796 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1797 +                               curlun->info_valid = 1;
1798 +                               break;
1799 +                       }
1800 +
1801 +                       amount = bh->outreq->actual;
1802 +                       if (curlun->file_length - file_offset < amount) {
1803 +                               LERROR(curlun,
1804 +       "write %u @ %llu beyond end %llu\n",
1805 +       amount, (unsigned long long) file_offset,
1806 +       (unsigned long long) curlun->file_length);
1807 +                               amount = curlun->file_length - file_offset;
1808 +                       }
1809 +
1810 +                       /* Don't accept excess data.  The spec doesn't say
1811 +                        * what to do in this case.  We'll ignore the error.
1812 +                        */
1813 +                       amount = min(amount, bh->bulk_out_intended_length);
1814 +
1815 +                       /* Don't write a partial block */
1816 +                       amount = round_down(amount, curlun->blksize);
1817 +                       if (amount == 0)
1818 +                               goto empty_write;
1819 +
1820 +                       /* Perform the write */
1821 +                       file_offset_tmp = file_offset;
1822 +                       nwritten = vfs_write(curlun->filp,
1823 +                                       (char __user *) bh->buf,
1824 +                                       amount, &file_offset_tmp);
1825 +                       VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
1826 +                                       (unsigned long long) file_offset,
1827 +                                       (int) nwritten);
1828 +                       if (signal_pending(current))
1829 +                               return -EINTR;          // Interrupted!
1830 +
1831 +                       if (nwritten < 0) {
1832 +                               LDBG(curlun, "error in file write: %d\n",
1833 +                                               (int) nwritten);
1834 +                               nwritten = 0;
1835 +                       } else if (nwritten < amount) {
1836 +                               LDBG(curlun, "partial file write: %d/%u\n",
1837 +                                               (int) nwritten, amount);
1838 +                               nwritten = round_down(nwritten, curlun->blksize);
1839 +                       }
1840 +                       file_offset += nwritten;
1841 +                       amount_left_to_write -= nwritten;
1842 +                       fsg->residue -= nwritten;
1843 +
1844 +                       /* If an error occurred, report it and its position */
1845 +                       if (nwritten < amount) {
1846 +                               curlun->sense_data = SS_WRITE_ERROR;
1847 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1848 +                               curlun->info_valid = 1;
1849 +                               break;
1850 +                       }
1851 +
1852 + empty_write:
1853 +                       /* Did the host decide to stop early? */
1854 +                       if (bh->outreq->actual < bh->bulk_out_intended_length) {
1855 +                               fsg->short_packet_received = 1;
1856 +                               break;
1857 +                       }
1858 +                       continue;
1859 +               }
1860 +
1861 +               /* Wait for something to happen */
1862 +               rc = sleep_thread(fsg);
1863 +               if (rc)
1864 +                       return rc;
1865 +       }
1866 +
1867 +       return -EIO;            // No default reply
1868 +}
1869 +
1870 +
1871 +/*-------------------------------------------------------------------------*/
1872 +
1873 +static int do_synchronize_cache(struct fsg_dev *fsg)
1874 +{
1875 +       struct fsg_lun  *curlun = fsg->curlun;
1876 +       int             rc;
1877 +
1878 +       /* We ignore the requested LBA and write out all file's
1879 +        * dirty data buffers. */
1880 +       rc = fsg_lun_fsync_sub(curlun);
1881 +       if (rc)
1882 +               curlun->sense_data = SS_WRITE_ERROR;
1883 +       return 0;
1884 +}
1885 +
1886 +
1887 +/*-------------------------------------------------------------------------*/
1888 +
1889 +static void invalidate_sub(struct fsg_lun *curlun)
1890 +{
1891 +       struct file     *filp = curlun->filp;
1892 +       struct inode    *inode = filp->f_path.dentry->d_inode;
1893 +       unsigned long   rc;
1894 +
1895 +       rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
1896 +       VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
1897 +}
1898 +
1899 +static int do_verify(struct fsg_dev *fsg)
1900 +{
1901 +       struct fsg_lun          *curlun = fsg->curlun;
1902 +       u32                     lba;
1903 +       u32                     verification_length;
1904 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
1905 +       loff_t                  file_offset, file_offset_tmp;
1906 +       u32                     amount_left;
1907 +       unsigned int            amount;
1908 +       ssize_t                 nread;
1909 +
1910 +       /* Get the starting Logical Block Address and check that it's
1911 +        * not too big */
1912 +       lba = get_unaligned_be32(&fsg->cmnd[2]);
1913 +       if (lba >= curlun->num_sectors) {
1914 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1915 +               return -EINVAL;
1916 +       }
1917 +
1918 +       /* We allow DPO (Disable Page Out = don't save data in the
1919 +        * cache) but we don't implement it. */
1920 +       if ((fsg->cmnd[1] & ~0x10) != 0) {
1921 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1922 +               return -EINVAL;
1923 +       }
1924 +
1925 +       verification_length = get_unaligned_be16(&fsg->cmnd[7]);
1926 +       if (unlikely(verification_length == 0))
1927 +               return -EIO;            // No default reply
1928 +
1929 +       /* Prepare to carry out the file verify */
1930 +       amount_left = verification_length << curlun->blkbits;
1931 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1932 +
1933 +       /* Write out all the dirty buffers before invalidating them */
1934 +       fsg_lun_fsync_sub(curlun);
1935 +       if (signal_pending(current))
1936 +               return -EINTR;
1937 +
1938 +       invalidate_sub(curlun);
1939 +       if (signal_pending(current))
1940 +               return -EINTR;
1941 +
1942 +       /* Just try to read the requested blocks */
1943 +       while (amount_left > 0) {
1944 +
1945 +               /* Figure out how much we need to read:
1946 +                * Try to read the remaining amount, but not more than
1947 +                * the buffer size.
1948 +                * And don't try to read past the end of the file.
1949 +                */
1950 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1951 +               amount = min((loff_t) amount,
1952 +                               curlun->file_length - file_offset);
1953 +               if (amount == 0) {
1954 +                       curlun->sense_data =
1955 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1956 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1957 +                       curlun->info_valid = 1;
1958 +                       break;
1959 +               }
1960 +
1961 +               /* Perform the read */
1962 +               file_offset_tmp = file_offset;
1963 +               nread = vfs_read(curlun->filp,
1964 +                               (char __user *) bh->buf,
1965 +                               amount, &file_offset_tmp);
1966 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1967 +                               (unsigned long long) file_offset,
1968 +                               (int) nread);
1969 +               if (signal_pending(current))
1970 +                       return -EINTR;
1971 +
1972 +               if (nread < 0) {
1973 +                       LDBG(curlun, "error in file verify: %d\n",
1974 +                                       (int) nread);
1975 +                       nread = 0;
1976 +               } else if (nread < amount) {
1977 +                       LDBG(curlun, "partial file verify: %d/%u\n",
1978 +                                       (int) nread, amount);
1979 +                       nread = round_down(nread, curlun->blksize);
1980 +               }
1981 +               if (nread == 0) {
1982 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1983 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1984 +                       curlun->info_valid = 1;
1985 +                       break;
1986 +               }
1987 +               file_offset += nread;
1988 +               amount_left -= nread;
1989 +       }
1990 +       return 0;
1991 +}
1992 +
1993 +
1994 +/*-------------------------------------------------------------------------*/
1995 +
1996 +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1997 +{
1998 +       u8      *buf = (u8 *) bh->buf;
1999 +
2000 +       static char vendor_id[] = "Linux   ";
2001 +       static char product_disk_id[] = "File-Stor Gadget";
2002 +       static char product_cdrom_id[] = "File-CD Gadget  ";
2003 +
2004 +       if (!fsg->curlun) {             // Unsupported LUNs are okay
2005 +               fsg->bad_lun_okay = 1;
2006 +               memset(buf, 0, 36);
2007 +               buf[0] = 0x7f;          // Unsupported, no device-type
2008 +               buf[4] = 31;            // Additional length
2009 +               return 36;
2010 +       }
2011 +
2012 +       memset(buf, 0, 8);
2013 +       buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
2014 +       if (mod_data.removable)
2015 +               buf[1] = 0x80;
2016 +       buf[2] = 2;             // ANSI SCSI level 2
2017 +       buf[3] = 2;             // SCSI-2 INQUIRY data format
2018 +       buf[4] = 31;            // Additional length
2019 +                               // No special options
2020 +       sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
2021 +                       (mod_data.cdrom ? product_cdrom_id :
2022 +                               product_disk_id),
2023 +                       mod_data.release);
2024 +       return 36;
2025 +}
2026 +
2027 +
2028 +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2029 +{
2030 +       struct fsg_lun  *curlun = fsg->curlun;
2031 +       u8              *buf = (u8 *) bh->buf;
2032 +       u32             sd, sdinfo;
2033 +       int             valid;
2034 +
2035 +       /*
2036 +        * From the SCSI-2 spec., section 7.9 (Unit attention condition):
2037 +        *
2038 +        * If a REQUEST SENSE command is received from an initiator
2039 +        * with a pending unit attention condition (before the target
2040 +        * generates the contingent allegiance condition), then the
2041 +        * target shall either:
2042 +        *   a) report any pending sense data and preserve the unit
2043 +        *      attention condition on the logical unit, or,
2044 +        *   b) report the unit attention condition, may discard any
2045 +        *      pending sense data, and clear the unit attention
2046 +        *      condition on the logical unit for that initiator.
2047 +        *
2048 +        * FSG normally uses option a); enable this code to use option b).
2049 +        */
2050 +#if 0
2051 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
2052 +               curlun->sense_data = curlun->unit_attention_data;
2053 +               curlun->unit_attention_data = SS_NO_SENSE;
2054 +       }
2055 +#endif
2056 +
2057 +       if (!curlun) {          // Unsupported LUNs are okay
2058 +               fsg->bad_lun_okay = 1;
2059 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2060 +               sdinfo = 0;
2061 +               valid = 0;
2062 +       } else {
2063 +               sd = curlun->sense_data;
2064 +               sdinfo = curlun->sense_data_info;
2065 +               valid = curlun->info_valid << 7;
2066 +               curlun->sense_data = SS_NO_SENSE;
2067 +               curlun->sense_data_info = 0;
2068 +               curlun->info_valid = 0;
2069 +       }
2070 +
2071 +       memset(buf, 0, 18);
2072 +       buf[0] = valid | 0x70;                  // Valid, current error
2073 +       buf[2] = SK(sd);
2074 +       put_unaligned_be32(sdinfo, &buf[3]);    /* Sense information */
2075 +       buf[7] = 18 - 8;                        // Additional sense length
2076 +       buf[12] = ASC(sd);
2077 +       buf[13] = ASCQ(sd);
2078 +       return 18;
2079 +}
2080 +
2081 +
2082 +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2083 +{
2084 +       struct fsg_lun  *curlun = fsg->curlun;
2085 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2086 +       int             pmi = fsg->cmnd[8];
2087 +       u8              *buf = (u8 *) bh->buf;
2088 +
2089 +       /* Check the PMI and LBA fields */
2090 +       if (pmi > 1 || (pmi == 0 && lba != 0)) {
2091 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2092 +               return -EINVAL;
2093 +       }
2094 +
2095 +       put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
2096 +                                               /* Max logical block */
2097 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2098 +       return 8;
2099 +}
2100 +
2101 +
2102 +static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2103 +{
2104 +       struct fsg_lun  *curlun = fsg->curlun;
2105 +       int             msf = fsg->cmnd[1] & 0x02;
2106 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2107 +       u8              *buf = (u8 *) bh->buf;
2108 +
2109 +       if ((fsg->cmnd[1] & ~0x02) != 0) {              /* Mask away MSF */
2110 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2111 +               return -EINVAL;
2112 +       }
2113 +       if (lba >= curlun->num_sectors) {
2114 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
2115 +               return -EINVAL;
2116 +       }
2117 +
2118 +       memset(buf, 0, 8);
2119 +       buf[0] = 0x01;          /* 2048 bytes of user data, rest is EC */
2120 +       store_cdrom_address(&buf[4], msf, lba);
2121 +       return 8;
2122 +}
2123 +
2124 +
2125 +static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2126 +{
2127 +       struct fsg_lun  *curlun = fsg->curlun;
2128 +       int             msf = fsg->cmnd[1] & 0x02;
2129 +       int             start_track = fsg->cmnd[6];
2130 +       u8              *buf = (u8 *) bh->buf;
2131 +
2132 +       if ((fsg->cmnd[1] & ~0x02) != 0 ||              /* Mask away MSF */
2133 +                       start_track > 1) {
2134 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2135 +               return -EINVAL;
2136 +       }
2137 +
2138 +       memset(buf, 0, 20);
2139 +       buf[1] = (20-2);                /* TOC data length */
2140 +       buf[2] = 1;                     /* First track number */
2141 +       buf[3] = 1;                     /* Last track number */
2142 +       buf[5] = 0x16;                  /* Data track, copying allowed */
2143 +       buf[6] = 0x01;                  /* Only track is number 1 */
2144 +       store_cdrom_address(&buf[8], msf, 0);
2145 +
2146 +       buf[13] = 0x16;                 /* Lead-out track is data */
2147 +       buf[14] = 0xAA;                 /* Lead-out track number */
2148 +       store_cdrom_address(&buf[16], msf, curlun->num_sectors);
2149 +       return 20;
2150 +}
2151 +
2152 +
2153 +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2154 +{
2155 +       struct fsg_lun  *curlun = fsg->curlun;
2156 +       int             mscmnd = fsg->cmnd[0];
2157 +       u8              *buf = (u8 *) bh->buf;
2158 +       u8              *buf0 = buf;
2159 +       int             pc, page_code;
2160 +       int             changeable_values, all_pages;
2161 +       int             valid_page = 0;
2162 +       int             len, limit;
2163 +
2164 +       if ((fsg->cmnd[1] & ~0x08) != 0) {              // Mask away DBD
2165 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2166 +               return -EINVAL;
2167 +       }
2168 +       pc = fsg->cmnd[2] >> 6;
2169 +       page_code = fsg->cmnd[2] & 0x3f;
2170 +       if (pc == 3) {
2171 +               curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
2172 +               return -EINVAL;
2173 +       }
2174 +       changeable_values = (pc == 1);
2175 +       all_pages = (page_code == 0x3f);
2176 +
2177 +       /* Write the mode parameter header.  Fixed values are: default
2178 +        * medium type, no cache control (DPOFUA), and no block descriptors.
2179 +        * The only variable value is the WriteProtect bit.  We will fill in
2180 +        * the mode data length later. */
2181 +       memset(buf, 0, 8);
2182 +       if (mscmnd == MODE_SENSE) {
2183 +               buf[2] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2184 +               buf += 4;
2185 +               limit = 255;
2186 +       } else {                        // MODE_SENSE_10
2187 +               buf[3] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2188 +               buf += 8;
2189 +               limit = 65535;          // Should really be mod_data.buflen
2190 +       }
2191 +
2192 +       /* No block descriptors */
2193 +
2194 +       /* The mode pages, in numerical order.  The only page we support
2195 +        * is the Caching page. */
2196 +       if (page_code == 0x08 || all_pages) {
2197 +               valid_page = 1;
2198 +               buf[0] = 0x08;          // Page code
2199 +               buf[1] = 10;            // Page length
2200 +               memset(buf+2, 0, 10);   // None of the fields are changeable
2201 +
2202 +               if (!changeable_values) {
2203 +                       buf[2] = 0x04;  // Write cache enable,
2204 +                                       // Read cache not disabled
2205 +                                       // No cache retention priorities
2206 +                       put_unaligned_be16(0xffff, &buf[4]);
2207 +                                       /* Don't disable prefetch */
2208 +                                       /* Minimum prefetch = 0 */
2209 +                       put_unaligned_be16(0xffff, &buf[8]);
2210 +                                       /* Maximum prefetch */
2211 +                       put_unaligned_be16(0xffff, &buf[10]);
2212 +                                       /* Maximum prefetch ceiling */
2213 +               }
2214 +               buf += 12;
2215 +       }
2216 +
2217 +       /* Check that a valid page was requested and the mode data length
2218 +        * isn't too long. */
2219 +       len = buf - buf0;
2220 +       if (!valid_page || len > limit) {
2221 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2222 +               return -EINVAL;
2223 +       }
2224 +
2225 +       /*  Store the mode data length */
2226 +       if (mscmnd == MODE_SENSE)
2227 +               buf0[0] = len - 1;
2228 +       else
2229 +               put_unaligned_be16(len - 2, buf0);
2230 +       return len;
2231 +}
2232 +
2233 +
2234 +static int do_start_stop(struct fsg_dev *fsg)
2235 +{
2236 +       struct fsg_lun  *curlun = fsg->curlun;
2237 +       int             loej, start;
2238 +
2239 +       if (!mod_data.removable) {
2240 +               curlun->sense_data = SS_INVALID_COMMAND;
2241 +               return -EINVAL;
2242 +       }
2243 +
2244 +       // int immed = fsg->cmnd[1] & 0x01;
2245 +       loej = fsg->cmnd[4] & 0x02;
2246 +       start = fsg->cmnd[4] & 0x01;
2247 +
2248 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
2249 +       if ((fsg->cmnd[1] & ~0x01) != 0 ||              // Mask away Immed
2250 +                       (fsg->cmnd[4] & ~0x03) != 0) {  // Mask LoEj, Start
2251 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2252 +               return -EINVAL;
2253 +       }
2254 +
2255 +       if (!start) {
2256 +
2257 +               /* Are we allowed to unload the media? */
2258 +               if (curlun->prevent_medium_removal) {
2259 +                       LDBG(curlun, "unload attempt prevented\n");
2260 +                       curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
2261 +                       return -EINVAL;
2262 +               }
2263 +               if (loej) {             // Simulate an unload/eject
2264 +                       up_read(&fsg->filesem);
2265 +                       down_write(&fsg->filesem);
2266 +                       fsg_lun_close(curlun);
2267 +                       up_write(&fsg->filesem);
2268 +                       down_read(&fsg->filesem);
2269 +               }
2270 +       } else {
2271 +
2272 +               /* Our emulation doesn't support mounting; the medium is
2273 +                * available for use as soon as it is loaded. */
2274 +               if (!fsg_lun_is_open(curlun)) {
2275 +                       curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2276 +                       return -EINVAL;
2277 +               }
2278 +       }
2279 +#endif
2280 +       return 0;
2281 +}
2282 +
2283 +
2284 +static int do_prevent_allow(struct fsg_dev *fsg)
2285 +{
2286 +       struct fsg_lun  *curlun = fsg->curlun;
2287 +       int             prevent;
2288 +
2289 +       if (!mod_data.removable) {
2290 +               curlun->sense_data = SS_INVALID_COMMAND;
2291 +               return -EINVAL;
2292 +       }
2293 +
2294 +       prevent = fsg->cmnd[4] & 0x01;
2295 +       if ((fsg->cmnd[4] & ~0x01) != 0) {              // Mask away Prevent
2296 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2297 +               return -EINVAL;
2298 +       }
2299 +
2300 +       if (curlun->prevent_medium_removal && !prevent)
2301 +               fsg_lun_fsync_sub(curlun);
2302 +       curlun->prevent_medium_removal = prevent;
2303 +       return 0;
2304 +}
2305 +
2306 +
2307 +static int do_read_format_capacities(struct fsg_dev *fsg,
2308 +                       struct fsg_buffhd *bh)
2309 +{
2310 +       struct fsg_lun  *curlun = fsg->curlun;
2311 +       u8              *buf = (u8 *) bh->buf;
2312 +
2313 +       buf[0] = buf[1] = buf[2] = 0;
2314 +       buf[3] = 8;             // Only the Current/Maximum Capacity Descriptor
2315 +       buf += 4;
2316 +
2317 +       put_unaligned_be32(curlun->num_sectors, &buf[0]);
2318 +                                               /* Number of blocks */
2319 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2320 +       buf[4] = 0x02;                          /* Current capacity */
2321 +       return 12;
2322 +}
2323 +
2324 +
2325 +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2326 +{
2327 +       struct fsg_lun  *curlun = fsg->curlun;
2328 +
2329 +       /* We don't support MODE SELECT */
2330 +       curlun->sense_data = SS_INVALID_COMMAND;
2331 +       return -EINVAL;
2332 +}
2333 +
2334 +
2335 +/*-------------------------------------------------------------------------*/
2336 +
2337 +static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
2338 +{
2339 +       int     rc;
2340 +
2341 +       rc = fsg_set_halt(fsg, fsg->bulk_in);
2342 +       if (rc == -EAGAIN)
2343 +               VDBG(fsg, "delayed bulk-in endpoint halt\n");
2344 +       while (rc != 0) {
2345 +               if (rc != -EAGAIN) {
2346 +                       WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
2347 +                       rc = 0;
2348 +                       break;
2349 +               }
2350 +
2351 +               /* Wait for a short time and then try again */
2352 +               if (msleep_interruptible(100) != 0)
2353 +                       return -EINTR;
2354 +               rc = usb_ep_set_halt(fsg->bulk_in);
2355 +       }
2356 +       return rc;
2357 +}
2358 +
2359 +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
2360 +{
2361 +       int     rc;
2362 +
2363 +       DBG(fsg, "bulk-in set wedge\n");
2364 +       rc = usb_ep_set_wedge(fsg->bulk_in);
2365 +       if (rc == -EAGAIN)
2366 +               VDBG(fsg, "delayed bulk-in endpoint wedge\n");
2367 +       while (rc != 0) {
2368 +               if (rc != -EAGAIN) {
2369 +                       WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
2370 +                       rc = 0;
2371 +                       break;
2372 +               }
2373 +
2374 +               /* Wait for a short time and then try again */
2375 +               if (msleep_interruptible(100) != 0)
2376 +                       return -EINTR;
2377 +               rc = usb_ep_set_wedge(fsg->bulk_in);
2378 +       }
2379 +       return rc;
2380 +}
2381 +
2382 +static int throw_away_data(struct fsg_dev *fsg)
2383 +{
2384 +       struct fsg_buffhd       *bh;
2385 +       u32                     amount;
2386 +       int                     rc;
2387 +
2388 +       while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
2389 +                       fsg->usb_amount_left > 0) {
2390 +
2391 +               /* Throw away the data in a filled buffer */
2392 +               if (bh->state == BUF_STATE_FULL) {
2393 +                       smp_rmb();
2394 +                       bh->state = BUF_STATE_EMPTY;
2395 +                       fsg->next_buffhd_to_drain = bh->next;
2396 +
2397 +                       /* A short packet or an error ends everything */
2398 +                       if (bh->outreq->actual < bh->bulk_out_intended_length ||
2399 +                                       bh->outreq->status != 0) {
2400 +                               raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2401 +                               return -EINTR;
2402 +                       }
2403 +                       continue;
2404 +               }
2405 +
2406 +               /* Try to submit another request if we need one */
2407 +               bh = fsg->next_buffhd_to_fill;
2408 +               if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
2409 +                       amount = min(fsg->usb_amount_left,
2410 +                                       (u32) mod_data.buflen);
2411 +
2412 +                       /* Except at the end of the transfer, amount will be
2413 +                        * equal to the buffer size, which is divisible by
2414 +                        * the bulk-out maxpacket size.
2415 +                        */
2416 +                       set_bulk_out_req_length(fsg, bh, amount);
2417 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
2418 +                                       &bh->outreq_busy, &bh->state);
2419 +                       fsg->next_buffhd_to_fill = bh->next;
2420 +                       fsg->usb_amount_left -= amount;
2421 +                       continue;
2422 +               }
2423 +
2424 +               /* Otherwise wait for something to happen */
2425 +               rc = sleep_thread(fsg);
2426 +               if (rc)
2427 +                       return rc;
2428 +       }
2429 +       return 0;
2430 +}
2431 +
2432 +
2433 +static int finish_reply(struct fsg_dev *fsg)
2434 +{
2435 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
2436 +       int                     rc = 0;
2437 +
2438 +       switch (fsg->data_dir) {
2439 +       case DATA_DIR_NONE:
2440 +               break;                  // Nothing to send
2441 +
2442 +       /* If we don't know whether the host wants to read or write,
2443 +        * this must be CB or CBI with an unknown command.  We mustn't
2444 +        * try to send or receive any data.  So stall both bulk pipes
2445 +        * if we can and wait for a reset. */
2446 +       case DATA_DIR_UNKNOWN:
2447 +               if (mod_data.can_stall) {
2448 +                       fsg_set_halt(fsg, fsg->bulk_out);
2449 +                       rc = halt_bulk_in_endpoint(fsg);
2450 +               }
2451 +               break;
2452 +
2453 +       /* All but the last buffer of data must have already been sent */
2454 +       case DATA_DIR_TO_HOST:
2455 +               if (fsg->data_size == 0)
2456 +                       ;               // Nothing to send
2457 +
2458 +               /* If there's no residue, simply send the last buffer */
2459 +               else if (fsg->residue == 0) {
2460 +                       bh->inreq->zero = 0;
2461 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2462 +                                       &bh->inreq_busy, &bh->state);
2463 +                       fsg->next_buffhd_to_fill = bh->next;
2464 +               }
2465 +
2466 +               /* There is a residue.  For CB and CBI, simply mark the end
2467 +                * of the data with a short packet.  However, if we are
2468 +                * allowed to stall, there was no data at all (residue ==
2469 +                * data_size), and the command failed (invalid LUN or
2470 +                * sense data is set), then halt the bulk-in endpoint
2471 +                * instead. */
2472 +               else if (!transport_is_bbb()) {
2473 +                       if (mod_data.can_stall &&
2474 +                                       fsg->residue == fsg->data_size &&
2475 +       (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
2476 +                               bh->state = BUF_STATE_EMPTY;
2477 +                               rc = halt_bulk_in_endpoint(fsg);
2478 +                       } else {
2479 +                               bh->inreq->zero = 1;
2480 +                               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2481 +                                               &bh->inreq_busy, &bh->state);
2482 +                               fsg->next_buffhd_to_fill = bh->next;
2483 +                       }
2484 +               }
2485 +
2486 +               /*
2487 +                * For Bulk-only, mark the end of the data with a short
2488 +                * packet.  If we are allowed to stall, halt the bulk-in
2489 +                * endpoint.  (Note: This violates the Bulk-Only Transport
2490 +                * specification, which requires us to pad the data if we
2491 +                * don't halt the endpoint.  Presumably nobody will mind.)
2492 +                */
2493 +               else {
2494 +                       bh->inreq->zero = 1;
2495 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2496 +                                       &bh->inreq_busy, &bh->state);
2497 +                       fsg->next_buffhd_to_fill = bh->next;
2498 +                       if (mod_data.can_stall)
2499 +                               rc = halt_bulk_in_endpoint(fsg);
2500 +               }
2501 +               break;
2502 +
2503 +       /* We have processed all we want from the data the host has sent.
2504 +        * There may still be outstanding bulk-out requests. */
2505 +       case DATA_DIR_FROM_HOST:
2506 +               if (fsg->residue == 0)
2507 +                       ;               // Nothing to receive
2508 +
2509 +               /* Did the host stop sending unexpectedly early? */
2510 +               else if (fsg->short_packet_received) {
2511 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2512 +                       rc = -EINTR;
2513 +               }
2514 +
2515 +               /* We haven't processed all the incoming data.  Even though
2516 +                * we may be allowed to stall, doing so would cause a race.
2517 +                * The controller may already have ACK'ed all the remaining
2518 +                * bulk-out packets, in which case the host wouldn't see a
2519 +                * STALL.  Not realizing the endpoint was halted, it wouldn't
2520 +                * clear the halt -- leading to problems later on. */
2521 +#if 0
2522 +               else if (mod_data.can_stall) {
2523 +                       fsg_set_halt(fsg, fsg->bulk_out);
2524 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2525 +                       rc = -EINTR;
2526 +               }
2527 +#endif
2528 +
2529 +               /* We can't stall.  Read in the excess data and throw it
2530 +                * all away. */
2531 +               else
2532 +                       rc = throw_away_data(fsg);
2533 +               break;
2534 +       }
2535 +       return rc;
2536 +}
2537 +
2538 +
2539 +static int send_status(struct fsg_dev *fsg)
2540 +{
2541 +       struct fsg_lun          *curlun = fsg->curlun;
2542 +       struct fsg_buffhd       *bh;
2543 +       int                     rc;
2544 +       u8                      status = US_BULK_STAT_OK;
2545 +       u32                     sd, sdinfo = 0;
2546 +
2547 +       /* Wait for the next buffer to become available */
2548 +       bh = fsg->next_buffhd_to_fill;
2549 +       while (bh->state != BUF_STATE_EMPTY) {
2550 +               rc = sleep_thread(fsg);
2551 +               if (rc)
2552 +                       return rc;
2553 +       }
2554 +
2555 +       if (curlun) {
2556 +               sd = curlun->sense_data;
2557 +               sdinfo = curlun->sense_data_info;
2558 +       } else if (fsg->bad_lun_okay)
2559 +               sd = SS_NO_SENSE;
2560 +       else
2561 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2562 +
2563 +       if (fsg->phase_error) {
2564 +               DBG(fsg, "sending phase-error status\n");
2565 +               status = US_BULK_STAT_PHASE;
2566 +               sd = SS_INVALID_COMMAND;
2567 +       } else if (sd != SS_NO_SENSE) {
2568 +               DBG(fsg, "sending command-failure status\n");
2569 +               status = US_BULK_STAT_FAIL;
2570 +               VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
2571 +                               "  info x%x\n",
2572 +                               SK(sd), ASC(sd), ASCQ(sd), sdinfo);
2573 +       }
2574 +
2575 +       if (transport_is_bbb()) {
2576 +               struct bulk_cs_wrap     *csw = bh->buf;
2577 +
2578 +               /* Store and send the Bulk-only CSW */
2579 +               csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
2580 +               csw->Tag = fsg->tag;
2581 +               csw->Residue = cpu_to_le32(fsg->residue);
2582 +               csw->Status = status;
2583 +
2584 +               bh->inreq->length = US_BULK_CS_WRAP_LEN;
2585 +               bh->inreq->zero = 0;
2586 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2587 +                               &bh->inreq_busy, &bh->state);
2588 +
2589 +       } else if (mod_data.transport_type == USB_PR_CB) {
2590 +
2591 +               /* Control-Bulk transport has no status phase! */
2592 +               return 0;
2593 +
2594 +       } else {                        // USB_PR_CBI
2595 +               struct interrupt_data   *buf = bh->buf;
2596 +
2597 +               /* Store and send the Interrupt data.  UFI sends the ASC
2598 +                * and ASCQ bytes.  Everything else sends a Type (which
2599 +                * is always 0) and the status Value. */
2600 +               if (mod_data.protocol_type == USB_SC_UFI) {
2601 +                       buf->bType = ASC(sd);
2602 +                       buf->bValue = ASCQ(sd);
2603 +               } else {
2604 +                       buf->bType = 0;
2605 +                       buf->bValue = status;
2606 +               }
2607 +               fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
2608 +
2609 +               fsg->intr_buffhd = bh;          // Point to the right buffhd
2610 +               fsg->intreq->buf = bh->inreq->buf;
2611 +               fsg->intreq->context = bh;
2612 +               start_transfer(fsg, fsg->intr_in, fsg->intreq,
2613 +                               &fsg->intreq_busy, &bh->state);
2614 +       }
2615 +
2616 +       fsg->next_buffhd_to_fill = bh->next;
2617 +       return 0;
2618 +}
2619 +
2620 +
2621 +/*-------------------------------------------------------------------------*/
2622 +
2623 +/* Check whether the command is properly formed and whether its data size
2624 + * and direction agree with the values we already have. */
2625 +static int check_command(struct fsg_dev *fsg, int cmnd_size,
2626 +               enum data_direction data_dir, unsigned int mask,
2627 +               int needs_medium, const char *name)
2628 +{
2629 +       int                     i;
2630 +       int                     lun = fsg->cmnd[1] >> 5;
2631 +       static const char       dirletter[4] = {'u', 'o', 'i', 'n'};
2632 +       char                    hdlen[20];
2633 +       struct fsg_lun          *curlun;
2634 +
2635 +       /* Adjust the expected cmnd_size for protocol encapsulation padding.
2636 +        * Transparent SCSI doesn't pad. */
2637 +       if (protocol_is_scsi())
2638 +               ;
2639 +
2640 +       /* There's some disagreement as to whether RBC pads commands or not.
2641 +        * We'll play it safe and accept either form. */
2642 +       else if (mod_data.protocol_type == USB_SC_RBC) {
2643 +               if (fsg->cmnd_size == 12)
2644 +                       cmnd_size = 12;
2645 +
2646 +       /* All the other protocols pad to 12 bytes */
2647 +       } else
2648 +               cmnd_size = 12;
2649 +
2650 +       hdlen[0] = 0;
2651 +       if (fsg->data_dir != DATA_DIR_UNKNOWN)
2652 +               sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
2653 +                               fsg->data_size);
2654 +       VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
2655 +                       name, cmnd_size, dirletter[(int) data_dir],
2656 +                       fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
2657 +
2658 +       /* We can't reply at all until we know the correct data direction
2659 +        * and size. */
2660 +       if (fsg->data_size_from_cmnd == 0)
2661 +               data_dir = DATA_DIR_NONE;
2662 +       if (fsg->data_dir == DATA_DIR_UNKNOWN) {        // CB or CBI
2663 +               fsg->data_dir = data_dir;
2664 +               fsg->data_size = fsg->data_size_from_cmnd;
2665 +
2666 +       } else {                                        // Bulk-only
2667 +               if (fsg->data_size < fsg->data_size_from_cmnd) {
2668 +
2669 +                       /* Host data size < Device data size is a phase error.
2670 +                        * Carry out the command, but only transfer as much
2671 +                        * as we are allowed. */
2672 +                       fsg->data_size_from_cmnd = fsg->data_size;
2673 +                       fsg->phase_error = 1;
2674 +               }
2675 +       }
2676 +       fsg->residue = fsg->usb_amount_left = fsg->data_size;
2677 +
2678 +       /* Conflicting data directions is a phase error */
2679 +       if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
2680 +               fsg->phase_error = 1;
2681 +               return -EINVAL;
2682 +       }
2683 +
2684 +       /* Verify the length of the command itself */
2685 +       if (cmnd_size != fsg->cmnd_size) {
2686 +
2687 +               /* Special case workaround: There are plenty of buggy SCSI
2688 +                * implementations. Many have issues with cbw->Length
2689 +                * field passing a wrong command size. For those cases we
2690 +                * always try to work around the problem by using the length
2691 +                * sent by the host side provided it is at least as large
2692 +                * as the correct command length.
2693 +                * Examples of such cases would be MS-Windows, which issues
2694 +                * REQUEST SENSE with cbw->Length == 12 where it should
2695 +                * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
2696 +                * REQUEST SENSE with cbw->Length == 10 where it should
2697 +                * be 6 as well.
2698 +                */
2699 +               if (cmnd_size <= fsg->cmnd_size) {
2700 +                       DBG(fsg, "%s is buggy! Expected length %d "
2701 +                                       "but we got %d\n", name,
2702 +                                       cmnd_size, fsg->cmnd_size);
2703 +                       cmnd_size = fsg->cmnd_size;
2704 +               } else {
2705 +                       fsg->phase_error = 1;
2706 +                       return -EINVAL;
2707 +               }
2708 +       }
2709 +
2710 +       /* Check that the LUN values are consistent */
2711 +       if (transport_is_bbb()) {
2712 +               if (fsg->lun != lun)
2713 +                       DBG(fsg, "using LUN %d from CBW, "
2714 +                                       "not LUN %d from CDB\n",
2715 +                                       fsg->lun, lun);
2716 +       }
2717 +
2718 +       /* Check the LUN */
2719 +       curlun = fsg->curlun;
2720 +       if (curlun) {
2721 +               if (fsg->cmnd[0] != REQUEST_SENSE) {
2722 +                       curlun->sense_data = SS_NO_SENSE;
2723 +                       curlun->sense_data_info = 0;
2724 +                       curlun->info_valid = 0;
2725 +               }
2726 +       } else {
2727 +               fsg->bad_lun_okay = 0;
2728 +
2729 +               /* INQUIRY and REQUEST SENSE commands are explicitly allowed
2730 +                * to use unsupported LUNs; all others may not. */
2731 +               if (fsg->cmnd[0] != INQUIRY &&
2732 +                               fsg->cmnd[0] != REQUEST_SENSE) {
2733 +                       DBG(fsg, "unsupported LUN %d\n", fsg->lun);
2734 +                       return -EINVAL;
2735 +               }
2736 +       }
2737 +
2738 +       /* If a unit attention condition exists, only INQUIRY and
2739 +        * REQUEST SENSE commands are allowed; anything else must fail. */
2740 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
2741 +                       fsg->cmnd[0] != INQUIRY &&
2742 +                       fsg->cmnd[0] != REQUEST_SENSE) {
2743 +               curlun->sense_data = curlun->unit_attention_data;
2744 +               curlun->unit_attention_data = SS_NO_SENSE;
2745 +               return -EINVAL;
2746 +       }
2747 +
2748 +       /* Check that only command bytes listed in the mask are non-zero */
2749 +       fsg->cmnd[1] &= 0x1f;                   // Mask away the LUN
2750 +       for (i = 1; i < cmnd_size; ++i) {
2751 +               if (fsg->cmnd[i] && !(mask & (1 << i))) {
2752 +                       if (curlun)
2753 +                               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2754 +                       return -EINVAL;
2755 +               }
2756 +       }
2757 +
2758 +       /* If the medium isn't mounted and the command needs to access
2759 +        * it, return an error. */
2760 +       if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
2761 +               curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2762 +               return -EINVAL;
2763 +       }
2764 +
2765 +       return 0;
2766 +}
2767 +
2768 +/* wrapper of check_command for data size in blocks handling */
2769 +static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
2770 +               enum data_direction data_dir, unsigned int mask,
2771 +               int needs_medium, const char *name)
2772 +{
2773 +       if (fsg->curlun)
2774 +               fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
2775 +       return check_command(fsg, cmnd_size, data_dir,
2776 +                       mask, needs_medium, name);
2777 +}
2778 +
2779 +static int do_scsi_command(struct fsg_dev *fsg)
2780 +{
2781 +       struct fsg_buffhd       *bh;
2782 +       int                     rc;
2783 +       int                     reply = -EINVAL;
2784 +       int                     i;
2785 +       static char             unknown[16];
2786 +
2787 +       dump_cdb(fsg);
2788 +
2789 +       /* Wait for the next buffer to become available for data or status */
2790 +       bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
2791 +       while (bh->state != BUF_STATE_EMPTY) {
2792 +               rc = sleep_thread(fsg);
2793 +               if (rc)
2794 +                       return rc;
2795 +       }
2796 +       fsg->phase_error = 0;
2797 +       fsg->short_packet_received = 0;
2798 +
2799 +       down_read(&fsg->filesem);       // We're using the backing file
2800 +       switch (fsg->cmnd[0]) {
2801 +
2802 +       case INQUIRY:
2803 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2804 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2805 +                               (1<<4), 0,
2806 +                               "INQUIRY")) == 0)
2807 +                       reply = do_inquiry(fsg, bh);
2808 +               break;
2809 +
2810 +       case MODE_SELECT:
2811 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2812 +               if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
2813 +                               (1<<1) | (1<<4), 0,
2814 +                               "MODE SELECT(6)")) == 0)
2815 +                       reply = do_mode_select(fsg, bh);
2816 +               break;
2817 +
2818 +       case MODE_SELECT_10:
2819 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2820 +               if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
2821 +                               (1<<1) | (3<<7), 0,
2822 +                               "MODE SELECT(10)")) == 0)
2823 +                       reply = do_mode_select(fsg, bh);
2824 +               break;
2825 +
2826 +       case MODE_SENSE:
2827 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2828 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2829 +                               (1<<1) | (1<<2) | (1<<4), 0,
2830 +                               "MODE SENSE(6)")) == 0)
2831 +                       reply = do_mode_sense(fsg, bh);
2832 +               break;
2833 +
2834 +       case MODE_SENSE_10:
2835 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2836 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2837 +                               (1<<1) | (1<<2) | (3<<7), 0,
2838 +                               "MODE SENSE(10)")) == 0)
2839 +                       reply = do_mode_sense(fsg, bh);
2840 +               break;
2841 +
2842 +       case ALLOW_MEDIUM_REMOVAL:
2843 +               fsg->data_size_from_cmnd = 0;
2844 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2845 +                               (1<<4), 0,
2846 +                               "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
2847 +                       reply = do_prevent_allow(fsg);
2848 +               break;
2849 +
2850 +       case READ_6:
2851 +               i = fsg->cmnd[4];
2852 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2853 +               if ((reply = check_command_size_in_blocks(fsg, 6,
2854 +                               DATA_DIR_TO_HOST,
2855 +                               (7<<1) | (1<<4), 1,
2856 +                               "READ(6)")) == 0)
2857 +                       reply = do_read(fsg);
2858 +               break;
2859 +
2860 +       case READ_10:
2861 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2862 +               if ((reply = check_command_size_in_blocks(fsg, 10,
2863 +                               DATA_DIR_TO_HOST,
2864 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2865 +                               "READ(10)")) == 0)
2866 +                       reply = do_read(fsg);
2867 +               break;
2868 +
2869 +       case READ_12:
2870 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2871 +               if ((reply = check_command_size_in_blocks(fsg, 12,
2872 +                               DATA_DIR_TO_HOST,
2873 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
2874 +                               "READ(12)")) == 0)
2875 +                       reply = do_read(fsg);
2876 +               break;
2877 +
2878 +       case READ_CAPACITY:
2879 +               fsg->data_size_from_cmnd = 8;
2880 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2881 +                               (0xf<<2) | (1<<8), 1,
2882 +                               "READ CAPACITY")) == 0)
2883 +                       reply = do_read_capacity(fsg, bh);
2884 +               break;
2885 +
2886 +       case READ_HEADER:
2887 +               if (!mod_data.cdrom)
2888 +                       goto unknown_cmnd;
2889 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2890 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2891 +                               (3<<7) | (0x1f<<1), 1,
2892 +                               "READ HEADER")) == 0)
2893 +                       reply = do_read_header(fsg, bh);
2894 +               break;
2895 +
2896 +       case READ_TOC:
2897 +               if (!mod_data.cdrom)
2898 +                       goto unknown_cmnd;
2899 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2900 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2901 +                               (7<<6) | (1<<1), 1,
2902 +                               "READ TOC")) == 0)
2903 +                       reply = do_read_toc(fsg, bh);
2904 +               break;
2905 +
2906 +       case READ_FORMAT_CAPACITIES:
2907 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2908 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2909 +                               (3<<7), 1,
2910 +                               "READ FORMAT CAPACITIES")) == 0)
2911 +                       reply = do_read_format_capacities(fsg, bh);
2912 +               break;
2913 +
2914 +       case REQUEST_SENSE:
2915 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2916 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2917 +                               (1<<4), 0,
2918 +                               "REQUEST SENSE")) == 0)
2919 +                       reply = do_request_sense(fsg, bh);
2920 +               break;
2921 +
2922 +       case START_STOP:
2923 +               fsg->data_size_from_cmnd = 0;
2924 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2925 +                               (1<<1) | (1<<4), 0,
2926 +                               "START-STOP UNIT")) == 0)
2927 +                       reply = do_start_stop(fsg);
2928 +               break;
2929 +
2930 +       case SYNCHRONIZE_CACHE:
2931 +               fsg->data_size_from_cmnd = 0;
2932 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2933 +                               (0xf<<2) | (3<<7), 1,
2934 +                               "SYNCHRONIZE CACHE")) == 0)
2935 +                       reply = do_synchronize_cache(fsg);
2936 +               break;
2937 +
2938 +       case TEST_UNIT_READY:
2939 +               fsg->data_size_from_cmnd = 0;
2940 +               reply = check_command(fsg, 6, DATA_DIR_NONE,
2941 +                               0, 1,
2942 +                               "TEST UNIT READY");
2943 +               break;
2944 +
2945 +       /* Although optional, this command is used by MS-Windows.  We
2946 +        * support a minimal version: BytChk must be 0. */
2947 +       case VERIFY:
2948 +               fsg->data_size_from_cmnd = 0;
2949 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2950 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2951 +                               "VERIFY")) == 0)
2952 +                       reply = do_verify(fsg);
2953 +               break;
2954 +
2955 +       case WRITE_6:
2956 +               i = fsg->cmnd[4];
2957 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2958 +               if ((reply = check_command_size_in_blocks(fsg, 6,
2959 +                               DATA_DIR_FROM_HOST,
2960 +                               (7<<1) | (1<<4), 1,
2961 +                               "WRITE(6)")) == 0)
2962 +                       reply = do_write(fsg);
2963 +               break;
2964 +
2965 +       case WRITE_10:
2966 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2967 +               if ((reply = check_command_size_in_blocks(fsg, 10,
2968 +                               DATA_DIR_FROM_HOST,
2969 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2970 +                               "WRITE(10)")) == 0)
2971 +                       reply = do_write(fsg);
2972 +               break;
2973 +
2974 +       case WRITE_12:
2975 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2976 +               if ((reply = check_command_size_in_blocks(fsg, 12,
2977 +                               DATA_DIR_FROM_HOST,
2978 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
2979 +                               "WRITE(12)")) == 0)
2980 +                       reply = do_write(fsg);
2981 +               break;
2982 +
2983 +       /* Some mandatory commands that we recognize but don't implement.
2984 +        * They don't mean much in this setting.  It's left as an exercise
2985 +        * for anyone interested to implement RESERVE and RELEASE in terms
2986 +        * of Posix locks. */
2987 +       case FORMAT_UNIT:
2988 +       case RELEASE:
2989 +       case RESERVE:
2990 +       case SEND_DIAGNOSTIC:
2991 +               // Fall through
2992 +
2993 +       default:
2994 + unknown_cmnd:
2995 +               fsg->data_size_from_cmnd = 0;
2996 +               sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
2997 +               if ((reply = check_command(fsg, fsg->cmnd_size,
2998 +                               DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
2999 +                       fsg->curlun->sense_data = SS_INVALID_COMMAND;
3000 +                       reply = -EINVAL;
3001 +               }
3002 +               break;
3003 +       }
3004 +       up_read(&fsg->filesem);
3005 +
3006 +       if (reply == -EINTR || signal_pending(current))
3007 +               return -EINTR;
3008 +
3009 +       /* Set up the single reply buffer for finish_reply() */
3010 +       if (reply == -EINVAL)
3011 +               reply = 0;              // Error reply length
3012 +       if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
3013 +               reply = min((u32) reply, fsg->data_size_from_cmnd);
3014 +               bh->inreq->length = reply;
3015 +               bh->state = BUF_STATE_FULL;
3016 +               fsg->residue -= reply;
3017 +       }                               // Otherwise it's already set
3018 +
3019 +       return 0;
3020 +}
3021 +
3022 +
3023 +/*-------------------------------------------------------------------------*/
3024 +
3025 +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
3026 +{
3027 +       struct usb_request              *req = bh->outreq;
3028 +       struct bulk_cb_wrap     *cbw = req->buf;
3029 +
3030 +       /* Was this a real packet?  Should it be ignored? */
3031 +       if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3032 +               return -EINVAL;
3033 +
3034 +       /* Is the CBW valid? */
3035 +       if (req->actual != US_BULK_CB_WRAP_LEN ||
3036 +                       cbw->Signature != cpu_to_le32(
3037 +                               US_BULK_CB_SIGN)) {
3038 +               DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
3039 +                               req->actual,
3040 +                               le32_to_cpu(cbw->Signature));
3041 +
3042 +               /* The Bulk-only spec says we MUST stall the IN endpoint
3043 +                * (6.6.1), so it's unavoidable.  It also says we must
3044 +                * retain this state until the next reset, but there's
3045 +                * no way to tell the controller driver it should ignore
3046 +                * Clear-Feature(HALT) requests.
3047 +                *
3048 +                * We aren't required to halt the OUT endpoint; instead
3049 +                * we can simply accept and discard any data received
3050 +                * until the next reset. */
3051 +               wedge_bulk_in_endpoint(fsg);
3052 +               set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3053 +               return -EINVAL;
3054 +       }
3055 +
3056 +       /* Is the CBW meaningful? */
3057 +       if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
3058 +                       cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
3059 +               DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
3060 +                               "cmdlen %u\n",
3061 +                               cbw->Lun, cbw->Flags, cbw->Length);
3062 +
3063 +               /* We can do anything we want here, so let's stall the
3064 +                * bulk pipes if we are allowed to. */
3065 +               if (mod_data.can_stall) {
3066 +                       fsg_set_halt(fsg, fsg->bulk_out);
3067 +                       halt_bulk_in_endpoint(fsg);
3068 +               }
3069 +               return -EINVAL;
3070 +       }
3071 +
3072 +       /* Save the command for later */
3073 +       fsg->cmnd_size = cbw->Length;
3074 +       memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
3075 +       if (cbw->Flags & US_BULK_FLAG_IN)
3076 +               fsg->data_dir = DATA_DIR_TO_HOST;
3077 +       else
3078 +               fsg->data_dir = DATA_DIR_FROM_HOST;
3079 +       fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
3080 +       if (fsg->data_size == 0)
3081 +               fsg->data_dir = DATA_DIR_NONE;
3082 +       fsg->lun = cbw->Lun;
3083 +       fsg->tag = cbw->Tag;
3084 +       return 0;
3085 +}
3086 +
3087 +
3088 +static int get_next_command(struct fsg_dev *fsg)
3089 +{
3090 +       struct fsg_buffhd       *bh;
3091 +       int                     rc = 0;
3092 +
3093 +       if (transport_is_bbb()) {
3094 +
3095 +               /* Wait for the next buffer to become available */
3096 +               bh = fsg->next_buffhd_to_fill;
3097 +               while (bh->state != BUF_STATE_EMPTY) {
3098 +                       rc = sleep_thread(fsg);
3099 +                       if (rc)
3100 +                               return rc;
3101 +               }
3102 +
3103 +               /* Queue a request to read a Bulk-only CBW */
3104 +               set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
3105 +               start_transfer(fsg, fsg->bulk_out, bh->outreq,
3106 +                               &bh->outreq_busy, &bh->state);
3107 +
3108 +               /* We will drain the buffer in software, which means we
3109 +                * can reuse it for the next filling.  No need to advance
3110 +                * next_buffhd_to_fill. */
3111 +
3112 +               /* Wait for the CBW to arrive */
3113 +               while (bh->state != BUF_STATE_FULL) {
3114 +                       rc = sleep_thread(fsg);
3115 +                       if (rc)
3116 +                               return rc;
3117 +               }
3118 +               smp_rmb();
3119 +               rc = received_cbw(fsg, bh);
3120 +               bh->state = BUF_STATE_EMPTY;
3121 +
3122 +       } else {                // USB_PR_CB or USB_PR_CBI
3123 +
3124 +               /* Wait for the next command to arrive */
3125 +               while (fsg->cbbuf_cmnd_size == 0) {
3126 +                       rc = sleep_thread(fsg);
3127 +                       if (rc)
3128 +                               return rc;
3129 +               }
3130 +
3131 +               /* Is the previous status interrupt request still busy?
3132 +                * The host is allowed to skip reading the status,
3133 +                * so we must cancel it. */
3134 +               if (fsg->intreq_busy)
3135 +                       usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3136 +
3137 +               /* Copy the command and mark the buffer empty */
3138 +               fsg->data_dir = DATA_DIR_UNKNOWN;
3139 +               spin_lock_irq(&fsg->lock);
3140 +               fsg->cmnd_size = fsg->cbbuf_cmnd_size;
3141 +               memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
3142 +               fsg->cbbuf_cmnd_size = 0;
3143 +               spin_unlock_irq(&fsg->lock);
3144 +
3145 +               /* Use LUN from the command */
3146 +               fsg->lun = fsg->cmnd[1] >> 5;
3147 +       }
3148 +
3149 +       /* Update current lun */
3150 +       if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
3151 +               fsg->curlun = &fsg->luns[fsg->lun];
3152 +       else
3153 +               fsg->curlun = NULL;
3154 +
3155 +       return rc;
3156 +}
3157 +
3158 +
3159 +/*-------------------------------------------------------------------------*/
3160 +
3161 +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
3162 +               const struct usb_endpoint_descriptor *d)
3163 +{
3164 +       int     rc;
3165 +
3166 +       ep->driver_data = fsg;
3167 +       ep->desc = d;
3168 +       rc = usb_ep_enable(ep);
3169 +       if (rc)
3170 +               ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
3171 +       return rc;
3172 +}
3173 +
3174 +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
3175 +               struct usb_request **preq)
3176 +{
3177 +       *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
3178 +       if (*preq)
3179 +               return 0;
3180 +       ERROR(fsg, "can't allocate request for %s\n", ep->name);
3181 +       return -ENOMEM;
3182 +}
3183 +
3184 +/*
3185 + * Reset interface setting and re-init endpoint state (toggle etc).
3186 + * Call with altsetting < 0 to disable the interface.  The only other
3187 + * available altsetting is 0, which enables the interface.
3188 + */
3189 +static int do_set_interface(struct fsg_dev *fsg, int altsetting)
3190 +{
3191 +       int     rc = 0;
3192 +       int     i;
3193 +       const struct usb_endpoint_descriptor    *d;
3194 +
3195 +       if (fsg->running)
3196 +               DBG(fsg, "reset interface\n");
3197 +
3198 +reset:
3199 +       /* Deallocate the requests */
3200 +       for (i = 0; i < fsg_num_buffers; ++i) {
3201 +               struct fsg_buffhd *bh = &fsg->buffhds[i];
3202 +
3203 +               if (bh->inreq) {
3204 +                       usb_ep_free_request(fsg->bulk_in, bh->inreq);
3205 +                       bh->inreq = NULL;
3206 +               }
3207 +               if (bh->outreq) {
3208 +                       usb_ep_free_request(fsg->bulk_out, bh->outreq);
3209 +                       bh->outreq = NULL;
3210 +               }
3211 +       }
3212 +       if (fsg->intreq) {
3213 +               usb_ep_free_request(fsg->intr_in, fsg->intreq);
3214 +               fsg->intreq = NULL;
3215 +       }
3216 +
3217 +       /* Disable the endpoints */
3218 +       if (fsg->bulk_in_enabled) {
3219 +               usb_ep_disable(fsg->bulk_in);
3220 +               fsg->bulk_in_enabled = 0;
3221 +       }
3222 +       if (fsg->bulk_out_enabled) {
3223 +               usb_ep_disable(fsg->bulk_out);
3224 +               fsg->bulk_out_enabled = 0;
3225 +       }
3226 +       if (fsg->intr_in_enabled) {
3227 +               usb_ep_disable(fsg->intr_in);
3228 +               fsg->intr_in_enabled = 0;
3229 +       }
3230 +
3231 +       fsg->running = 0;
3232 +       if (altsetting < 0 || rc != 0)
3233 +               return rc;
3234 +
3235 +       DBG(fsg, "set interface %d\n", altsetting);
3236 +
3237 +       /* Enable the endpoints */
3238 +       d = fsg_ep_desc(fsg->gadget,
3239 +                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
3240 +                       &fsg_ss_bulk_in_desc);
3241 +       if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
3242 +               goto reset;
3243 +       fsg->bulk_in_enabled = 1;
3244 +
3245 +       d = fsg_ep_desc(fsg->gadget,
3246 +                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
3247 +                       &fsg_ss_bulk_out_desc);
3248 +       if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
3249 +               goto reset;
3250 +       fsg->bulk_out_enabled = 1;
3251 +       fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
3252 +       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3253 +
3254 +       if (transport_is_cbi()) {
3255 +               d = fsg_ep_desc(fsg->gadget,
3256 +                               &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
3257 +                               &fsg_ss_intr_in_desc);
3258 +               if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
3259 +                       goto reset;
3260 +               fsg->intr_in_enabled = 1;
3261 +       }
3262 +
3263 +       /* Allocate the requests */
3264 +       for (i = 0; i < fsg_num_buffers; ++i) {
3265 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3266 +
3267 +               if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
3268 +                       goto reset;
3269 +               if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
3270 +                       goto reset;
3271 +               bh->inreq->buf = bh->outreq->buf = bh->buf;
3272 +               bh->inreq->context = bh->outreq->context = bh;
3273 +               bh->inreq->complete = bulk_in_complete;
3274 +               bh->outreq->complete = bulk_out_complete;
3275 +       }
3276 +       if (transport_is_cbi()) {
3277 +               if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
3278 +                       goto reset;
3279 +               fsg->intreq->complete = intr_in_complete;
3280 +       }
3281 +
3282 +       fsg->running = 1;
3283 +       for (i = 0; i < fsg->nluns; ++i)
3284 +               fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3285 +       return rc;
3286 +}
3287 +
3288 +
3289 +/*
3290 + * Change our operational configuration.  This code must agree with the code
3291 + * that returns config descriptors, and with interface altsetting code.
3292 + *
3293 + * It's also responsible for power management interactions.  Some
3294 + * configurations might not work with our current power sources.
3295 + * For now we just assume the gadget is always self-powered.
3296 + */
3297 +static int do_set_config(struct fsg_dev *fsg, u8 new_config)
3298 +{
3299 +       int     rc = 0;
3300 +
3301 +       /* Disable the single interface */
3302 +       if (fsg->config != 0) {
3303 +               DBG(fsg, "reset config\n");
3304 +               fsg->config = 0;
3305 +               rc = do_set_interface(fsg, -1);
3306 +       }
3307 +
3308 +       /* Enable the interface */
3309 +       if (new_config != 0) {
3310 +               fsg->config = new_config;
3311 +               if ((rc = do_set_interface(fsg, 0)) != 0)
3312 +                       fsg->config = 0;        // Reset on errors
3313 +               else
3314 +                       INFO(fsg, "%s config #%d\n",
3315 +                            usb_speed_string(fsg->gadget->speed),
3316 +                            fsg->config);
3317 +       }
3318 +       return rc;
3319 +}
3320 +
3321 +
3322 +/*-------------------------------------------------------------------------*/
3323 +
3324 +static void handle_exception(struct fsg_dev *fsg)
3325 +{
3326 +       siginfo_t               info;
3327 +       int                     sig;
3328 +       int                     i;
3329 +       int                     num_active;
3330 +       struct fsg_buffhd       *bh;
3331 +       enum fsg_state          old_state;
3332 +       u8                      new_config;
3333 +       struct fsg_lun          *curlun;
3334 +       unsigned int            exception_req_tag;
3335 +       int                     rc;
3336 +
3337 +       /* Clear the existing signals.  Anything but SIGUSR1 is converted
3338 +        * into a high-priority EXIT exception. */
3339 +       for (;;) {
3340 +               sig = dequeue_signal_lock(current, &current->blocked, &info);
3341 +               if (!sig)
3342 +                       break;
3343 +               if (sig != SIGUSR1) {
3344 +                       if (fsg->state < FSG_STATE_EXIT)
3345 +                               DBG(fsg, "Main thread exiting on signal\n");
3346 +                       raise_exception(fsg, FSG_STATE_EXIT);
3347 +               }
3348 +       }
3349 +
3350 +       /* Cancel all the pending transfers */
3351 +       if (fsg->intreq_busy)
3352 +               usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3353 +       for (i = 0; i < fsg_num_buffers; ++i) {
3354 +               bh = &fsg->buffhds[i];
3355 +               if (bh->inreq_busy)
3356 +                       usb_ep_dequeue(fsg->bulk_in, bh->inreq);
3357 +               if (bh->outreq_busy)
3358 +                       usb_ep_dequeue(fsg->bulk_out, bh->outreq);
3359 +       }
3360 +
3361 +       /* Wait until everything is idle */
3362 +       for (;;) {
3363 +               num_active = fsg->intreq_busy;
3364 +               for (i = 0; i < fsg_num_buffers; ++i) {
3365 +                       bh = &fsg->buffhds[i];
3366 +                       num_active += bh->inreq_busy + bh->outreq_busy;
3367 +               }
3368 +               if (num_active == 0)
3369 +                       break;
3370 +               if (sleep_thread(fsg))
3371 +                       return;
3372 +       }
3373 +
3374 +       /* Clear out the controller's fifos */
3375 +       if (fsg->bulk_in_enabled)
3376 +               usb_ep_fifo_flush(fsg->bulk_in);
3377 +       if (fsg->bulk_out_enabled)
3378 +               usb_ep_fifo_flush(fsg->bulk_out);
3379 +       if (fsg->intr_in_enabled)
3380 +               usb_ep_fifo_flush(fsg->intr_in);
3381 +
3382 +       /* Reset the I/O buffer states and pointers, the SCSI
3383 +        * state, and the exception.  Then invoke the handler. */
3384 +       spin_lock_irq(&fsg->lock);
3385 +
3386 +       for (i = 0; i < fsg_num_buffers; ++i) {
3387 +               bh = &fsg->buffhds[i];
3388 +               bh->state = BUF_STATE_EMPTY;
3389 +       }
3390 +       fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
3391 +                       &fsg->buffhds[0];
3392 +
3393 +       exception_req_tag = fsg->exception_req_tag;
3394 +       new_config = fsg->new_config;
3395 +       old_state = fsg->state;
3396 +
3397 +       if (old_state == FSG_STATE_ABORT_BULK_OUT)
3398 +               fsg->state = FSG_STATE_STATUS_PHASE;
3399 +       else {
3400 +               for (i = 0; i < fsg->nluns; ++i) {
3401 +                       curlun = &fsg->luns[i];
3402 +                       curlun->prevent_medium_removal = 0;
3403 +                       curlun->sense_data = curlun->unit_attention_data =
3404 +                                       SS_NO_SENSE;
3405 +                       curlun->sense_data_info = 0;
3406 +                       curlun->info_valid = 0;
3407 +               }
3408 +               fsg->state = FSG_STATE_IDLE;
3409 +       }
3410 +       spin_unlock_irq(&fsg->lock);
3411 +
3412 +       /* Carry out any extra actions required for the exception */
3413 +       switch (old_state) {
3414 +       default:
3415 +               break;
3416 +
3417 +       case FSG_STATE_ABORT_BULK_OUT:
3418 +               send_status(fsg);
3419 +               spin_lock_irq(&fsg->lock);
3420 +               if (fsg->state == FSG_STATE_STATUS_PHASE)
3421 +                       fsg->state = FSG_STATE_IDLE;
3422 +               spin_unlock_irq(&fsg->lock);
3423 +               break;
3424 +
3425 +       case FSG_STATE_RESET:
3426 +               /* In case we were forced against our will to halt a
3427 +                * bulk endpoint, clear the halt now.  (The SuperH UDC
3428 +                * requires this.) */
3429 +               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3430 +                       usb_ep_clear_halt(fsg->bulk_in);
3431 +
3432 +               if (transport_is_bbb()) {
3433 +                       if (fsg->ep0_req_tag == exception_req_tag)
3434 +                               ep0_queue(fsg); // Complete the status stage
3435 +
3436 +               } else if (transport_is_cbi())
3437 +                       send_status(fsg);       // Status by interrupt pipe
3438 +
3439 +               /* Technically this should go here, but it would only be
3440 +                * a waste of time.  Ditto for the INTERFACE_CHANGE and
3441 +                * CONFIG_CHANGE cases. */
3442 +               // for (i = 0; i < fsg->nluns; ++i)
3443 +               //      fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3444 +               break;
3445 +
3446 +       case FSG_STATE_INTERFACE_CHANGE:
3447 +               rc = do_set_interface(fsg, 0);
3448 +               if (fsg->ep0_req_tag != exception_req_tag)
3449 +                       break;
3450 +               if (rc != 0)                    // STALL on errors
3451 +                       fsg_set_halt(fsg, fsg->ep0);
3452 +               else                            // Complete the status stage
3453 +                       ep0_queue(fsg);
3454 +               break;
3455 +
3456 +       case FSG_STATE_CONFIG_CHANGE:
3457 +               rc = do_set_config(fsg, new_config);
3458 +               if (fsg->ep0_req_tag != exception_req_tag)
3459 +                       break;
3460 +               if (rc != 0)                    // STALL on errors
3461 +                       fsg_set_halt(fsg, fsg->ep0);
3462 +               else                            // Complete the status stage
3463 +                       ep0_queue(fsg);
3464 +               break;
3465 +
3466 +       case FSG_STATE_DISCONNECT:
3467 +               for (i = 0; i < fsg->nluns; ++i)
3468 +                       fsg_lun_fsync_sub(fsg->luns + i);
3469 +               do_set_config(fsg, 0);          // Unconfigured state
3470 +               break;
3471 +
3472 +       case FSG_STATE_EXIT:
3473 +       case FSG_STATE_TERMINATED:
3474 +               do_set_config(fsg, 0);                  // Free resources
3475 +               spin_lock_irq(&fsg->lock);
3476 +               fsg->state = FSG_STATE_TERMINATED;      // Stop the thread
3477 +               spin_unlock_irq(&fsg->lock);
3478 +               break;
3479 +       }
3480 +}
3481 +
3482 +
3483 +/*-------------------------------------------------------------------------*/
3484 +
3485 +static int fsg_main_thread(void *fsg_)
3486 +{
3487 +       struct fsg_dev          *fsg = fsg_;
3488 +
3489 +       /* Allow the thread to be killed by a signal, but set the signal mask
3490 +        * to block everything but INT, TERM, KILL, and USR1. */
3491 +       allow_signal(SIGINT);
3492 +       allow_signal(SIGTERM);
3493 +       allow_signal(SIGKILL);
3494 +       allow_signal(SIGUSR1);
3495 +
3496 +       /* Allow the thread to be frozen */
3497 +       set_freezable();
3498 +
3499 +       /* Arrange for userspace references to be interpreted as kernel
3500 +        * pointers.  That way we can pass a kernel pointer to a routine
3501 +        * that expects a __user pointer and it will work okay. */
3502 +       set_fs(get_ds());
3503 +
3504 +       /* The main loop */
3505 +       while (fsg->state != FSG_STATE_TERMINATED) {
3506 +               if (exception_in_progress(fsg) || signal_pending(current)) {
3507 +                       handle_exception(fsg);
3508 +                       continue;
3509 +               }
3510 +
3511 +               if (!fsg->running) {
3512 +                       sleep_thread(fsg);
3513 +                       continue;
3514 +               }
3515 +
3516 +               if (get_next_command(fsg))
3517 +                       continue;
3518 +
3519 +               spin_lock_irq(&fsg->lock);
3520 +               if (!exception_in_progress(fsg))
3521 +                       fsg->state = FSG_STATE_DATA_PHASE;
3522 +               spin_unlock_irq(&fsg->lock);
3523 +
3524 +               if (do_scsi_command(fsg) || finish_reply(fsg))
3525 +                       continue;
3526 +
3527 +               spin_lock_irq(&fsg->lock);
3528 +               if (!exception_in_progress(fsg))
3529 +                       fsg->state = FSG_STATE_STATUS_PHASE;
3530 +               spin_unlock_irq(&fsg->lock);
3531 +
3532 +               if (send_status(fsg))
3533 +                       continue;
3534 +
3535 +               spin_lock_irq(&fsg->lock);
3536 +               if (!exception_in_progress(fsg))
3537 +                       fsg->state = FSG_STATE_IDLE;
3538 +               spin_unlock_irq(&fsg->lock);
3539 +               }
3540 +
3541 +       spin_lock_irq(&fsg->lock);
3542 +       fsg->thread_task = NULL;
3543 +       spin_unlock_irq(&fsg->lock);
3544 +
3545 +       /* If we are exiting because of a signal, unregister the
3546 +        * gadget driver. */
3547 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
3548 +               usb_gadget_unregister_driver(&fsg_driver);
3549 +
3550 +       /* Let the unbind and cleanup routines know the thread has exited */
3551 +       complete_and_exit(&fsg->thread_notifier, 0);
3552 +}
3553 +
3554 +
3555 +/*-------------------------------------------------------------------------*/
3556 +
3557 +
3558 +/* The write permissions and store_xxx pointers are set in fsg_bind() */
3559 +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
3560 +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
3561 +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
3562 +
3563 +
3564 +/*-------------------------------------------------------------------------*/
3565 +
3566 +static void fsg_release(struct kref *ref)
3567 +{
3568 +       struct fsg_dev  *fsg = container_of(ref, struct fsg_dev, ref);
3569 +
3570 +       kfree(fsg->luns);
3571 +       kfree(fsg);
3572 +}
3573 +
3574 +static void lun_release(struct device *dev)
3575 +{
3576 +       struct rw_semaphore     *filesem = dev_get_drvdata(dev);
3577 +       struct fsg_dev          *fsg =
3578 +               container_of(filesem, struct fsg_dev, filesem);
3579 +
3580 +       kref_put(&fsg->ref, fsg_release);
3581 +}
3582 +
3583 +static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
3584 +{
3585 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
3586 +       int                     i;
3587 +       struct fsg_lun          *curlun;
3588 +       struct usb_request      *req = fsg->ep0req;
3589 +
3590 +       DBG(fsg, "unbind\n");
3591 +       clear_bit(REGISTERED, &fsg->atomic_bitflags);
3592 +
3593 +       /* If the thread isn't already dead, tell it to exit now */
3594 +       if (fsg->state != FSG_STATE_TERMINATED) {
3595 +               raise_exception(fsg, FSG_STATE_EXIT);
3596 +               wait_for_completion(&fsg->thread_notifier);
3597 +
3598 +               /* The cleanup routine waits for this completion also */
3599 +               complete(&fsg->thread_notifier);
3600 +       }
3601 +
3602 +       /* Unregister the sysfs attribute files and the LUNs */
3603 +       for (i = 0; i < fsg->nluns; ++i) {
3604 +               curlun = &fsg->luns[i];
3605 +               if (curlun->registered) {
3606 +                       device_remove_file(&curlun->dev, &dev_attr_nofua);
3607 +                       device_remove_file(&curlun->dev, &dev_attr_ro);
3608 +                       device_remove_file(&curlun->dev, &dev_attr_file);
3609 +                       fsg_lun_close(curlun);
3610 +                       device_unregister(&curlun->dev);
3611 +                       curlun->registered = 0;
3612 +               }
3613 +       }
3614 +
3615 +       /* Free the data buffers */
3616 +       for (i = 0; i < fsg_num_buffers; ++i)
3617 +               kfree(fsg->buffhds[i].buf);
3618 +
3619 +       /* Free the request and buffer for endpoint 0 */
3620 +       if (req) {
3621 +               kfree(req->buf);
3622 +               usb_ep_free_request(fsg->ep0, req);
3623 +       }
3624 +
3625 +       set_gadget_data(gadget, NULL);
3626 +}
3627 +
3628 +
3629 +static int __init check_parameters(struct fsg_dev *fsg)
3630 +{
3631 +       int     prot;
3632 +       int     gcnum;
3633 +
3634 +       /* Store the default values */
3635 +       mod_data.transport_type = USB_PR_BULK;
3636 +       mod_data.transport_name = "Bulk-only";
3637 +       mod_data.protocol_type = USB_SC_SCSI;
3638 +       mod_data.protocol_name = "Transparent SCSI";
3639 +
3640 +       /* Some peripheral controllers are known not to be able to
3641 +        * halt bulk endpoints correctly.  If one of them is present,
3642 +        * disable stalls.
3643 +        */
3644 +       if (gadget_is_at91(fsg->gadget))
3645 +               mod_data.can_stall = 0;
3646 +
3647 +       if (mod_data.release == 0xffff) {       // Parameter wasn't set
3648 +               gcnum = usb_gadget_controller_number(fsg->gadget);
3649 +               if (gcnum >= 0)
3650 +                       mod_data.release = 0x0300 + gcnum;
3651 +               else {
3652 +                       WARNING(fsg, "controller '%s' not recognized\n",
3653 +                               fsg->gadget->name);
3654 +                       mod_data.release = 0x0399;
3655 +               }
3656 +       }
3657 +
3658 +       prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
3659 +
3660 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
3661 +       if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
3662 +               ;               // Use default setting
3663 +       } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
3664 +               mod_data.transport_type = USB_PR_CB;
3665 +               mod_data.transport_name = "Control-Bulk";
3666 +       } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
3667 +               mod_data.transport_type = USB_PR_CBI;
3668 +               mod_data.transport_name = "Control-Bulk-Interrupt";
3669 +       } else {
3670 +               ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
3671 +               return -EINVAL;
3672 +       }
3673 +
3674 +       if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
3675 +                       prot == USB_SC_SCSI) {
3676 +               ;               // Use default setting
3677 +       } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
3678 +                       prot == USB_SC_RBC) {
3679 +               mod_data.protocol_type = USB_SC_RBC;
3680 +               mod_data.protocol_name = "RBC";
3681 +       } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
3682 +                       strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
3683 +                       prot == USB_SC_8020) {
3684 +               mod_data.protocol_type = USB_SC_8020;
3685 +               mod_data.protocol_name = "8020i (ATAPI)";
3686 +       } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
3687 +                       prot == USB_SC_QIC) {
3688 +               mod_data.protocol_type = USB_SC_QIC;
3689 +               mod_data.protocol_name = "QIC-157";
3690 +       } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
3691 +                       prot == USB_SC_UFI) {
3692 +               mod_data.protocol_type = USB_SC_UFI;
3693 +               mod_data.protocol_name = "UFI";
3694 +       } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
3695 +                       prot == USB_SC_8070) {
3696 +               mod_data.protocol_type = USB_SC_8070;
3697 +               mod_data.protocol_name = "8070i";
3698 +       } else {
3699 +               ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
3700 +               return -EINVAL;
3701 +       }
3702 +
3703 +       mod_data.buflen &= PAGE_CACHE_MASK;
3704 +       if (mod_data.buflen <= 0) {
3705 +               ERROR(fsg, "invalid buflen\n");
3706 +               return -ETOOSMALL;
3707 +       }
3708 +
3709 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
3710 +
3711 +       /* Serial string handling.
3712 +        * On a real device, the serial string would be loaded
3713 +        * from permanent storage. */
3714 +       if (mod_data.serial) {
3715 +               const char *ch;
3716 +               unsigned len = 0;
3717 +
3718 +               /* Sanity check :
3719 +                * The CB[I] specification limits the serial string to
3720 +                * 12 uppercase hexadecimal characters.
3721 +                * BBB need at least 12 uppercase hexadecimal characters,
3722 +                * with a maximum of 126. */
3723 +               for (ch = mod_data.serial; *ch; ++ch) {
3724 +                       ++len;
3725 +                       if ((*ch < '0' || *ch > '9') &&
3726 +                           (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
3727 +                               WARNING(fsg,
3728 +                                       "Invalid serial string character: %c\n",
3729 +                                       *ch);
3730 +                               goto no_serial;
3731 +                       }
3732 +               }
3733 +               if (len > 126 ||
3734 +                   (mod_data.transport_type == USB_PR_BULK && len < 12) ||
3735 +                   (mod_data.transport_type != USB_PR_BULK && len > 12)) {
3736 +                       WARNING(fsg, "Invalid serial string length!\n");
3737 +                       goto no_serial;
3738 +               }
3739 +               fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
3740 +       } else {
3741 +               WARNING(fsg, "No serial-number string provided!\n");
3742 + no_serial:
3743 +               device_desc.iSerialNumber = 0;
3744 +       }
3745 +
3746 +       return 0;
3747 +}
3748 +
3749 +
3750 +static int __init fsg_bind(struct usb_gadget *gadget)
3751 +{
3752 +       struct fsg_dev          *fsg = the_fsg;
3753 +       int                     rc;
3754 +       int                     i;
3755 +       struct fsg_lun          *curlun;
3756 +       struct usb_ep           *ep;
3757 +       struct usb_request      *req;
3758 +       char                    *pathbuf, *p;
3759 +
3760 +       fsg->gadget = gadget;
3761 +       set_gadget_data(gadget, fsg);
3762 +       fsg->ep0 = gadget->ep0;
3763 +       fsg->ep0->driver_data = fsg;
3764 +
3765 +       if ((rc = check_parameters(fsg)) != 0)
3766 +               goto out;
3767 +
3768 +       if (mod_data.removable) {       // Enable the store_xxx attributes
3769 +               dev_attr_file.attr.mode = 0644;
3770 +               dev_attr_file.store = fsg_store_file;
3771 +               if (!mod_data.cdrom) {
3772 +                       dev_attr_ro.attr.mode = 0644;
3773 +                       dev_attr_ro.store = fsg_store_ro;
3774 +               }
3775 +       }
3776 +
3777 +       /* Only for removable media? */
3778 +       dev_attr_nofua.attr.mode = 0644;
3779 +       dev_attr_nofua.store = fsg_store_nofua;
3780 +
3781 +       /* Find out how many LUNs there should be */
3782 +       i = mod_data.nluns;
3783 +       if (i == 0)
3784 +               i = max(mod_data.num_filenames, 1u);
3785 +       if (i > FSG_MAX_LUNS) {
3786 +               ERROR(fsg, "invalid number of LUNs: %d\n", i);
3787 +               rc = -EINVAL;
3788 +               goto out;
3789 +       }
3790 +
3791 +       /* Create the LUNs, open their backing files, and register the
3792 +        * LUN devices in sysfs. */
3793 +       fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
3794 +       if (!fsg->luns) {
3795 +               rc = -ENOMEM;
3796 +               goto out;
3797 +       }
3798 +       fsg->nluns = i;
3799 +
3800 +       for (i = 0; i < fsg->nluns; ++i) {
3801 +               curlun = &fsg->luns[i];
3802 +               curlun->cdrom = !!mod_data.cdrom;
3803 +               curlun->ro = mod_data.cdrom || mod_data.ro[i];
3804 +               curlun->initially_ro = curlun->ro;
3805 +               curlun->removable = mod_data.removable;
3806 +               curlun->nofua = mod_data.nofua[i];
3807 +               curlun->dev.release = lun_release;
3808 +               curlun->dev.parent = &gadget->dev;
3809 +               curlun->dev.driver = &fsg_driver.driver;
3810 +               dev_set_drvdata(&curlun->dev, &fsg->filesem);
3811 +               dev_set_name(&curlun->dev,"%s-lun%d",
3812 +                            dev_name(&gadget->dev), i);
3813 +
3814 +               kref_get(&fsg->ref);
3815 +               rc = device_register(&curlun->dev);
3816 +               if (rc) {
3817 +                       INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
3818 +                       put_device(&curlun->dev);
3819 +                       goto out;
3820 +               }
3821 +               curlun->registered = 1;
3822 +
3823 +               rc = device_create_file(&curlun->dev, &dev_attr_ro);
3824 +               if (rc)
3825 +                       goto out;
3826 +               rc = device_create_file(&curlun->dev, &dev_attr_nofua);
3827 +               if (rc)
3828 +                       goto out;
3829 +               rc = device_create_file(&curlun->dev, &dev_attr_file);
3830 +               if (rc)
3831 +                       goto out;
3832 +
3833 +               if (mod_data.file[i] && *mod_data.file[i]) {
3834 +                       rc = fsg_lun_open(curlun, mod_data.file[i]);
3835 +                       if (rc)
3836 +                               goto out;
3837 +               } else if (!mod_data.removable) {
3838 +                       ERROR(fsg, "no file given for LUN%d\n", i);
3839 +                       rc = -EINVAL;
3840 +                       goto out;
3841 +               }
3842 +       }
3843 +
3844 +       /* Find all the endpoints we will use */
3845 +       usb_ep_autoconfig_reset(gadget);
3846 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
3847 +       if (!ep)
3848 +               goto autoconf_fail;
3849 +       ep->driver_data = fsg;          // claim the endpoint
3850 +       fsg->bulk_in = ep;
3851 +
3852 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
3853 +       if (!ep)
3854 +               goto autoconf_fail;
3855 +       ep->driver_data = fsg;          // claim the endpoint
3856 +       fsg->bulk_out = ep;
3857 +
3858 +       if (transport_is_cbi()) {
3859 +               ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
3860 +               if (!ep)
3861 +                       goto autoconf_fail;
3862 +               ep->driver_data = fsg;          // claim the endpoint
3863 +               fsg->intr_in = ep;
3864 +       }
3865 +
3866 +       /* Fix up the descriptors */
3867 +       device_desc.idVendor = cpu_to_le16(mod_data.vendor);
3868 +       device_desc.idProduct = cpu_to_le16(mod_data.product);
3869 +       device_desc.bcdDevice = cpu_to_le16(mod_data.release);
3870 +
3871 +       i = (transport_is_cbi() ? 3 : 2);       // Number of endpoints
3872 +       fsg_intf_desc.bNumEndpoints = i;
3873 +       fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
3874 +       fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
3875 +       fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3876 +
3877 +       if (gadget_is_dualspeed(gadget)) {
3878 +               fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3879 +
3880 +               /* Assume endpoint addresses are the same for both speeds */
3881 +               fsg_hs_bulk_in_desc.bEndpointAddress =
3882 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3883 +               fsg_hs_bulk_out_desc.bEndpointAddress =
3884 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3885 +               fsg_hs_intr_in_desc.bEndpointAddress =
3886 +                       fsg_fs_intr_in_desc.bEndpointAddress;
3887 +       }
3888 +
3889 +       if (gadget_is_superspeed(gadget)) {
3890 +               unsigned                max_burst;
3891 +
3892 +               fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3893 +
3894 +               /* Calculate bMaxBurst, we know packet size is 1024 */
3895 +               max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
3896 +
3897 +               /* Assume endpoint addresses are the same for both speeds */
3898 +               fsg_ss_bulk_in_desc.bEndpointAddress =
3899 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3900 +               fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
3901 +
3902 +               fsg_ss_bulk_out_desc.bEndpointAddress =
3903 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3904 +               fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
3905 +       }
3906 +
3907 +       if (gadget_is_otg(gadget))
3908 +               fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
3909 +
3910 +       rc = -ENOMEM;
3911 +
3912 +       /* Allocate the request and buffer for endpoint 0 */
3913 +       fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
3914 +       if (!req)
3915 +               goto out;
3916 +       req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
3917 +       if (!req->buf)
3918 +               goto out;
3919 +       req->complete = ep0_complete;
3920 +
3921 +       /* Allocate the data buffers */
3922 +       for (i = 0; i < fsg_num_buffers; ++i) {
3923 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3924 +
3925 +               /* Allocate for the bulk-in endpoint.  We assume that
3926 +                * the buffer will also work with the bulk-out (and
3927 +                * interrupt-in) endpoint. */
3928 +               bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
3929 +               if (!bh->buf)
3930 +                       goto out;
3931 +               bh->next = bh + 1;
3932 +       }
3933 +       fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
3934 +
3935 +       /* This should reflect the actual gadget power source */
3936 +       usb_gadget_set_selfpowered(gadget);
3937 +
3938 +       snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
3939 +                       "%s %s with %s",
3940 +                       init_utsname()->sysname, init_utsname()->release,
3941 +                       gadget->name);
3942 +
3943 +       fsg->thread_task = kthread_create(fsg_main_thread, fsg,
3944 +                       "file-storage-gadget");
3945 +       if (IS_ERR(fsg->thread_task)) {
3946 +               rc = PTR_ERR(fsg->thread_task);
3947 +               goto out;
3948 +       }
3949 +
3950 +       INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
3951 +       INFO(fsg, "NOTE: This driver is deprecated.  "
3952 +                       "Consider using g_mass_storage instead.\n");
3953 +       INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
3954 +
3955 +       pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
3956 +       for (i = 0; i < fsg->nluns; ++i) {
3957 +               curlun = &fsg->luns[i];
3958 +               if (fsg_lun_is_open(curlun)) {
3959 +                       p = NULL;
3960 +                       if (pathbuf) {
3961 +                               p = d_path(&curlun->filp->f_path,
3962 +                                          pathbuf, PATH_MAX);
3963 +                               if (IS_ERR(p))
3964 +                                       p = NULL;
3965 +                       }
3966 +                       LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
3967 +                             curlun->ro, curlun->nofua, (p ? p : "(error)"));
3968 +               }
3969 +       }
3970 +       kfree(pathbuf);
3971 +
3972 +       DBG(fsg, "transport=%s (x%02x)\n",
3973 +                       mod_data.transport_name, mod_data.transport_type);
3974 +       DBG(fsg, "protocol=%s (x%02x)\n",
3975 +                       mod_data.protocol_name, mod_data.protocol_type);
3976 +       DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
3977 +                       mod_data.vendor, mod_data.product, mod_data.release);
3978 +       DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
3979 +                       mod_data.removable, mod_data.can_stall,
3980 +                       mod_data.cdrom, mod_data.buflen);
3981 +       DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
3982 +
3983 +       set_bit(REGISTERED, &fsg->atomic_bitflags);
3984 +
3985 +       /* Tell the thread to start working */
3986 +       wake_up_process(fsg->thread_task);
3987 +       return 0;
3988 +
3989 +autoconf_fail:
3990 +       ERROR(fsg, "unable to autoconfigure all endpoints\n");
3991 +       rc = -ENOTSUPP;
3992 +
3993 +out:
3994 +       fsg->state = FSG_STATE_TERMINATED;      // The thread is dead
3995 +       fsg_unbind(gadget);
3996 +       complete(&fsg->thread_notifier);
3997 +       return rc;
3998 +}
3999 +
4000 +
4001 +/*-------------------------------------------------------------------------*/
4002 +
4003 +static void fsg_suspend(struct usb_gadget *gadget)
4004 +{
4005 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4006 +
4007 +       DBG(fsg, "suspend\n");
4008 +       set_bit(SUSPENDED, &fsg->atomic_bitflags);
4009 +}
4010 +
4011 +static void fsg_resume(struct usb_gadget *gadget)
4012 +{
4013 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4014 +
4015 +       DBG(fsg, "resume\n");
4016 +       clear_bit(SUSPENDED, &fsg->atomic_bitflags);
4017 +}
4018 +
4019 +
4020 +/*-------------------------------------------------------------------------*/
4021 +
4022 +static struct usb_gadget_driver                fsg_driver = {
4023 +       .max_speed      = USB_SPEED_SUPER,
4024 +       .function       = (char *) fsg_string_product,
4025 +       .unbind         = fsg_unbind,
4026 +       .disconnect     = fsg_disconnect,
4027 +       .setup          = fsg_setup,
4028 +       .suspend        = fsg_suspend,
4029 +       .resume         = fsg_resume,
4030 +
4031 +       .driver         = {
4032 +               .name           = DRIVER_NAME,
4033 +               .owner          = THIS_MODULE,
4034 +               // .release = ...
4035 +               // .suspend = ...
4036 +               // .resume = ...
4037 +       },
4038 +};
4039 +
4040 +
4041 +static int __init fsg_alloc(void)
4042 +{
4043 +       struct fsg_dev          *fsg;
4044 +
4045 +       fsg = kzalloc(sizeof *fsg +
4046 +                     fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
4047 +
4048 +       if (!fsg)
4049 +               return -ENOMEM;
4050 +       spin_lock_init(&fsg->lock);
4051 +       init_rwsem(&fsg->filesem);
4052 +       kref_init(&fsg->ref);
4053 +       init_completion(&fsg->thread_notifier);
4054 +
4055 +       the_fsg = fsg;
4056 +       return 0;
4057 +}
4058 +
4059 +
4060 +static int __init fsg_init(void)
4061 +{
4062 +       int             rc;
4063 +       struct fsg_dev  *fsg;
4064 +
4065 +       rc = fsg_num_buffers_validate();
4066 +       if (rc != 0)
4067 +               return rc;
4068 +
4069 +       if ((rc = fsg_alloc()) != 0)
4070 +               return rc;
4071 +       fsg = the_fsg;
4072 +       if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
4073 +               kref_put(&fsg->ref, fsg_release);
4074 +       return rc;
4075 +}
4076 +module_init(fsg_init);
4077 +
4078 +
4079 +static void __exit fsg_cleanup(void)
4080 +{
4081 +       struct fsg_dev  *fsg = the_fsg;
4082 +
4083 +       /* Unregister the driver iff the thread hasn't already done so */
4084 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
4085 +               usb_gadget_unregister_driver(&fsg_driver);
4086 +
4087 +       /* Wait for the thread to finish up */
4088 +       wait_for_completion(&fsg->thread_notifier);
4089 +
4090 +       kref_put(&fsg->ref, fsg_release);
4091 +}
4092 +module_exit(fsg_cleanup);
4093 diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
4094 index a3ca137..4937c9c 100644
4095 --- a/drivers/usb/host/Kconfig
4096 +++ b/drivers/usb/host/Kconfig
4097 @@ -744,6 +744,19 @@ config USB_HWA_HCD
4098           To compile this driver a module, choose M here: the module
4099           will be called "hwa-hc".
4100  
4101 +config USB_DWCOTG
4102 +       tristate "Synopsis DWC host support"
4103 +       depends on USB
4104 +       help
4105 +         The Synopsis DWC controller is a dual-role
4106 +         host/peripheral/OTG ("On The Go") USB controllers.
4107 +
4108 +         Enable this option to support this IP in host controller mode.
4109 +         If unsure, say N.
4110 +
4111 +         To compile this driver as a module, choose M here: the
4112 +         modules built will be called dwc_otg and dwc_common_port.
4113 +
4114  config USB_IMX21_HCD
4115         tristate "i.MX21 HCD support"
4116         depends on ARM && ARCH_MXC
4117 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
4118 index 348c243..7ca1836 100644
4119 --- a/drivers/usb/host/Makefile
4120 +++ b/drivers/usb/host/Makefile
4121 @@ -71,6 +71,8 @@ obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
4122  obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
4123  obj-$(CONFIG_USB_ISP1760_HCD)  += isp1760.o
4124  obj-$(CONFIG_USB_HWA_HCD)      += hwa-hc.o
4125 +
4126 +obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/
4127  obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
4128  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
4129  obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
4130 diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile
4131 new file mode 100644
4132 index 0000000..f10d466
4133 --- /dev/null
4134 +++ b/drivers/usb/host/dwc_common_port/Makefile
4135 @@ -0,0 +1,58 @@
4136 +#
4137 +# Makefile for DWC_common library
4138 +#
4139 +
4140 +ifneq ($(KERNELRELEASE),)
4141 +
4142 +ccflags-y      += -DDWC_LINUX
4143 +#ccflags-y     += -DDEBUG
4144 +#ccflags-y     += -DDWC_DEBUG_REGS
4145 +#ccflags-y     += -DDWC_DEBUG_MEMORY
4146 +
4147 +ccflags-y      += -DDWC_LIBMODULE
4148 +ccflags-y      += -DDWC_CCLIB
4149 +#ccflags-y     += -DDWC_CRYPTOLIB
4150 +ccflags-y      += -DDWC_NOTIFYLIB
4151 +ccflags-y      += -DDWC_UTFLIB
4152 +
4153 +obj-$(CONFIG_USB_DWCOTG)       += dwc_common_port_lib.o
4154 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4155 +                           dwc_crypto.o dwc_notifier.o \
4156 +                           dwc_common_linux.o dwc_mem.o
4157 +
4158 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
4159 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
4160 +
4161 +ifneq ($(kernrel3),2.6.20)
4162 +# grayg - I only know that we use ccflags-y in 2.6.31 actually
4163 +ccflags-y += $(CPPFLAGS)
4164 +endif
4165 +
4166 +else
4167 +
4168 +#ifeq ($(KDIR),)
4169 +#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4170 +#endif
4171 +
4172 +ifeq ($(ARCH),)
4173 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4174 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4175 +endif
4176 +
4177 +ifeq ($(DOXYGEN),)
4178 +DOXYGEN                := doxygen
4179 +endif
4180 +
4181 +default:
4182 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4183 +
4184 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4185 +       $(DOXYGEN) doc/doxygen.cfg
4186 +
4187 +tags:  $(wildcard *.[hc])
4188 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4189 +
4190 +endif
4191 +
4192 +clean:
4193 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4194 diff --git a/drivers/usb/host/dwc_common_port/Makefile.fbsd b/drivers/usb/host/dwc_common_port/Makefile.fbsd
4195 new file mode 100644
4196 index 0000000..45db991
4197 --- /dev/null
4198 +++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd
4199 @@ -0,0 +1,17 @@
4200 +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
4201 +CFLAGS += -DDWC_FREEBSD
4202 +CFLAGS += -DDEBUG
4203 +#CFLAGS        += -DDWC_DEBUG_REGS
4204 +#CFLAGS        += -DDWC_DEBUG_MEMORY
4205 +
4206 +#CFLAGS        += -DDWC_LIBMODULE
4207 +#CFLAGS        += -DDWC_CCLIB
4208 +#CFLAGS        += -DDWC_CRYPTOLIB
4209 +#CFLAGS        += -DDWC_NOTIFYLIB
4210 +#CFLAGS        += -DDWC_UTFLIB
4211 +
4212 +KMOD = dwc_common_port_lib
4213 +SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \
4214 +       dwc_common_fbsd.c dwc_mem.c
4215 +
4216 +.include <bsd.kmod.mk>
4217 diff --git a/drivers/usb/host/dwc_common_port/Makefile.linux b/drivers/usb/host/dwc_common_port/Makefile.linux
4218 new file mode 100644
4219 index 0000000..0cef7b4
4220 --- /dev/null
4221 +++ b/drivers/usb/host/dwc_common_port/Makefile.linux
4222 @@ -0,0 +1,49 @@
4223 +#
4224 +# Makefile for DWC_common library
4225 +#
4226 +ifneq ($(KERNELRELEASE),)
4227 +
4228 +ccflags-y      += -DDWC_LINUX
4229 +#ccflags-y     += -DDEBUG
4230 +#ccflags-y     += -DDWC_DEBUG_REGS
4231 +#ccflags-y     += -DDWC_DEBUG_MEMORY
4232 +
4233 +ccflags-y      += -DDWC_LIBMODULE
4234 +ccflags-y      += -DDWC_CCLIB
4235 +ccflags-y      += -DDWC_CRYPTOLIB
4236 +ccflags-y      += -DDWC_NOTIFYLIB
4237 +ccflags-y      += -DDWC_UTFLIB
4238 +
4239 +obj-m                   := dwc_common_port_lib.o
4240 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4241 +                           dwc_crypto.o dwc_notifier.o \
4242 +                           dwc_common_linux.o dwc_mem.o
4243 +
4244 +else
4245 +
4246 +ifeq ($(KDIR),)
4247 +$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4248 +endif
4249 +
4250 +ifeq ($(ARCH),)
4251 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4252 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4253 +endif
4254 +
4255 +ifeq ($(DOXYGEN),)
4256 +DOXYGEN                := doxygen
4257 +endif
4258 +
4259 +default:
4260 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4261 +
4262 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4263 +       $(DOXYGEN) doc/doxygen.cfg
4264 +
4265 +tags:  $(wildcard *.[hc])
4266 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4267 +
4268 +endif
4269 +
4270 +clean:
4271 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4272 diff --git a/drivers/usb/host/dwc_common_port/changes.txt b/drivers/usb/host/dwc_common_port/changes.txt
4273 new file mode 100644
4274 index 0000000..f6839f9
4275 --- /dev/null
4276 +++ b/drivers/usb/host/dwc_common_port/changes.txt
4277 @@ -0,0 +1,174 @@
4278 +
4279 +dwc_read_reg32() and friends now take an additional parameter, a pointer to an
4280 +IO context struct. The IO context struct should live in an os-dependent struct
4281 +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct
4282 +named 'os_dep' embedded in the main device struct. So there these calls look
4283 +like this:
4284 +
4285 +       dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);
4286 +
4287 +       dwc_write_reg32(&usb3_dev->os_dep.ioctx,
4288 +                       &pcd->dev_global_regs->dcfg, 0);
4289 +
4290 +Note that for the existing Linux driver ports, it is not necessary to actually
4291 +define the 'ioctx' member in the os-dependent struct. Since Linux does not
4292 +require an IO context, its macros for dwc_read_reg32() and friends do not
4293 +use the context pointer, so it is optimized away by the compiler. But it is
4294 +necessary to add the pointer parameter to all of the call sites, to be ready
4295 +for any future ports (such as FreeBSD) which do require an IO context.
4296 +
4297 +
4298 +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now
4299 +take an additional parameter, a pointer to a memory context. Examples:
4300 +
4301 +       addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);
4302 +
4303 +       dwc_free(&usb3_dev->os_dep.memctx, addr);
4304 +
4305 +Again, for the Linux ports, it is not necessary to actually define the memctx
4306 +member, but it is necessary to add the pointer parameter to all of the call
4307 +sites.
4308 +
4309 +
4310 +Same for dwc_dma_alloc() and dwc_dma_free(). Examples:
4311 +
4312 +       virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);
4313 +
4314 +       dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);
4315 +
4316 +
4317 +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:
4318 +
4319 +       mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);
4320 +
4321 +       dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);
4322 +
4323 +
4324 +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:
4325 +
4326 +       lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);
4327 +
4328 +       dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);
4329 +
4330 +
4331 +Same for dwc_timer_alloc(). Example:
4332 +
4333 +       timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",
4334 +                               cb_func, cb_data);
4335 +
4336 +
4337 +Same for dwc_waitq_alloc(). Example:
4338 +
4339 +       waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);
4340 +
4341 +
4342 +Same for dwc_thread_run(). Example:
4343 +
4344 +       thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,
4345 +                               "dwc_usb3_thd1", data);
4346 +
4347 +
4348 +Same for dwc_workq_alloc(). Example:
4349 +
4350 +       workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");
4351 +
4352 +
4353 +Same for dwc_task_alloc(). Example:
4354 +
4355 +       task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",
4356 +                             cb_func, cb_data);
4357 +
4358 +
4359 +In addition to the context pointer additions, a few core functions have had
4360 +other changes made to their parameters:
4361 +
4362 +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()
4363 +has been changed from a uint64_t to a dwc_irqflags_t.
4364 +
4365 +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the
4366 +FreeBSD equivalent of that function requires it.
4367 +
4368 +And, in addition to the context pointer, dwc_task_alloc() also adds a
4369 +'char *name' parameter, to be consistent with dwc_thread_run() and
4370 +dwc_workq_alloc(), and because the FreeBSD equivalent of that function
4371 +requires a unique name.
4372 +
4373 +
4374 +Here is a complete list of the core functions that now take a pointer to a
4375 +context as their first parameter:
4376 +
4377 +       dwc_read_reg32
4378 +       dwc_read_reg64
4379 +       dwc_write_reg32
4380 +       dwc_write_reg64
4381 +       dwc_modify_reg32
4382 +       dwc_modify_reg64
4383 +       dwc_alloc
4384 +       dwc_alloc_atomic
4385 +       dwc_strdup
4386 +       dwc_free
4387 +       dwc_dma_alloc
4388 +       dwc_dma_free
4389 +       dwc_mutex_alloc
4390 +       dwc_mutex_free
4391 +       dwc_spinlock_alloc
4392 +       dwc_spinlock_free
4393 +       dwc_timer_alloc
4394 +       dwc_waitq_alloc
4395 +       dwc_thread_run
4396 +       dwc_workq_alloc
4397 +       dwc_task_alloc     Also adds a 'char *name' as its 2nd parameter
4398 +
4399 +And here are the core functions that have other changes to their parameters:
4400 +
4401 +       dwc_spinlock_irqsave      'flags' param is now a 'dwc_irqflags_t *'
4402 +       dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'
4403 +       dwc_thread_should_stop    Adds a 'dwc_thread_t *' parameter
4404 +
4405 +
4406 +
4407 +The changes to the core functions also require some of the other library
4408 +functions to change:
4409 +
4410 +       dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'
4411 +       (for memory allocation) as the 1st param and a 'void *mtxctx'
4412 +       (for mutex allocation) as the 2nd param.
4413 +
4414 +       dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),
4415 +       dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a
4416 +       'void *memctx' as the 1st param.
4417 +
4418 +       dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a
4419 +       'void *memctx' as the 1st param.
4420 +
4421 +       dwc_modpow() now takes a 'void *memctx' as the 1st param.
4422 +
4423 +       dwc_alloc_notification_manager() now takes a 'void *memctx' as the
4424 +       1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd
4425 +       param, and also now returns an integer value that is non-zero if
4426 +       allocation of its data structures or work queue fails.
4427 +
4428 +       dwc_register_notifier() now takes a 'void *memctx' as the 1st param.
4429 +
4430 +       dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first
4431 +       param, and also now returns an integer value that is non-zero if
4432 +       allocation of its data structures fails.
4433 +
4434 +
4435 +
4436 +Other miscellaneous changes:
4437 +
4438 +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to
4439 +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.
4440 +
4441 +The following #define's have been added to allow selectively compiling library
4442 +features:
4443 +
4444 +       DWC_CCLIB
4445 +       DWC_CRYPTOLIB
4446 +       DWC_NOTIFYLIB
4447 +       DWC_UTFLIB
4448 +
4449 +A DWC_LIBMODULE #define has also been added. If this is not defined, then the
4450 +module code in dwc_common_linux.c is not compiled in. This allows linking the
4451 +library code directly into a driver module, instead of as a standalone module.
4452 diff --git a/drivers/usb/host/dwc_common_port/doc/doxygen.cfg b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4453 new file mode 100644
4454 index 0000000..89aa887
4455 --- /dev/null
4456 +++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4457 @@ -0,0 +1,270 @@
4458 +# Doxyfile 1.4.5
4459 +
4460 +#---------------------------------------------------------------------------
4461 +# Project related configuration options
4462 +#---------------------------------------------------------------------------
4463 +PROJECT_NAME           = "Synopsys DWC Portability and Common Library for UWB"
4464 +PROJECT_NUMBER         =
4465 +OUTPUT_DIRECTORY       = doc
4466 +CREATE_SUBDIRS         = NO
4467 +OUTPUT_LANGUAGE        = English
4468 +BRIEF_MEMBER_DESC      = YES
4469 +REPEAT_BRIEF           = YES
4470 +ABBREVIATE_BRIEF       = "The $name class" \
4471 +                         "The $name widget" \
4472 +                         "The $name file" \
4473 +                         is \
4474 +                         provides \
4475 +                         specifies \
4476 +                         contains \
4477 +                         represents \
4478 +                         a \
4479 +                         an \
4480 +                         the
4481 +ALWAYS_DETAILED_SEC    = YES
4482 +INLINE_INHERITED_MEMB  = NO
4483 +FULL_PATH_NAMES        = NO
4484 +STRIP_FROM_PATH        = ..
4485 +STRIP_FROM_INC_PATH    =
4486 +SHORT_NAMES            = NO
4487 +JAVADOC_AUTOBRIEF      = YES
4488 +MULTILINE_CPP_IS_BRIEF = NO
4489 +DETAILS_AT_TOP         = YES
4490 +INHERIT_DOCS           = YES
4491 +SEPARATE_MEMBER_PAGES  = NO
4492 +TAB_SIZE               = 8
4493 +ALIASES                =
4494 +OPTIMIZE_OUTPUT_FOR_C  = YES
4495 +OPTIMIZE_OUTPUT_JAVA   = NO
4496 +BUILTIN_STL_SUPPORT    = NO
4497 +DISTRIBUTE_GROUP_DOC   = NO
4498 +SUBGROUPING            = NO
4499 +#---------------------------------------------------------------------------
4500 +# Build related configuration options
4501 +#---------------------------------------------------------------------------
4502 +EXTRACT_ALL            = NO
4503 +EXTRACT_PRIVATE        = NO
4504 +EXTRACT_STATIC         = YES
4505 +EXTRACT_LOCAL_CLASSES  = NO
4506 +EXTRACT_LOCAL_METHODS  = NO
4507 +HIDE_UNDOC_MEMBERS     = NO
4508 +HIDE_UNDOC_CLASSES     = NO
4509 +HIDE_FRIEND_COMPOUNDS  = NO
4510 +HIDE_IN_BODY_DOCS      = NO
4511 +INTERNAL_DOCS          = NO
4512 +CASE_SENSE_NAMES       = YES
4513 +HIDE_SCOPE_NAMES       = NO
4514 +SHOW_INCLUDE_FILES     = NO
4515 +INLINE_INFO            = YES
4516 +SORT_MEMBER_DOCS       = NO
4517 +SORT_BRIEF_DOCS        = NO
4518 +SORT_BY_SCOPE_NAME     = NO
4519 +GENERATE_TODOLIST      = YES
4520 +GENERATE_TESTLIST      = YES
4521 +GENERATE_BUGLIST       = YES
4522 +GENERATE_DEPRECATEDLIST= YES
4523 +ENABLED_SECTIONS       =
4524 +MAX_INITIALIZER_LINES  = 30
4525 +SHOW_USED_FILES        = YES
4526 +SHOW_DIRECTORIES       = YES
4527 +FILE_VERSION_FILTER    =
4528 +#---------------------------------------------------------------------------
4529 +# configuration options related to warning and progress messages
4530 +#---------------------------------------------------------------------------
4531 +QUIET                  = YES
4532 +WARNINGS               = YES
4533 +WARN_IF_UNDOCUMENTED   = NO
4534 +WARN_IF_DOC_ERROR      = YES
4535 +WARN_NO_PARAMDOC       = YES
4536 +WARN_FORMAT            = "$file:$line: $text"
4537 +WARN_LOGFILE           =
4538 +#---------------------------------------------------------------------------
4539 +# configuration options related to the input files
4540 +#---------------------------------------------------------------------------
4541 +INPUT                  = .
4542 +FILE_PATTERNS          = *.c \
4543 +                         *.cc \
4544 +                         *.cxx \
4545 +                         *.cpp \
4546 +                         *.c++ \
4547 +                         *.d \
4548 +                         *.java \
4549 +                         *.ii \
4550 +                         *.ixx \
4551 +                         *.ipp \
4552 +                         *.i++ \
4553 +                         *.inl \
4554 +                         *.h \
4555 +                         *.hh \
4556 +                         *.hxx \
4557 +                         *.hpp \
4558 +                         *.h++ \
4559 +                         *.idl \
4560 +                         *.odl \
4561 +                         *.cs \
4562 +                         *.php \
4563 +                         *.php3 \
4564 +                         *.inc \
4565 +                         *.m \
4566 +                         *.mm \
4567 +                         *.dox \
4568 +                         *.py \
4569 +                         *.C \
4570 +                         *.CC \
4571 +                         *.C++ \
4572 +                         *.II \
4573 +                         *.I++ \
4574 +                         *.H \
4575 +                         *.HH \
4576 +                         *.H++ \
4577 +                         *.CS \
4578 +                         *.PHP \
4579 +                         *.PHP3 \
4580 +                         *.M \
4581 +                         *.MM \
4582 +                         *.PY
4583 +RECURSIVE              = NO
4584 +EXCLUDE                =
4585 +EXCLUDE_SYMLINKS       = NO
4586 +EXCLUDE_PATTERNS       =
4587 +EXAMPLE_PATH           =
4588 +EXAMPLE_PATTERNS       = *
4589 +EXAMPLE_RECURSIVE      = NO
4590 +IMAGE_PATH             =
4591 +INPUT_FILTER           =
4592 +FILTER_PATTERNS        =
4593 +FILTER_SOURCE_FILES    = NO
4594 +#---------------------------------------------------------------------------
4595 +# configuration options related to source browsing
4596 +#---------------------------------------------------------------------------
4597 +SOURCE_BROWSER         = NO
4598 +INLINE_SOURCES         = NO
4599 +STRIP_CODE_COMMENTS    = YES
4600 +REFERENCED_BY_RELATION = YES
4601 +REFERENCES_RELATION    = YES
4602 +USE_HTAGS              = NO
4603 +VERBATIM_HEADERS       = NO
4604 +#---------------------------------------------------------------------------
4605 +# configuration options related to the alphabetical class index
4606 +#---------------------------------------------------------------------------
4607 +ALPHABETICAL_INDEX     = NO
4608 +COLS_IN_ALPHA_INDEX    = 5
4609 +IGNORE_PREFIX          =
4610 +#---------------------------------------------------------------------------
4611 +# configuration options related to the HTML output
4612 +#---------------------------------------------------------------------------
4613 +GENERATE_HTML          = YES
4614 +HTML_OUTPUT            = html
4615 +HTML_FILE_EXTENSION    = .html
4616 +HTML_HEADER            =
4617 +HTML_FOOTER            =
4618 +HTML_STYLESHEET        =
4619 +HTML_ALIGN_MEMBERS     = YES
4620 +GENERATE_HTMLHELP      = NO
4621 +CHM_FILE               =
4622 +HHC_LOCATION           =
4623 +GENERATE_CHI           = NO
4624 +BINARY_TOC             = NO
4625 +TOC_EXPAND             = NO
4626 +DISABLE_INDEX          = NO
4627 +ENUM_VALUES_PER_LINE   = 4
4628 +GENERATE_TREEVIEW      = YES
4629 +TREEVIEW_WIDTH         = 250
4630 +#---------------------------------------------------------------------------
4631 +# configuration options related to the LaTeX output
4632 +#---------------------------------------------------------------------------
4633 +GENERATE_LATEX         = NO
4634 +LATEX_OUTPUT           = latex
4635 +LATEX_CMD_NAME         = latex
4636 +MAKEINDEX_CMD_NAME     = makeindex
4637 +COMPACT_LATEX          = NO
4638 +PAPER_TYPE             = a4wide
4639 +EXTRA_PACKAGES         =
4640 +LATEX_HEADER           =
4641 +PDF_HYPERLINKS         = NO
4642 +USE_PDFLATEX           = NO
4643 +LATEX_BATCHMODE        = NO
4644 +LATEX_HIDE_INDICES     = NO
4645 +#---------------------------------------------------------------------------
4646 +# configuration options related to the RTF output
4647 +#---------------------------------------------------------------------------
4648 +GENERATE_RTF           = NO
4649 +RTF_OUTPUT             = rtf
4650 +COMPACT_RTF            = NO
4651 +RTF_HYPERLINKS         = NO
4652 +RTF_STYLESHEET_FILE    =
4653 +RTF_EXTENSIONS_FILE    =
4654 +#---------------------------------------------------------------------------
4655 +# configuration options related to the man page output
4656 +#---------------------------------------------------------------------------
4657 +GENERATE_MAN           = NO
4658 +MAN_OUTPUT             = man
4659 +MAN_EXTENSION          = .3
4660 +MAN_LINKS              = NO
4661 +#---------------------------------------------------------------------------
4662 +# configuration options related to the XML output
4663 +#---------------------------------------------------------------------------
4664 +GENERATE_XML           = NO
4665 +XML_OUTPUT             = xml
4666 +XML_SCHEMA             =
4667 +XML_DTD                =
4668 +XML_PROGRAMLISTING     = YES
4669 +#---------------------------------------------------------------------------
4670 +# configuration options for the AutoGen Definitions output
4671 +#---------------------------------------------------------------------------
4672 +GENERATE_AUTOGEN_DEF   = NO
4673 +#---------------------------------------------------------------------------
4674 +# configuration options related to the Perl module output
4675 +#---------------------------------------------------------------------------
4676 +GENERATE_PERLMOD       = NO
4677 +PERLMOD_LATEX          = NO
4678 +PERLMOD_PRETTY         = YES
4679 +PERLMOD_MAKEVAR_PREFIX =
4680 +#---------------------------------------------------------------------------
4681 +# Configuration options related to the preprocessor
4682 +#---------------------------------------------------------------------------
4683 +ENABLE_PREPROCESSING   = YES
4684 +MACRO_EXPANSION        = NO
4685 +EXPAND_ONLY_PREDEF     = NO
4686 +SEARCH_INCLUDES        = YES
4687 +INCLUDE_PATH           =
4688 +INCLUDE_FILE_PATTERNS  =
4689 +PREDEFINED             = DEBUG DEBUG_MEMORY
4690 +EXPAND_AS_DEFINED      =
4691 +SKIP_FUNCTION_MACROS   = YES
4692 +#---------------------------------------------------------------------------
4693 +# Configuration::additions related to external references
4694 +#---------------------------------------------------------------------------
4695 +TAGFILES               =
4696 +GENERATE_TAGFILE       =
4697 +ALLEXTERNALS           = NO
4698 +EXTERNAL_GROUPS        = YES
4699 +PERL_PATH              = /usr/bin/perl
4700 +#---------------------------------------------------------------------------
4701 +# Configuration options related to the dot tool
4702 +#---------------------------------------------------------------------------
4703 +CLASS_DIAGRAMS         = YES
4704 +HIDE_UNDOC_RELATIONS   = YES
4705 +HAVE_DOT               = NO
4706 +CLASS_GRAPH            = YES
4707 +COLLABORATION_GRAPH    = YES
4708 +GROUP_GRAPHS           = YES
4709 +UML_LOOK               = NO
4710 +TEMPLATE_RELATIONS     = NO
4711 +INCLUDE_GRAPH          = NO
4712 +INCLUDED_BY_GRAPH      = YES
4713 +CALL_GRAPH             = NO
4714 +GRAPHICAL_HIERARCHY    = YES
4715 +DIRECTORY_GRAPH        = YES
4716 +DOT_IMAGE_FORMAT       = png
4717 +DOT_PATH               =
4718 +DOTFILE_DIRS           =
4719 +MAX_DOT_GRAPH_DEPTH    = 1000
4720 +DOT_TRANSPARENT        = NO
4721 +DOT_MULTI_TARGETS      = NO
4722 +GENERATE_LEGEND        = YES
4723 +DOT_CLEANUP            = YES
4724 +#---------------------------------------------------------------------------
4725 +# Configuration::additions related to the search engine
4726 +#---------------------------------------------------------------------------
4727 +SEARCHENGINE           = NO
4728 diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.c b/drivers/usb/host/dwc_common_port/dwc_cc.c
4729 new file mode 100644
4730 index 0000000..5ec2ae2
4731 --- /dev/null
4732 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
4733 @@ -0,0 +1,532 @@
4734 +/* =========================================================================
4735 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
4736 + * $Revision: #4 $
4737 + * $Date: 2010/11/04 $
4738 + * $Change: 1621692 $
4739 + *
4740 + * Synopsys Portability Library Software and documentation
4741 + * (hereinafter, "Software") is an Unsupported proprietary work of
4742 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
4743 + * between Synopsys and you.
4744 + *
4745 + * The Software IS NOT an item of Licensed Software or Licensed Product
4746 + * under any End User Software License Agreement or Agreement for
4747 + * Licensed Product with Synopsys or any supplement thereto. You are
4748 + * permitted to use and redistribute this Software in source and binary
4749 + * forms, with or without modification, provided that redistributions
4750 + * of source code must retain this notice. You may not view, use,
4751 + * disclose, copy or distribute this file or any information contained
4752 + * herein except pursuant to this license grant from Synopsys. If you
4753 + * do not agree with this notice, including the disclaimer below, then
4754 + * you are not authorized to use the Software.
4755 + *
4756 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4757 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4758 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
4759 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
4760 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4761 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4762 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4763 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
4764 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4765 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4766 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4767 + * DAMAGE.
4768 + * ========================================================================= */
4769 +#ifdef DWC_CCLIB
4770 +
4771 +#include "dwc_cc.h"
4772 +
4773 +typedef struct dwc_cc
4774 +{
4775 +       uint32_t uid;
4776 +       uint8_t chid[16];
4777 +       uint8_t cdid[16];
4778 +       uint8_t ck[16];
4779 +       uint8_t *name;
4780 +       uint8_t length;
4781 +        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
4782 +} dwc_cc_t;
4783 +
4784 +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
4785 +
4786 +/** The main structure for CC management.  */
4787 +struct dwc_cc_if
4788 +{
4789 +       dwc_mutex_t *mutex;
4790 +       char *filename;
4791 +
4792 +       unsigned is_host:1;
4793 +
4794 +       dwc_notifier_t *notifier;
4795 +
4796 +       struct context_list list;
4797 +};
4798 +
4799 +#ifdef DEBUG
4800 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
4801 +{
4802 +       int i;
4803 +       DWC_PRINTF("%s: ", name);
4804 +       for (i=0; i<len; i++) {
4805 +               DWC_PRINTF("%02x ", bytes[i]);
4806 +       }
4807 +       DWC_PRINTF("\n");
4808 +}
4809 +#else
4810 +#define dump_bytes(x...)
4811 +#endif
4812 +
4813 +static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
4814 +{
4815 +       dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
4816 +       if (!cc) {
4817 +               return NULL;
4818 +       }
4819 +       DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
4820 +
4821 +       if (name) {
4822 +               cc->length = length;
4823 +               cc->name = dwc_alloc(mem_ctx, length);
4824 +               if (!cc->name) {
4825 +                       dwc_free(mem_ctx, cc);
4826 +                       return NULL;
4827 +               }
4828 +
4829 +               DWC_MEMCPY(cc->name, name, length);
4830 +       }
4831 +
4832 +       return cc;
4833 +}
4834 +
4835 +static void free_cc(void *mem_ctx, dwc_cc_t *cc)
4836 +{
4837 +       if (cc->name) {
4838 +               dwc_free(mem_ctx, cc->name);
4839 +       }
4840 +       dwc_free(mem_ctx, cc);
4841 +}
4842 +
4843 +static uint32_t next_uid(dwc_cc_if_t *cc_if)
4844 +{
4845 +       uint32_t uid = 0;
4846 +       dwc_cc_t *cc;
4847 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4848 +               if (cc->uid > uid) {
4849 +                       uid = cc->uid;
4850 +               }
4851 +       }
4852 +
4853 +       if (uid == 0) {
4854 +               uid = 255;
4855 +       }
4856 +
4857 +       return uid + 1;
4858 +}
4859 +
4860 +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
4861 +{
4862 +       dwc_cc_t *cc;
4863 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4864 +               if (cc->uid == uid) {
4865 +                       return cc;
4866 +               }
4867 +       }
4868 +       return NULL;
4869 +}
4870 +
4871 +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
4872 +{
4873 +       unsigned int size = 0;
4874 +       dwc_cc_t *cc;
4875 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4876 +               size += (48 + 1);
4877 +               if (cc->name) {
4878 +                       size += cc->length;
4879 +               }
4880 +       }
4881 +       return size;
4882 +}
4883 +
4884 +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
4885 +{
4886 +       uint32_t uid = 0;
4887 +       dwc_cc_t *cc;
4888 +
4889 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4890 +               if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
4891 +                       uid = cc->uid;
4892 +                       break;
4893 +               }
4894 +       }
4895 +       return uid;
4896 +}
4897 +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
4898 +{
4899 +       uint32_t uid = 0;
4900 +       dwc_cc_t *cc;
4901 +
4902 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4903 +               if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
4904 +                       uid = cc->uid;
4905 +                       break;
4906 +               }
4907 +       }
4908 +       return uid;
4909 +}
4910 +
4911 +/* Internal cc_add */
4912 +static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4913 +                     uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4914 +{
4915 +       dwc_cc_t *cc;
4916 +       uint32_t uid;
4917 +
4918 +       if (cc_if->is_host) {
4919 +               uid = cc_match_cdid(cc_if, cdid);
4920 +       }
4921 +       else {
4922 +               uid = cc_match_chid(cc_if, chid);
4923 +       }
4924 +
4925 +       if (uid) {
4926 +               DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
4927 +               cc = cc_find(cc_if, uid);
4928 +       }
4929 +       else {
4930 +               cc = alloc_cc(mem_ctx, name, length);
4931 +               cc->uid = next_uid(cc_if);
4932 +               DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
4933 +       }
4934 +
4935 +       DWC_MEMCPY(&(cc->chid[0]), chid, 16);
4936 +       DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
4937 +       DWC_MEMCPY(&(cc->ck[0]), ck, 16);
4938 +
4939 +       DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
4940 +       dump_bytes("CHID", cc->chid, 16);
4941 +       dump_bytes("CDID", cc->cdid, 16);
4942 +       dump_bytes("CK", cc->ck, 16);
4943 +       return cc->uid;
4944 +}
4945 +
4946 +/* Internal cc_clear */
4947 +static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
4948 +{
4949 +       while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
4950 +               dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
4951 +               DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
4952 +               free_cc(mem_ctx, cc);
4953 +       }
4954 +}
4955 +
4956 +dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
4957 +                            dwc_notifier_t *notifier, unsigned is_host)
4958 +{
4959 +       dwc_cc_if_t *cc_if = NULL;
4960 +
4961 +       /* Allocate a common_cc_if structure */
4962 +       cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
4963 +
4964 +       if (!cc_if)
4965 +               return NULL;
4966 +
4967 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4968 +       DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
4969 +#else
4970 +       cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
4971 +#endif
4972 +       if (!cc_if->mutex) {
4973 +               dwc_free(mem_ctx, cc_if);
4974 +               return NULL;
4975 +       }
4976 +
4977 +       DWC_CIRCLEQ_INIT(&cc_if->list);
4978 +       cc_if->is_host = is_host;
4979 +       cc_if->notifier = notifier;
4980 +       return cc_if;
4981 +}
4982 +
4983 +void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
4984 +{
4985 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4986 +       DWC_MUTEX_FREE(cc_if->mutex);
4987 +#else
4988 +       dwc_mutex_free(mtx_ctx, cc_if->mutex);
4989 +#endif
4990 +       cc_clear(mem_ctx, cc_if);
4991 +       dwc_free(mem_ctx, cc_if);
4992 +}
4993 +
4994 +static void cc_changed(dwc_cc_if_t *cc_if)
4995 +{
4996 +       if (cc_if->notifier) {
4997 +               dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
4998 +       }
4999 +}
5000 +
5001 +void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
5002 +{
5003 +       DWC_MUTEX_LOCK(cc_if->mutex);
5004 +       cc_clear(mem_ctx, cc_if);
5005 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5006 +       cc_changed(cc_if);
5007 +}
5008 +
5009 +int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5010 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
5011 +{
5012 +       uint32_t uid;
5013 +
5014 +       DWC_MUTEX_LOCK(cc_if->mutex);
5015 +       uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
5016 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5017 +       cc_changed(cc_if);
5018 +
5019 +       return uid;
5020 +}
5021 +
5022 +void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
5023 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
5024 +{
5025 +       dwc_cc_t* cc;
5026 +
5027 +       DWC_DEBUGC("Change connection context %d", id);
5028 +
5029 +       DWC_MUTEX_LOCK(cc_if->mutex);
5030 +       cc = cc_find(cc_if, id);
5031 +       if (!cc) {
5032 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5033 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5034 +               return;
5035 +       }
5036 +
5037 +       if (chid) {
5038 +               DWC_MEMCPY(&(cc->chid[0]), chid, 16);
5039 +       }
5040 +       if (cdid) {
5041 +               DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
5042 +       }
5043 +       if (ck) {
5044 +               DWC_MEMCPY(&(cc->ck[0]), ck, 16);
5045 +       }
5046 +
5047 +       if (name) {
5048 +               if (cc->name) {
5049 +                       dwc_free(mem_ctx, cc->name);
5050 +               }
5051 +               cc->name = dwc_alloc(mem_ctx, length);
5052 +               if (!cc->name) {
5053 +                       DWC_ERROR("Out of memory in dwc_cc_change()\n");
5054 +                       DWC_MUTEX_UNLOCK(cc_if->mutex);
5055 +                       return;
5056 +               }
5057 +               cc->length = length;
5058 +               DWC_MEMCPY(cc->name, name, length);
5059 +       }
5060 +
5061 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5062 +
5063 +       cc_changed(cc_if);
5064 +
5065 +       DWC_DEBUGC("Changed connection context id=%d\n", id);
5066 +       dump_bytes("New CHID", cc->chid, 16);
5067 +       dump_bytes("New CDID", cc->cdid, 16);
5068 +       dump_bytes("New CK", cc->ck, 16);
5069 +}
5070 +
5071 +void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
5072 +{
5073 +       dwc_cc_t *cc;
5074 +
5075 +       DWC_DEBUGC("Removing connection context %d", id);
5076 +
5077 +       DWC_MUTEX_LOCK(cc_if->mutex);
5078 +       cc = cc_find(cc_if, id);
5079 +       if (!cc) {
5080 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5081 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5082 +               return;
5083 +       }
5084 +
5085 +       DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
5086 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5087 +       free_cc(mem_ctx, cc);
5088 +
5089 +       cc_changed(cc_if);
5090 +}
5091 +
5092 +uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
5093 +{
5094 +       uint8_t *buf, *x;
5095 +       uint8_t zero = 0;
5096 +       dwc_cc_t *cc;
5097 +
5098 +       DWC_MUTEX_LOCK(cc_if->mutex);
5099 +       *length = cc_data_size(cc_if);
5100 +       if (!(*length)) {
5101 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5102 +               return NULL;
5103 +       }
5104 +
5105 +       DWC_DEBUGC("Creating data for saving (length=%d)", *length);
5106 +
5107 +       buf = dwc_alloc(mem_ctx, *length);
5108 +       if (!buf) {
5109 +               *length = 0;
5110 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5111 +               return NULL;
5112 +       }
5113 +
5114 +       x = buf;
5115 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
5116 +               DWC_MEMCPY(x, cc->chid, 16);
5117 +               x += 16;
5118 +               DWC_MEMCPY(x, cc->cdid, 16);
5119 +               x += 16;
5120 +               DWC_MEMCPY(x, cc->ck, 16);
5121 +               x += 16;
5122 +               if (cc->name) {
5123 +                       DWC_MEMCPY(x, &cc->length, 1);
5124 +                       x += 1;
5125 +                       DWC_MEMCPY(x, cc->name, cc->length);
5126 +                       x += cc->length;
5127 +               }
5128 +               else {
5129 +                       DWC_MEMCPY(x, &zero, 1);
5130 +                       x += 1;
5131 +               }
5132 +       }
5133 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5134 +
5135 +       return buf;
5136 +}
5137 +
5138 +void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
5139 +{
5140 +       uint8_t name_length;
5141 +       uint8_t *name;
5142 +       uint8_t *chid;
5143 +       uint8_t *cdid;
5144 +       uint8_t *ck;
5145 +       uint32_t i = 0;
5146 +
5147 +       DWC_MUTEX_LOCK(cc_if->mutex);
5148 +       cc_clear(mem_ctx, cc_if);
5149 +
5150 +       while (i < length) {
5151 +               chid = &data[i];
5152 +               i += 16;
5153 +               cdid = &data[i];
5154 +               i += 16;
5155 +               ck = &data[i];
5156 +               i += 16;
5157 +
5158 +               name_length = data[i];
5159 +               i ++;
5160 +
5161 +               if (name_length) {
5162 +                       name = &data[i];
5163 +                       i += name_length;
5164 +               }
5165 +               else {
5166 +                       name = NULL;
5167 +               }
5168 +
5169 +               /* check to see if we haven't overflown the buffer */
5170 +               if (i > length) {
5171 +                       DWC_ERROR("Data format error while attempting to load CCs "
5172 +                                 "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
5173 +                       break;
5174 +               }
5175 +
5176 +               cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
5177 +       }
5178 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5179 +
5180 +       cc_changed(cc_if);
5181 +}
5182 +
5183 +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
5184 +{
5185 +       uint32_t uid = 0;
5186 +
5187 +       DWC_MUTEX_LOCK(cc_if->mutex);
5188 +       uid = cc_match_chid(cc_if, chid);
5189 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5190 +       return uid;
5191 +}
5192 +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
5193 +{
5194 +       uint32_t uid = 0;
5195 +
5196 +       DWC_MUTEX_LOCK(cc_if->mutex);
5197 +       uid = cc_match_cdid(cc_if, cdid);
5198 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5199 +       return uid;
5200 +}
5201 +
5202 +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
5203 +{
5204 +       uint8_t *ck = NULL;
5205 +       dwc_cc_t *cc;
5206 +
5207 +       DWC_MUTEX_LOCK(cc_if->mutex);
5208 +       cc = cc_find(cc_if, id);
5209 +       if (cc) {
5210 +               ck = cc->ck;
5211 +       }
5212 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5213 +
5214 +       return ck;
5215 +
5216 +}
5217 +
5218 +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
5219 +{
5220 +       uint8_t *retval = NULL;
5221 +       dwc_cc_t *cc;
5222 +
5223 +       DWC_MUTEX_LOCK(cc_if->mutex);
5224 +       cc = cc_find(cc_if, id);
5225 +       if (cc) {
5226 +               retval = cc->chid;
5227 +       }
5228 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5229 +
5230 +       return retval;
5231 +}
5232 +
5233 +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
5234 +{
5235 +       uint8_t *retval = NULL;
5236 +       dwc_cc_t *cc;
5237 +
5238 +       DWC_MUTEX_LOCK(cc_if->mutex);
5239 +       cc = cc_find(cc_if, id);
5240 +       if (cc) {
5241 +               retval = cc->cdid;
5242 +       }
5243 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5244 +
5245 +       return retval;
5246 +}
5247 +
5248 +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
5249 +{
5250 +       uint8_t *retval = NULL;
5251 +       dwc_cc_t *cc;
5252 +
5253 +       DWC_MUTEX_LOCK(cc_if->mutex);
5254 +       *length = 0;
5255 +       cc = cc_find(cc_if, id);
5256 +       if (cc) {
5257 +               *length = cc->length;
5258 +               retval = cc->name;
5259 +       }
5260 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5261 +
5262 +       return retval;
5263 +}
5264 +
5265 +#endif /* DWC_CCLIB */
5266 diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.h b/drivers/usb/host/dwc_common_port/dwc_cc.h
5267 new file mode 100644
5268 index 0000000..f86e6f2
5269 --- /dev/null
5270 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
5271 @@ -0,0 +1,224 @@
5272 +/* =========================================================================
5273 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
5274 + * $Revision: #4 $
5275 + * $Date: 2010/09/28 $
5276 + * $Change: 1596182 $
5277 + *
5278 + * Synopsys Portability Library Software and documentation
5279 + * (hereinafter, "Software") is an Unsupported proprietary work of
5280 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
5281 + * between Synopsys and you.
5282 + *
5283 + * The Software IS NOT an item of Licensed Software or Licensed Product
5284 + * under any End User Software License Agreement or Agreement for
5285 + * Licensed Product with Synopsys or any supplement thereto. You are
5286 + * permitted to use and redistribute this Software in source and binary
5287 + * forms, with or without modification, provided that redistributions
5288 + * of source code must retain this notice. You may not view, use,
5289 + * disclose, copy or distribute this file or any information contained
5290 + * herein except pursuant to this license grant from Synopsys. If you
5291 + * do not agree with this notice, including the disclaimer below, then
5292 + * you are not authorized to use the Software.
5293 + *
5294 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
5295 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5296 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
5297 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
5298 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5299 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5300 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5301 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
5302 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5303 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5304 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
5305 + * DAMAGE.
5306 + * ========================================================================= */
5307 +#ifndef _DWC_CC_H_
5308 +#define _DWC_CC_H_
5309 +
5310 +#ifdef __cplusplus
5311 +extern "C" {
5312 +#endif
5313 +
5314 +/** @file
5315 + *
5316 + * This file defines the Context Context library.
5317 + *
5318 + * The main data structure is dwc_cc_if_t which is returned by either the
5319 + * dwc_cc_if_alloc function or returned by the module to the user via a provided
5320 + * function. The data structure is opaque and should only be manipulated via the
5321 + * functions provied in this API.
5322 + *
5323 + * It manages a list of connection contexts and operations can be performed to
5324 + * add, remove, query, search, and change, those contexts.  Additionally,
5325 + * a dwc_notifier_t object can be requested from the manager so that
5326 + * the user can be notified whenever the context list has changed.
5327 + */
5328 +
5329 +#include "dwc_os.h"
5330 +#include "dwc_list.h"
5331 +#include "dwc_notifier.h"
5332 +
5333 +
5334 +/* Notifications */
5335 +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
5336 +
5337 +struct dwc_cc_if;
5338 +typedef struct dwc_cc_if dwc_cc_if_t;
5339 +
5340 +
5341 +/** @name Connection Context Operations */
5342 +/** @{ */
5343 +
5344 +/** This function allocates memory for a dwc_cc_if_t structure, initializes
5345 + * fields to default values, and returns a pointer to the structure or NULL on
5346 + * error. */
5347 +extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
5348 +                                   dwc_notifier_t *notifier, unsigned is_host);
5349 +
5350 +/** Frees the memory for the specified CC structure allocated from
5351 + * dwc_cc_if_alloc(). */
5352 +extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);
5353 +
5354 +/** Removes all contexts from the connection context list */
5355 +extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);
5356 +
5357 +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
5358 + * If a CHID already exists, the CK and name are overwritten.  Statistics are
5359 + * not overwritten.
5360 + *
5361 + * @param cc_if The cc_if structure.
5362 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.
5363 + * @param ck A pointer to the 16-byte CK.  This value will be copied.
5364 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.
5365 + * @param name An optional host friendly name as defined in the association model
5366 + * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.
5367 + * @param length The length othe unicode string.
5368 + * @return A unique identifier used to refer to this context that is valid for
5369 + * as long as this context is still in the list. */
5370 +extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5371 +                         uint8_t *cdid, uint8_t *ck, uint8_t *name,
5372 +                         uint8_t length);
5373 +
5374 +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
5375 + * list, preserving any accumulated statistics.  This would typically be called
5376 + * if the host decideds to change the context with a SET_CONNECTION request.
5377 + *
5378 + * @param cc_if The cc_if structure.
5379 + * @param id The identifier of the connection context.
5380 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL
5381 + * indicates no change.
5382 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL
5383 + * indicates no change.
5384 + * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL
5385 + * indicates no change.
5386 + * @param name Host friendly name UTF16-LE.  NULL indicates no change.
5387 + * @param length Length of name. */
5388 +extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,
5389 +                         uint8_t *chid, uint8_t *cdid, uint8_t *ck,
5390 +                         uint8_t *name, uint8_t length);
5391 +
5392 +/** Remove the specified connection context.
5393 + * @param cc_if The cc_if structure.
5394 + * @param id The identifier of the connection context to remove. */
5395 +extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);
5396 +
5397 +/** Get a binary block of data for the connection context list and attributes.
5398 + * This data can be used by the OS specific driver to save the connection
5399 + * context list into non-volatile memory.
5400 + *
5401 + * @param cc_if The cc_if structure.
5402 + * @param length Return the length of the data buffer.
5403 + * @return A pointer to the data buffer.  The memory for this buffer should be
5404 + * freed with DWC_FREE() after use. */
5405 +extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,
5406 +                                    unsigned int *length);
5407 +
5408 +/** Restore the connection context list from the binary data that was previously
5409 + * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific
5410 + * driver to load a connection context list from non-volatile memory.
5411 + *
5412 + * @param cc_if The cc_if structure.
5413 + * @param data The data bytes as returned from dwc_cc_data_for_save.
5414 + * @param length The length of the data. */
5415 +extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,
5416 +                                    uint8_t *data, unsigned int length);
5417 +
5418 +/** Find the connection context from the specified CHID.
5419 + *
5420 + * @param cc_if The cc_if structure.
5421 + * @param chid A pointer to the CHID data.
5422 + * @return A non-zero identifier of the connection context if the CHID matches.
5423 + * Otherwise returns 0. */
5424 +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
5425 +
5426 +/** Find the connection context from the specified CDID.
5427 + *
5428 + * @param cc_if The cc_if structure.
5429 + * @param cdid A pointer to the CDID data.
5430 + * @return A non-zero identifier of the connection context if the CHID matches.
5431 + * Otherwise returns 0. */
5432 +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
5433 +
5434 +/** Retrieve the CK from the specified connection context.
5435 + *
5436 + * @param cc_if The cc_if structure.
5437 + * @param id The identifier of the connection context.
5438 + * @return A pointer to the CK data.  The memory does not need to be freed. */
5439 +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
5440 +
5441 +/** Retrieve the CHID from the specified connection context.
5442 + *
5443 + * @param cc_if The cc_if structure.
5444 + * @param id The identifier of the connection context.
5445 + * @return A pointer to the CHID data.  The memory does not need to be freed. */
5446 +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
5447 +
5448 +/** Retrieve the CDID from the specified connection context.
5449 + *
5450 + * @param cc_if The cc_if structure.
5451 + * @param id The identifier of the connection context.
5452 + * @return A pointer to the CDID data.  The memory does not need to be freed. */
5453 +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
5454 +
5455 +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
5456 +
5457 +/** Checks a buffer for non-zero.
5458 + * @param id A pointer to a 16 byte buffer.
5459 + * @return true if the 16 byte value is non-zero. */
5460 +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
5461 +       int i;
5462 +       for (i=0; i<16; i++) {
5463 +               if (id[i]) return 1;
5464 +       }
5465 +       return 0;
5466 +}
5467 +
5468 +/** Checks a buffer for zero.
5469 + * @param id A pointer to a 16 byte buffer.
5470 + * @return true if the 16 byte value is zero. */
5471 +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
5472 +       return !dwc_assoc_is_not_zero_id(id);
5473 +}
5474 +
5475 +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
5476 + * buffer. */
5477 +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
5478 +       char *ptr = buffer;
5479 +       int i;
5480 +       for (i=0; i<16; i++) {
5481 +               ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
5482 +               if (i < 15) {
5483 +                       ptr += DWC_SPRINTF(ptr, " ");
5484 +               }
5485 +       }
5486 +       return ptr - buffer;
5487 +}
5488 +
5489 +/** @} */
5490 +
5491 +#ifdef __cplusplus
5492 +}
5493 +#endif
5494 +
5495 +#endif /* _DWC_CC_H_ */
5496 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5497 new file mode 100644
5498 index 0000000..6dd04b5
5499 --- /dev/null
5500 +++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5501 @@ -0,0 +1,1308 @@
5502 +#include "dwc_os.h"
5503 +#include "dwc_list.h"
5504 +
5505 +#ifdef DWC_CCLIB
5506 +# include "dwc_cc.h"
5507 +#endif
5508 +
5509 +#ifdef DWC_CRYPTOLIB
5510 +# include "dwc_modpow.h"
5511 +# include "dwc_dh.h"
5512 +# include "dwc_crypto.h"
5513 +#endif
5514 +
5515 +#ifdef DWC_NOTIFYLIB
5516 +# include "dwc_notifier.h"
5517 +#endif
5518 +
5519 +/* OS-Level Implementations */
5520 +
5521 +/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */
5522 +
5523 +
5524 +/* MISC */
5525 +
5526 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
5527 +{
5528 +       return memset(dest, byte, size);
5529 +}
5530 +
5531 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
5532 +{
5533 +       return memcpy(dest, src, size);
5534 +}
5535 +
5536 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
5537 +{
5538 +       bcopy(src, dest, size);
5539 +       return dest;
5540 +}
5541 +
5542 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
5543 +{
5544 +       return memcmp(m1, m2, size);
5545 +}
5546 +
5547 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
5548 +{
5549 +       return strncmp(s1, s2, size);
5550 +}
5551 +
5552 +int DWC_STRCMP(void *s1, void *s2)
5553 +{
5554 +       return strcmp(s1, s2);
5555 +}
5556 +
5557 +int DWC_STRLEN(char const *str)
5558 +{
5559 +       return strlen(str);
5560 +}
5561 +
5562 +char *DWC_STRCPY(char *to, char const *from)
5563 +{
5564 +       return strcpy(to, from);
5565 +}
5566 +
5567 +char *DWC_STRDUP(char const *str)
5568 +{
5569 +       int len = DWC_STRLEN(str) + 1;
5570 +       char *new = DWC_ALLOC_ATOMIC(len);
5571 +
5572 +       if (!new) {
5573 +               return NULL;
5574 +       }
5575 +
5576 +       DWC_MEMCPY(new, str, len);
5577 +       return new;
5578 +}
5579 +
5580 +int DWC_ATOI(char *str, int32_t *value)
5581 +{
5582 +       char *end = NULL;
5583 +
5584 +       *value = strtol(str, &end, 0);
5585 +       if (*end == '\0') {
5586 +               return 0;
5587 +       }
5588 +
5589 +       return -1;
5590 +}
5591 +
5592 +int DWC_ATOUI(char *str, uint32_t *value)
5593 +{
5594 +       char *end = NULL;
5595 +
5596 +       *value = strtoul(str, &end, 0);
5597 +       if (*end == '\0') {
5598 +               return 0;
5599 +       }
5600 +
5601 +       return -1;
5602 +}
5603 +
5604 +
5605 +#ifdef DWC_UTFLIB
5606 +/* From usbstring.c */
5607 +
5608 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
5609 +{
5610 +       int     count = 0;
5611 +       u8      c;
5612 +       u16     uchar;
5613 +
5614 +       /* this insists on correct encodings, though not minimal ones.
5615 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
5616 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
5617 +        */
5618 +       while (len != 0 && (c = (u8) *s++) != 0) {
5619 +               if (unlikely(c & 0x80)) {
5620 +                       // 2-byte sequence:
5621 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
5622 +                       if ((c & 0xe0) == 0xc0) {
5623 +                               uchar = (c & 0x1f) << 6;
5624 +
5625 +                               c = (u8) *s++;
5626 +                               if ((c & 0xc0) != 0xc0)
5627 +                                       goto fail;
5628 +                               c &= 0x3f;
5629 +                               uchar |= c;
5630 +
5631 +                       // 3-byte sequence (most CJKV characters):
5632 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
5633 +                       } else if ((c & 0xf0) == 0xe0) {
5634 +                               uchar = (c & 0x0f) << 12;
5635 +
5636 +                               c = (u8) *s++;
5637 +                               if ((c & 0xc0) != 0xc0)
5638 +                                       goto fail;
5639 +                               c &= 0x3f;
5640 +                               uchar |= c << 6;
5641 +
5642 +                               c = (u8) *s++;
5643 +                               if ((c & 0xc0) != 0xc0)
5644 +                                       goto fail;
5645 +                               c &= 0x3f;
5646 +                               uchar |= c;
5647 +
5648 +                               /* no bogus surrogates */
5649 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
5650 +                                       goto fail;
5651 +
5652 +                       // 4-byte sequence (surrogate pairs, currently rare):
5653 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
5654 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
5655 +                       // (uuuuu = wwww + 1)
5656 +                       // FIXME accept the surrogate code points (only)
5657 +                       } else
5658 +                               goto fail;
5659 +               } else
5660 +                       uchar = c;
5661 +               put_unaligned (cpu_to_le16 (uchar), cp++);
5662 +               count++;
5663 +               len--;
5664 +       }
5665 +       return count;
5666 +fail:
5667 +       return -1;
5668 +}
5669 +
5670 +#endif /* DWC_UTFLIB */
5671 +
5672 +
5673 +/* dwc_debug.h */
5674 +
5675 +dwc_bool_t DWC_IN_IRQ(void)
5676 +{
5677 +//     return in_irq();
5678 +       return 0;
5679 +}
5680 +
5681 +dwc_bool_t DWC_IN_BH(void)
5682 +{
5683 +//     return in_softirq();
5684 +       return 0;
5685 +}
5686 +
5687 +void DWC_VPRINTF(char *format, va_list args)
5688 +{
5689 +       vprintf(format, args);
5690 +}
5691 +
5692 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
5693 +{
5694 +       return vsnprintf(str, size, format, args);
5695 +}
5696 +
5697 +void DWC_PRINTF(char *format, ...)
5698 +{
5699 +       va_list args;
5700 +
5701 +       va_start(args, format);
5702 +       DWC_VPRINTF(format, args);
5703 +       va_end(args);
5704 +}
5705 +
5706 +int DWC_SPRINTF(char *buffer, char *format, ...)
5707 +{
5708 +       int retval;
5709 +       va_list args;
5710 +
5711 +       va_start(args, format);
5712 +       retval = vsprintf(buffer, format, args);
5713 +       va_end(args);
5714 +       return retval;
5715 +}
5716 +
5717 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
5718 +{
5719 +       int retval;
5720 +       va_list args;
5721 +
5722 +       va_start(args, format);
5723 +       retval = vsnprintf(buffer, size, format, args);
5724 +       va_end(args);
5725 +       return retval;
5726 +}
5727 +
5728 +void __DWC_WARN(char *format, ...)
5729 +{
5730 +       va_list args;
5731 +
5732 +       va_start(args, format);
5733 +       DWC_VPRINTF(format, args);
5734 +       va_end(args);
5735 +}
5736 +
5737 +void __DWC_ERROR(char *format, ...)
5738 +{
5739 +       va_list args;
5740 +
5741 +       va_start(args, format);
5742 +       DWC_VPRINTF(format, args);
5743 +       va_end(args);
5744 +}
5745 +
5746 +void DWC_EXCEPTION(char *format, ...)
5747 +{
5748 +       va_list args;
5749 +
5750 +       va_start(args, format);
5751 +       DWC_VPRINTF(format, args);
5752 +       va_end(args);
5753 +//     BUG_ON(1);      ???
5754 +}
5755 +
5756 +#ifdef DEBUG
5757 +void __DWC_DEBUG(char *format, ...)
5758 +{
5759 +       va_list args;
5760 +
5761 +       va_start(args, format);
5762 +       DWC_VPRINTF(format, args);
5763 +       va_end(args);
5764 +}
5765 +#endif
5766 +
5767 +
5768 +/* dwc_mem.h */
5769 +
5770 +#if 0
5771 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
5772 +                               uint32_t align,
5773 +                               uint32_t alloc)
5774 +{
5775 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
5776 +                                               size, align, alloc);
5777 +       return (dwc_pool_t *)pool;
5778 +}
5779 +
5780 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
5781 +{
5782 +       dma_pool_destroy((struct dma_pool *)pool);
5783 +}
5784 +
5785 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5786 +{
5787 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
5788 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
5789 +}
5790 +
5791 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5792 +{
5793 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
5794 +       memset(..);
5795 +}
5796 +
5797 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
5798 +{
5799 +       dma_pool_free(pool, vaddr, daddr);
5800 +}
5801 +#endif
5802 +
5803 +static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5804 +{
5805 +       if (error)
5806 +               return;
5807 +       *(bus_addr_t *)arg = segs[0].ds_addr;
5808 +}
5809 +
5810 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
5811 +{
5812 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5813 +       int error;
5814 +
5815 +       error = bus_dma_tag_create(
5816 +#if __FreeBSD_version >= 700000
5817 +                       bus_get_dma_tag(dma->dev),      /* parent */
5818 +#else
5819 +                       NULL,                           /* parent */
5820 +#endif
5821 +                       4, 0,                           /* alignment, bounds */
5822 +                       BUS_SPACE_MAXADDR_32BIT,        /* lowaddr */
5823 +                       BUS_SPACE_MAXADDR,              /* highaddr */
5824 +                       NULL, NULL,                     /* filter, filterarg */
5825 +                       size,                           /* maxsize */
5826 +                       1,                              /* nsegments */
5827 +                       size,                           /* maxsegsize */
5828 +                       0,                              /* flags */
5829 +                       NULL,                           /* lockfunc */
5830 +                       NULL,                           /* lockarg */
5831 +                       &dma->dma_tag);
5832 +       if (error) {
5833 +               device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",
5834 +                             __func__, error);
5835 +               goto fail_0;
5836 +       }
5837 +
5838 +       error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,
5839 +                                BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
5840 +       if (error) {
5841 +               device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
5842 +                             __func__, (uintmax_t)size, error);
5843 +               goto fail_1;
5844 +       }
5845 +
5846 +       dma->dma_paddr = 0;
5847 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,
5848 +                               dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);
5849 +       if (error || dma->dma_paddr == 0) {
5850 +               device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",
5851 +                             __func__, error);
5852 +               goto fail_2;
5853 +       }
5854 +
5855 +       *dma_addr = dma->dma_paddr;
5856 +       return dma->dma_vaddr;
5857 +
5858 +fail_2:
5859 +       bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5860 +fail_1:
5861 +       bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5862 +       bus_dma_tag_destroy(dma->dma_tag);
5863 +fail_0:
5864 +       dma->dma_map = NULL;
5865 +       dma->dma_tag = NULL;
5866 +
5867 +       return NULL;
5868 +}
5869 +
5870 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
5871 +{
5872 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5873 +
5874 +       if (dma->dma_tag == NULL)
5875 +               return;
5876 +       if (dma->dma_map != NULL) {
5877 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map,
5878 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
5879 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5880 +               bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5881 +               dma->dma_map = NULL;
5882 +       }
5883 +
5884 +       bus_dma_tag_destroy(dma->dma_tag);
5885 +       dma->dma_tag = NULL;
5886 +}
5887 +
5888 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
5889 +{
5890 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
5891 +}
5892 +
5893 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
5894 +{
5895 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
5896 +}
5897 +
5898 +void __DWC_FREE(void *mem_ctx, void *addr)
5899 +{
5900 +       free(addr, M_DEVBUF);
5901 +}
5902 +
5903 +
5904 +#ifdef DWC_CRYPTOLIB
5905 +/* dwc_crypto.h */
5906 +
5907 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
5908 +{
5909 +       get_random_bytes(buffer, length);
5910 +}
5911 +
5912 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
5913 +{
5914 +       struct crypto_blkcipher *tfm;
5915 +       struct blkcipher_desc desc;
5916 +       struct scatterlist sgd;
5917 +       struct scatterlist sgs;
5918 +
5919 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
5920 +       if (tfm == NULL) {
5921 +               printk("failed to load transform for aes CBC\n");
5922 +               return -1;
5923 +       }
5924 +
5925 +       crypto_blkcipher_setkey(tfm, key, keylen);
5926 +       crypto_blkcipher_set_iv(tfm, iv, 16);
5927 +
5928 +       sg_init_one(&sgd, out, messagelen);
5929 +       sg_init_one(&sgs, message, messagelen);
5930 +
5931 +       desc.tfm = tfm;
5932 +       desc.flags = 0;
5933 +
5934 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
5935 +               crypto_free_blkcipher(tfm);
5936 +               DWC_ERROR("AES CBC encryption failed");
5937 +               return -1;
5938 +       }
5939 +
5940 +       crypto_free_blkcipher(tfm);
5941 +       return 0;
5942 +}
5943 +
5944 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
5945 +{
5946 +       struct crypto_hash *tfm;
5947 +       struct hash_desc desc;
5948 +       struct scatterlist sg;
5949 +
5950 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
5951 +       if (IS_ERR(tfm)) {
5952 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
5953 +               return 0;
5954 +       }
5955 +       desc.tfm = tfm;
5956 +       desc.flags = 0;
5957 +
5958 +       sg_init_one(&sg, message, len);
5959 +       crypto_hash_digest(&desc, &sg, len, out);
5960 +       crypto_free_hash(tfm);
5961 +
5962 +       return 1;
5963 +}
5964 +
5965 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
5966 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
5967 +{
5968 +       struct crypto_hash *tfm;
5969 +       struct hash_desc desc;
5970 +       struct scatterlist sg;
5971 +
5972 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
5973 +       if (IS_ERR(tfm)) {
5974 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
5975 +               return 0;
5976 +       }
5977 +       desc.tfm = tfm;
5978 +       desc.flags = 0;
5979 +
5980 +       sg_init_one(&sg, message, messagelen);
5981 +       crypto_hash_setkey(tfm, key, keylen);
5982 +       crypto_hash_digest(&desc, &sg, messagelen, out);
5983 +       crypto_free_hash(tfm);
5984 +
5985 +       return 1;
5986 +}
5987 +
5988 +#endif /* DWC_CRYPTOLIB */
5989 +
5990 +
5991 +/* Byte Ordering Conversions */
5992 +
5993 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
5994 +{
5995 +#ifdef __LITTLE_ENDIAN
5996 +       return *p;
5997 +#else
5998 +       uint8_t *u_p = (uint8_t *)p;
5999 +
6000 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6001 +#endif
6002 +}
6003 +
6004 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
6005 +{
6006 +#ifdef __BIG_ENDIAN
6007 +       return *p;
6008 +#else
6009 +       uint8_t *u_p = (uint8_t *)p;
6010 +
6011 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6012 +#endif
6013 +}
6014 +
6015 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
6016 +{
6017 +#ifdef __LITTLE_ENDIAN
6018 +       return *p;
6019 +#else
6020 +       uint8_t *u_p = (uint8_t *)p;
6021 +
6022 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6023 +#endif
6024 +}
6025 +
6026 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
6027 +{
6028 +#ifdef __BIG_ENDIAN
6029 +       return *p;
6030 +#else
6031 +       uint8_t *u_p = (uint8_t *)p;
6032 +
6033 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6034 +#endif
6035 +}
6036 +
6037 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
6038 +{
6039 +#ifdef __LITTLE_ENDIAN
6040 +       return *p;
6041 +#else
6042 +       uint8_t *u_p = (uint8_t *)p;
6043 +       return (u_p[1] | (u_p[0] << 8));
6044 +#endif
6045 +}
6046 +
6047 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
6048 +{
6049 +#ifdef __BIG_ENDIAN
6050 +       return *p;
6051 +#else
6052 +       uint8_t *u_p = (uint8_t *)p;
6053 +       return (u_p[1] | (u_p[0] << 8));
6054 +#endif
6055 +}
6056 +
6057 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
6058 +{
6059 +#ifdef __LITTLE_ENDIAN
6060 +       return *p;
6061 +#else
6062 +       uint8_t *u_p = (uint8_t *)p;
6063 +       return (u_p[1] | (u_p[0] << 8));
6064 +#endif
6065 +}
6066 +
6067 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
6068 +{
6069 +#ifdef __BIG_ENDIAN
6070 +       return *p;
6071 +#else
6072 +       uint8_t *u_p = (uint8_t *)p;
6073 +       return (u_p[1] | (u_p[0] << 8));
6074 +#endif
6075 +}
6076 +
6077 +
6078 +/* Registers */
6079 +
6080 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
6081 +{
6082 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6083 +       bus_size_t ior = (bus_size_t)reg;
6084 +
6085 +       return bus_space_read_4(io->iot, io->ioh, ior);
6086 +}
6087 +
6088 +#if 0
6089 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
6090 +{
6091 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6092 +       bus_size_t ior = (bus_size_t)reg;
6093 +
6094 +       return bus_space_read_8(io->iot, io->ioh, ior);
6095 +}
6096 +#endif
6097 +
6098 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
6099 +{
6100 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6101 +       bus_size_t ior = (bus_size_t)reg;
6102 +
6103 +       bus_space_write_4(io->iot, io->ioh, ior, value);
6104 +}
6105 +
6106 +#if 0
6107 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
6108 +{
6109 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6110 +       bus_size_t ior = (bus_size_t)reg;
6111 +
6112 +       bus_space_write_8(io->iot, io->ioh, ior, value);
6113 +}
6114 +#endif
6115 +
6116 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
6117 +                     uint32_t set_mask)
6118 +{
6119 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6120 +       bus_size_t ior = (bus_size_t)reg;
6121 +
6122 +       bus_space_write_4(io->iot, io->ioh, ior,
6123 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
6124 +                          ~clear_mask) | set_mask);
6125 +}
6126 +
6127 +#if 0
6128 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
6129 +                     uint64_t set_mask)
6130 +{
6131 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6132 +       bus_size_t ior = (bus_size_t)reg;
6133 +
6134 +       bus_space_write_8(io->iot, io->ioh, ior,
6135 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
6136 +                          ~clear_mask) | set_mask);
6137 +}
6138 +#endif
6139 +
6140 +
6141 +/* Locking */
6142 +
6143 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
6144 +{
6145 +       struct mtx *sl = DWC_ALLOC(sizeof(*sl));
6146 +
6147 +       if (!sl) {
6148 +               DWC_ERROR("Cannot allocate memory for spinlock");
6149 +               return NULL;
6150 +       }
6151 +
6152 +       mtx_init(sl, "dw3spn", NULL, MTX_SPIN);
6153 +       return (dwc_spinlock_t *)sl;
6154 +}
6155 +
6156 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
6157 +{
6158 +       struct mtx *sl = (struct mtx *)lock;
6159 +
6160 +       mtx_destroy(sl);
6161 +       DWC_FREE(sl);
6162 +}
6163 +
6164 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
6165 +{
6166 +       mtx_lock_spin((struct mtx *)lock);      // ???
6167 +}
6168 +
6169 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
6170 +{
6171 +       mtx_unlock_spin((struct mtx *)lock);    // ???
6172 +}
6173 +
6174 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
6175 +{
6176 +       mtx_lock_spin((struct mtx *)lock);
6177 +}
6178 +
6179 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
6180 +{
6181 +       mtx_unlock_spin((struct mtx *)lock);
6182 +}
6183 +
6184 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
6185 +{
6186 +       struct mtx *m;
6187 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));
6188 +
6189 +       if (!mutex) {
6190 +               DWC_ERROR("Cannot allocate memory for mutex");
6191 +               return NULL;
6192 +       }
6193 +
6194 +       m = (struct mtx *)mutex;
6195 +       mtx_init(m, "dw3mtx", NULL, MTX_DEF);
6196 +       return mutex;
6197 +}
6198 +
6199 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
6200 +#else
6201 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
6202 +{
6203 +       mtx_destroy((struct mtx *)mutex);
6204 +       DWC_FREE(mutex);
6205 +}
6206 +#endif
6207 +
6208 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
6209 +{
6210 +       struct mtx *m = (struct mtx *)mutex;
6211 +
6212 +       mtx_lock(m);
6213 +}
6214 +
6215 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
6216 +{
6217 +       struct mtx *m = (struct mtx *)mutex;
6218 +
6219 +       return mtx_trylock(m);
6220 +}
6221 +
6222 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
6223 +{
6224 +       struct mtx *m = (struct mtx *)mutex;
6225 +
6226 +       mtx_unlock(m);
6227 +}
6228 +
6229 +
6230 +/* Timing */
6231 +
6232 +void DWC_UDELAY(uint32_t usecs)
6233 +{
6234 +       DELAY(usecs);
6235 +}
6236 +
6237 +void DWC_MDELAY(uint32_t msecs)
6238 +{
6239 +       do {
6240 +               DELAY(1000);
6241 +       } while (--msecs);
6242 +}
6243 +
6244 +void DWC_MSLEEP(uint32_t msecs)
6245 +{
6246 +       struct timeval tv;
6247 +
6248 +       tv.tv_sec = msecs / 1000;
6249 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6250 +       pause("dw3slp", tvtohz(&tv));
6251 +}
6252 +
6253 +uint32_t DWC_TIME(void)
6254 +{
6255 +       struct timeval tv;
6256 +
6257 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
6258 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
6259 +}
6260 +
6261 +
6262 +/* Timers */
6263 +
6264 +struct dwc_timer {
6265 +       struct callout t;
6266 +       char *name;
6267 +       dwc_spinlock_t *lock;
6268 +       dwc_timer_callback_t cb;
6269 +       void *data;
6270 +};
6271 +
6272 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
6273 +{
6274 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
6275 +
6276 +       if (!t) {
6277 +               DWC_ERROR("Cannot allocate memory for timer");
6278 +               return NULL;
6279 +       }
6280 +
6281 +       callout_init(&t->t, 1);
6282 +
6283 +       t->name = DWC_STRDUP(name);
6284 +       if (!t->name) {
6285 +               DWC_ERROR("Cannot allocate memory for timer->name");
6286 +               goto no_name;
6287 +       }
6288 +
6289 +       t->lock = DWC_SPINLOCK_ALLOC();
6290 +       if (!t->lock) {
6291 +               DWC_ERROR("Cannot allocate memory for lock");
6292 +               goto no_lock;
6293 +       }
6294 +
6295 +       t->cb = cb;
6296 +       t->data = data;
6297 +
6298 +       return t;
6299 +
6300 + no_lock:
6301 +       DWC_FREE(t->name);
6302 + no_name:
6303 +       DWC_FREE(t);
6304 +
6305 +       return NULL;
6306 +}
6307 +
6308 +void DWC_TIMER_FREE(dwc_timer_t *timer)
6309 +{
6310 +       callout_stop(&timer->t);
6311 +       DWC_SPINLOCK_FREE(timer->lock);
6312 +       DWC_FREE(timer->name);
6313 +       DWC_FREE(timer);
6314 +}
6315 +
6316 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
6317 +{
6318 +       struct timeval tv;
6319 +
6320 +       tv.tv_sec = time / 1000;
6321 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6322 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
6323 +}
6324 +
6325 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
6326 +{
6327 +       callout_stop(&timer->t);
6328 +}
6329 +
6330 +
6331 +/* Wait Queues */
6332 +
6333 +struct dwc_waitq {
6334 +       struct mtx lock;
6335 +       int abort;
6336 +};
6337 +
6338 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
6339 +{
6340 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
6341 +
6342 +       if (!wq) {
6343 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6344 +               return NULL;
6345 +       }
6346 +
6347 +       mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);
6348 +       wq->abort = 0;
6349 +
6350 +       return wq;
6351 +}
6352 +
6353 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
6354 +{
6355 +       mtx_destroy(&wq->lock);
6356 +       DWC_FREE(wq);
6357 +}
6358 +
6359 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
6360 +{
6361 +//     intrmask_t ipl;
6362 +       int result = 0;
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 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout
6371 +//             ipl = splbio();
6372 +       }
6373 +
6374 +       if (result == ERESTART) {       // signaled - restart
6375 +               result = -DWC_E_RESTART;
6376 +
6377 +       } else if (result == EINTR) {   // signaled - interrupt
6378 +               result = -DWC_E_ABORT;
6379 +
6380 +       } else if (wq->abort) {
6381 +               result = -DWC_E_ABORT;
6382 +
6383 +       } else {
6384 +               result = 0;
6385 +       }
6386 +
6387 +       wq->abort = 0;
6388 +//     splx(ipl);
6389 +       mtx_unlock(&wq->lock);
6390 +       return result;
6391 +}
6392 +
6393 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
6394 +                              void *data, int32_t msecs)
6395 +{
6396 +       struct timeval tv, tv1, tv2;
6397 +//     intrmask_t ipl;
6398 +       int result = 0;
6399 +
6400 +       tv.tv_sec = msecs / 1000;
6401 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6402 +
6403 +       mtx_lock(&wq->lock);
6404 +//     ipl = splbio();
6405 +
6406 +       /* Skip the sleep if already aborted or triggered */
6407 +       if (!wq->abort && !cond(data)) {
6408 +//             splx(ipl);
6409 +               getmicrouptime(&tv1);
6410 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));
6411 +               getmicrouptime(&tv2);
6412 +//             ipl = splbio();
6413 +       }
6414 +
6415 +       if (result == 0) {                      // awoken
6416 +               if (wq->abort) {
6417 +                       result = -DWC_E_ABORT;
6418 +               } else {
6419 +                       tv2.tv_usec -= tv1.tv_usec;
6420 +                       if (tv2.tv_usec < 0) {
6421 +                               tv2.tv_usec += 1000000;
6422 +                               tv2.tv_sec--;
6423 +                       }
6424 +
6425 +                       tv2.tv_sec -= tv1.tv_sec;
6426 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
6427 +                       result = msecs - result;
6428 +                       if (result <= 0)
6429 +                               result = 1;
6430 +               }
6431 +       } else if (result == ERESTART) {        // signaled - restart
6432 +               result = -DWC_E_RESTART;
6433 +
6434 +       } else if (result == EINTR) {           // signaled - interrupt
6435 +               result = -DWC_E_ABORT;
6436 +
6437 +       } else {                                // timed out
6438 +               result = -DWC_E_TIMEOUT;
6439 +       }
6440 +
6441 +       wq->abort = 0;
6442 +//     splx(ipl);
6443 +       mtx_unlock(&wq->lock);
6444 +       return result;
6445 +}
6446 +
6447 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
6448 +{
6449 +       wakeup(wq);
6450 +}
6451 +
6452 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
6453 +{
6454 +//     intrmask_t ipl;
6455 +
6456 +       mtx_lock(&wq->lock);
6457 +//     ipl = splbio();
6458 +       wq->abort = 1;
6459 +       wakeup(wq);
6460 +//     splx(ipl);
6461 +       mtx_unlock(&wq->lock);
6462 +}
6463 +
6464 +
6465 +/* Threading */
6466 +
6467 +struct dwc_thread {
6468 +       struct proc *proc;
6469 +       int abort;
6470 +};
6471 +
6472 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
6473 +{
6474 +       int retval;
6475 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
6476 +
6477 +       if (!thread) {
6478 +               return NULL;
6479 +       }
6480 +
6481 +       thread->abort = 0;
6482 +       retval = kthread_create((void (*)(void *))func, data, &thread->proc,
6483 +                               RFPROC | RFNOWAIT, 0, "%s", name);
6484 +       if (retval) {
6485 +               DWC_FREE(thread);
6486 +               return NULL;
6487 +       }
6488 +
6489 +       return thread;
6490 +}
6491 +
6492 +int DWC_THREAD_STOP(dwc_thread_t *thread)
6493 +{
6494 +       int retval;
6495 +
6496 +       thread->abort = 1;
6497 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
6498 +
6499 +       if (retval == 0) {
6500 +               /* DWC_THREAD_EXIT() will free the thread struct */
6501 +               return 0;
6502 +       }
6503 +
6504 +       /* NOTE: We leak the thread struct if thread doesn't die */
6505 +
6506 +       if (retval == EWOULDBLOCK) {
6507 +               return -DWC_E_TIMEOUT;
6508 +       }
6509 +
6510 +       return -DWC_E_UNKNOWN;
6511 +}
6512 +
6513 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
6514 +{
6515 +       return thread->abort;
6516 +}
6517 +
6518 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
6519 +{
6520 +       wakeup(&thread->abort);
6521 +       DWC_FREE(thread);
6522 +       kthread_exit(0);
6523 +}
6524 +
6525 +
6526 +/* tasklets
6527 + - Runs in interrupt context (cannot sleep)
6528 + - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]
6529 + - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]
6530 + */
6531 +struct dwc_tasklet {
6532 +       struct task t;
6533 +       dwc_tasklet_callback_t cb;
6534 +       void *data;
6535 +};
6536 +
6537 +static void tasklet_callback(void *data, int pending)  // what to do with pending ???
6538 +{
6539 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
6540 +
6541 +       task->cb(task->data);
6542 +}
6543 +
6544 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
6545 +{
6546 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
6547 +
6548 +       if (task) {
6549 +               task->cb = cb;
6550 +               task->data = data;
6551 +               TASK_INIT(&task->t, 0, tasklet_callback, task);
6552 +       } else {
6553 +               DWC_ERROR("Cannot allocate memory for tasklet");
6554 +       }
6555 +
6556 +       return task;
6557 +}
6558 +
6559 +void DWC_TASK_FREE(dwc_tasklet_t *task)
6560 +{
6561 +       taskqueue_drain(taskqueue_fast, &task->t);      // ???
6562 +       DWC_FREE(task);
6563 +}
6564 +
6565 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
6566 +{
6567 +       /* Uses predefined system queue */
6568 +       taskqueue_enqueue_fast(taskqueue_fast, &task->t);
6569 +}
6570 +
6571 +
6572 +/* workqueues
6573 + - Runs in process context (can sleep)
6574 + */
6575 +typedef struct work_container {
6576 +       dwc_work_callback_t cb;
6577 +       void *data;
6578 +       dwc_workq_t *wq;
6579 +       char *name;
6580 +       int hz;
6581 +
6582 +#ifdef DEBUG
6583 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
6584 +#endif
6585 +       struct task task;
6586 +} work_container_t;
6587 +
6588 +#ifdef DEBUG
6589 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
6590 +#endif
6591 +
6592 +struct dwc_workq {
6593 +       struct taskqueue *taskq;
6594 +       dwc_spinlock_t *lock;
6595 +       dwc_waitq_t *waitq;
6596 +       int pending;
6597 +
6598 +#ifdef DEBUG
6599 +       struct work_container_queue entries;
6600 +#endif
6601 +};
6602 +
6603 +static void do_work(void *data, int pending)   // what to do with pending ???
6604 +{
6605 +       work_container_t *container = (work_container_t *)data;
6606 +       dwc_workq_t *wq = container->wq;
6607 +       dwc_irqflags_t flags;
6608 +
6609 +       if (container->hz) {
6610 +               pause("dw3wrk", container->hz);
6611 +       }
6612 +
6613 +       container->cb(container->data);
6614 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
6615 +
6616 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6617 +
6618 +#ifdef DEBUG
6619 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
6620 +#endif
6621 +       if (container->name)
6622 +               DWC_FREE(container->name);
6623 +       DWC_FREE(container);
6624 +       wq->pending--;
6625 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6626 +       DWC_WAITQ_TRIGGER(wq->waitq);
6627 +}
6628 +
6629 +static int work_done(void *data)
6630 +{
6631 +       dwc_workq_t *workq = (dwc_workq_t *)data;
6632 +
6633 +       return workq->pending == 0;
6634 +}
6635 +
6636 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
6637 +{
6638 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
6639 +}
6640 +
6641 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
6642 +{
6643 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
6644 +
6645 +       if (!wq) {
6646 +               DWC_ERROR("Cannot allocate memory for workqueue");
6647 +               return NULL;
6648 +       }
6649 +
6650 +       wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);
6651 +       if (!wq->taskq) {
6652 +               DWC_ERROR("Cannot allocate memory for taskqueue");
6653 +               goto no_taskq;
6654 +       }
6655 +
6656 +       wq->pending = 0;
6657 +
6658 +       wq->lock = DWC_SPINLOCK_ALLOC();
6659 +       if (!wq->lock) {
6660 +               DWC_ERROR("Cannot allocate memory for spinlock");
6661 +               goto no_lock;
6662 +       }
6663 +
6664 +       wq->waitq = DWC_WAITQ_ALLOC();
6665 +       if (!wq->waitq) {
6666 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6667 +               goto no_waitq;
6668 +       }
6669 +
6670 +       taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");
6671 +
6672 +#ifdef DEBUG
6673 +       DWC_CIRCLEQ_INIT(&wq->entries);
6674 +#endif
6675 +       return wq;
6676 +
6677 + no_waitq:
6678 +       DWC_SPINLOCK_FREE(wq->lock);
6679 + no_lock:
6680 +       taskqueue_free(wq->taskq);
6681 + no_taskq:
6682 +       DWC_FREE(wq);
6683 +
6684 +       return NULL;
6685 +}
6686 +
6687 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
6688 +{
6689 +#ifdef DEBUG
6690 +       dwc_irqflags_t flags;
6691 +
6692 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6693 +
6694 +       if (wq->pending != 0) {
6695 +               struct work_container *container;
6696 +
6697 +               DWC_ERROR("Destroying work queue with pending work");
6698 +
6699 +               DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {
6700 +                       DWC_ERROR("Work %s still pending", container->name);
6701 +               }
6702 +       }
6703 +
6704 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6705 +#endif
6706 +       DWC_WAITQ_FREE(wq->waitq);
6707 +       DWC_SPINLOCK_FREE(wq->lock);
6708 +       taskqueue_free(wq->taskq);
6709 +       DWC_FREE(wq);
6710 +}
6711 +
6712 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
6713 +                       char *format, ...)
6714 +{
6715 +       dwc_irqflags_t flags;
6716 +       work_container_t *container;
6717 +       static char name[128];
6718 +       va_list args;
6719 +
6720 +       va_start(args, format);
6721 +       DWC_VSNPRINTF(name, 128, format, args);
6722 +       va_end(args);
6723 +
6724 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6725 +       wq->pending++;
6726 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6727 +       DWC_WAITQ_TRIGGER(wq->waitq);
6728 +
6729 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6730 +       if (!container) {
6731 +               DWC_ERROR("Cannot allocate memory for container");
6732 +               return;
6733 +       }
6734 +
6735 +       container->name = DWC_STRDUP(name);
6736 +       if (!container->name) {
6737 +               DWC_ERROR("Cannot allocate memory for container->name");
6738 +               DWC_FREE(container);
6739 +               return;
6740 +       }
6741 +
6742 +       container->cb = cb;
6743 +       container->data = data;
6744 +       container->wq = wq;
6745 +       container->hz = 0;
6746 +
6747 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6748 +
6749 +       TASK_INIT(&container->task, 0, do_work, container);
6750 +
6751 +#ifdef DEBUG
6752 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6753 +#endif
6754 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6755 +}
6756 +
6757 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
6758 +                               void *data, uint32_t time, char *format, ...)
6759 +{
6760 +       dwc_irqflags_t flags;
6761 +       work_container_t *container;
6762 +       static char name[128];
6763 +       struct timeval tv;
6764 +       va_list args;
6765 +
6766 +       va_start(args, format);
6767 +       DWC_VSNPRINTF(name, 128, format, args);
6768 +       va_end(args);
6769 +
6770 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6771 +       wq->pending++;
6772 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6773 +       DWC_WAITQ_TRIGGER(wq->waitq);
6774 +
6775 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6776 +       if (!container) {
6777 +               DWC_ERROR("Cannot allocate memory for container");
6778 +               return;
6779 +       }
6780 +
6781 +       container->name = DWC_STRDUP(name);
6782 +       if (!container->name) {
6783 +               DWC_ERROR("Cannot allocate memory for container->name");
6784 +               DWC_FREE(container);
6785 +               return;
6786 +       }
6787 +
6788 +       container->cb = cb;
6789 +       container->data = data;
6790 +       container->wq = wq;
6791 +
6792 +       tv.tv_sec = time / 1000;
6793 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6794 +       container->hz = tvtohz(&tv);
6795 +
6796 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6797 +
6798 +       TASK_INIT(&container->task, 0, do_work, container);
6799 +
6800 +#ifdef DEBUG
6801 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6802 +#endif
6803 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6804 +}
6805 +
6806 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
6807 +{
6808 +       return wq->pending;
6809 +}
6810 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6811 new file mode 100644
6812 index 0000000..1668f10
6813 --- /dev/null
6814 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6815 @@ -0,0 +1,1429 @@
6816 +#include <linux/kernel.h>
6817 +#include <linux/init.h>
6818 +#include <linux/module.h>
6819 +#include <linux/kthread.h>
6820 +
6821 +#ifdef DWC_CCLIB
6822 +# include "dwc_cc.h"
6823 +#endif
6824 +
6825 +#ifdef DWC_CRYPTOLIB
6826 +# include "dwc_modpow.h"
6827 +# include "dwc_dh.h"
6828 +# include "dwc_crypto.h"
6829 +#endif
6830 +
6831 +#ifdef DWC_NOTIFYLIB
6832 +# include "dwc_notifier.h"
6833 +#endif
6834 +
6835 +/* OS-Level Implementations */
6836 +
6837 +/* This is the Linux kernel implementation of the DWC platform library. */
6838 +#include <linux/moduleparam.h>
6839 +#include <linux/ctype.h>
6840 +#include <linux/crypto.h>
6841 +#include <linux/delay.h>
6842 +#include <linux/device.h>
6843 +#include <linux/dma-mapping.h>
6844 +#include <linux/cdev.h>
6845 +#include <linux/errno.h>
6846 +#include <linux/interrupt.h>
6847 +#include <linux/jiffies.h>
6848 +#include <linux/list.h>
6849 +#include <linux/pci.h>
6850 +#include <linux/random.h>
6851 +#include <linux/scatterlist.h>
6852 +#include <linux/slab.h>
6853 +#include <linux/stat.h>
6854 +#include <linux/string.h>
6855 +#include <linux/timer.h>
6856 +#include <linux/usb.h>
6857 +
6858 +#include <linux/version.h>
6859 +
6860 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
6861 +# include <linux/usb/gadget.h>
6862 +#else
6863 +# include <linux/usb_gadget.h>
6864 +#endif
6865 +
6866 +#include <asm/io.h>
6867 +#include <asm/page.h>
6868 +#include <asm/uaccess.h>
6869 +#include <asm/unaligned.h>
6870 +
6871 +#include "dwc_os.h"
6872 +#include "dwc_list.h"
6873 +
6874 +
6875 +/* MISC */
6876 +
6877 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
6878 +{
6879 +       return memset(dest, byte, size);
6880 +}
6881 +
6882 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
6883 +{
6884 +       return memcpy(dest, src, size);
6885 +}
6886 +
6887 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
6888 +{
6889 +       return memmove(dest, src, size);
6890 +}
6891 +
6892 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
6893 +{
6894 +       return memcmp(m1, m2, size);
6895 +}
6896 +
6897 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
6898 +{
6899 +       return strncmp(s1, s2, size);
6900 +}
6901 +
6902 +int DWC_STRCMP(void *s1, void *s2)
6903 +{
6904 +       return strcmp(s1, s2);
6905 +}
6906 +
6907 +int DWC_STRLEN(char const *str)
6908 +{
6909 +       return strlen(str);
6910 +}
6911 +
6912 +char *DWC_STRCPY(char *to, char const *from)
6913 +{
6914 +       return strcpy(to, from);
6915 +}
6916 +
6917 +char *DWC_STRDUP(char const *str)
6918 +{
6919 +       int len = DWC_STRLEN(str) + 1;
6920 +       char *new = DWC_ALLOC_ATOMIC(len);
6921 +
6922 +       if (!new) {
6923 +               return NULL;
6924 +       }
6925 +
6926 +       DWC_MEMCPY(new, str, len);
6927 +       return new;
6928 +}
6929 +
6930 +int DWC_ATOI(const char *str, int32_t *value)
6931 +{
6932 +       char *end = NULL;
6933 +
6934 +       *value = simple_strtol(str, &end, 0);
6935 +       if (*end == '\0') {
6936 +               return 0;
6937 +       }
6938 +
6939 +       return -1;
6940 +}
6941 +
6942 +int DWC_ATOUI(const char *str, uint32_t *value)
6943 +{
6944 +       char *end = NULL;
6945 +
6946 +       *value = simple_strtoul(str, &end, 0);
6947 +       if (*end == '\0') {
6948 +               return 0;
6949 +       }
6950 +
6951 +       return -1;
6952 +}
6953 +
6954 +
6955 +#ifdef DWC_UTFLIB
6956 +/* From usbstring.c */
6957 +
6958 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
6959 +{
6960 +       int     count = 0;
6961 +       u8      c;
6962 +       u16     uchar;
6963 +
6964 +       /* this insists on correct encodings, though not minimal ones.
6965 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
6966 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
6967 +        */
6968 +       while (len != 0 && (c = (u8) *s++) != 0) {
6969 +               if (unlikely(c & 0x80)) {
6970 +                       // 2-byte sequence:
6971 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
6972 +                       if ((c & 0xe0) == 0xc0) {
6973 +                               uchar = (c & 0x1f) << 6;
6974 +
6975 +                               c = (u8) *s++;
6976 +                               if ((c & 0xc0) != 0xc0)
6977 +                                       goto fail;
6978 +                               c &= 0x3f;
6979 +                               uchar |= c;
6980 +
6981 +                       // 3-byte sequence (most CJKV characters):
6982 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
6983 +                       } else if ((c & 0xf0) == 0xe0) {
6984 +                               uchar = (c & 0x0f) << 12;
6985 +
6986 +                               c = (u8) *s++;
6987 +                               if ((c & 0xc0) != 0xc0)
6988 +                                       goto fail;
6989 +                               c &= 0x3f;
6990 +                               uchar |= c << 6;
6991 +
6992 +                               c = (u8) *s++;
6993 +                               if ((c & 0xc0) != 0xc0)
6994 +                                       goto fail;
6995 +                               c &= 0x3f;
6996 +                               uchar |= c;
6997 +
6998 +                               /* no bogus surrogates */
6999 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
7000 +                                       goto fail;
7001 +
7002 +                       // 4-byte sequence (surrogate pairs, currently rare):
7003 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
7004 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
7005 +                       // (uuuuu = wwww + 1)
7006 +                       // FIXME accept the surrogate code points (only)
7007 +                       } else
7008 +                               goto fail;
7009 +               } else
7010 +                       uchar = c;
7011 +               put_unaligned (cpu_to_le16 (uchar), cp++);
7012 +               count++;
7013 +               len--;
7014 +       }
7015 +       return count;
7016 +fail:
7017 +       return -1;
7018 +}
7019 +#endif /* DWC_UTFLIB */
7020 +
7021 +
7022 +/* dwc_debug.h */
7023 +
7024 +dwc_bool_t DWC_IN_IRQ(void)
7025 +{
7026 +       return in_irq();
7027 +}
7028 +
7029 +dwc_bool_t DWC_IN_BH(void)
7030 +{
7031 +       return in_softirq();
7032 +}
7033 +
7034 +void DWC_VPRINTF(char *format, va_list args)
7035 +{
7036 +       vprintk(format, args);
7037 +}
7038 +
7039 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
7040 +{
7041 +       return vsnprintf(str, size, format, args);
7042 +}
7043 +
7044 +void DWC_PRINTF(char *format, ...)
7045 +{
7046 +       va_list args;
7047 +
7048 +       va_start(args, format);
7049 +       DWC_VPRINTF(format, args);
7050 +       va_end(args);
7051 +}
7052 +
7053 +int DWC_SPRINTF(char *buffer, char *format, ...)
7054 +{
7055 +       int retval;
7056 +       va_list args;
7057 +
7058 +       va_start(args, format);
7059 +       retval = vsprintf(buffer, format, args);
7060 +       va_end(args);
7061 +       return retval;
7062 +}
7063 +
7064 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
7065 +{
7066 +       int retval;
7067 +       va_list args;
7068 +
7069 +       va_start(args, format);
7070 +       retval = vsnprintf(buffer, size, format, args);
7071 +       va_end(args);
7072 +       return retval;
7073 +}
7074 +
7075 +void __DWC_WARN(char *format, ...)
7076 +{
7077 +       va_list args;
7078 +
7079 +       va_start(args, format);
7080 +       DWC_PRINTF(KERN_WARNING);
7081 +       DWC_VPRINTF(format, args);
7082 +       va_end(args);
7083 +}
7084 +
7085 +void __DWC_ERROR(char *format, ...)
7086 +{
7087 +       va_list args;
7088 +
7089 +       va_start(args, format);
7090 +       DWC_PRINTF(KERN_ERR);
7091 +       DWC_VPRINTF(format, args);
7092 +       va_end(args);
7093 +}
7094 +
7095 +void DWC_EXCEPTION(char *format, ...)
7096 +{
7097 +       va_list args;
7098 +
7099 +       va_start(args, format);
7100 +       DWC_PRINTF(KERN_ERR);
7101 +       DWC_VPRINTF(format, args);
7102 +       va_end(args);
7103 +       BUG_ON(1);
7104 +}
7105 +
7106 +#ifdef DEBUG
7107 +void __DWC_DEBUG(char *format, ...)
7108 +{
7109 +       va_list args;
7110 +
7111 +       va_start(args, format);
7112 +       DWC_PRINTF(KERN_DEBUG);
7113 +       DWC_VPRINTF(format, args);
7114 +       va_end(args);
7115 +}
7116 +#endif
7117 +
7118 +
7119 +/* dwc_mem.h */
7120 +
7121 +#if 0
7122 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
7123 +                               uint32_t align,
7124 +                               uint32_t alloc)
7125 +{
7126 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
7127 +                                               size, align, alloc);
7128 +       return (dwc_pool_t *)pool;
7129 +}
7130 +
7131 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
7132 +{
7133 +       dma_pool_destroy((struct dma_pool *)pool);
7134 +}
7135 +
7136 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7137 +{
7138 +       return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
7139 +}
7140 +
7141 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7142 +{
7143 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
7144 +       memset(..);
7145 +}
7146 +
7147 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
7148 +{
7149 +       dma_pool_free(pool, vaddr, daddr);
7150 +}
7151 +#endif
7152 +
7153 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7154 +{
7155 +#ifdef xxCOSIM /* Only works for 32-bit cosim */
7156 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);
7157 +#else
7158 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);
7159 +#endif
7160 +       if (!buf) {
7161 +               return NULL;
7162 +       }
7163 +
7164 +       memset(buf, 0, (size_t)size);
7165 +       return buf;
7166 +}
7167 +
7168 +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7169 +{
7170 +       void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
7171 +       if (!buf) {
7172 +               return NULL;
7173 +       }
7174 +       memset(buf, 0, (size_t)size);
7175 +       return buf;
7176 +}
7177 +
7178 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
7179 +{
7180 +       dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);
7181 +}
7182 +
7183 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
7184 +{
7185 +       return kzalloc(size, GFP_KERNEL);
7186 +}
7187 +
7188 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
7189 +{
7190 +       return kzalloc(size, GFP_ATOMIC);
7191 +}
7192 +
7193 +void __DWC_FREE(void *mem_ctx, void *addr)
7194 +{
7195 +       kfree(addr);
7196 +}
7197 +
7198 +
7199 +#ifdef DWC_CRYPTOLIB
7200 +/* dwc_crypto.h */
7201 +
7202 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
7203 +{
7204 +       get_random_bytes(buffer, length);
7205 +}
7206 +
7207 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
7208 +{
7209 +       struct crypto_blkcipher *tfm;
7210 +       struct blkcipher_desc desc;
7211 +       struct scatterlist sgd;
7212 +       struct scatterlist sgs;
7213 +
7214 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
7215 +       if (tfm == NULL) {
7216 +               printk("failed to load transform for aes CBC\n");
7217 +               return -1;
7218 +       }
7219 +
7220 +       crypto_blkcipher_setkey(tfm, key, keylen);
7221 +       crypto_blkcipher_set_iv(tfm, iv, 16);
7222 +
7223 +       sg_init_one(&sgd, out, messagelen);
7224 +       sg_init_one(&sgs, message, messagelen);
7225 +
7226 +       desc.tfm = tfm;
7227 +       desc.flags = 0;
7228 +
7229 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
7230 +               crypto_free_blkcipher(tfm);
7231 +               DWC_ERROR("AES CBC encryption failed");
7232 +               return -1;
7233 +       }
7234 +
7235 +       crypto_free_blkcipher(tfm);
7236 +       return 0;
7237 +}
7238 +
7239 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
7240 +{
7241 +       struct crypto_hash *tfm;
7242 +       struct hash_desc desc;
7243 +       struct scatterlist sg;
7244 +
7245 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
7246 +       if (IS_ERR(tfm)) {
7247 +               DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
7248 +               return 0;
7249 +       }
7250 +       desc.tfm = tfm;
7251 +       desc.flags = 0;
7252 +
7253 +       sg_init_one(&sg, message, len);
7254 +       crypto_hash_digest(&desc, &sg, len, out);
7255 +       crypto_free_hash(tfm);
7256 +
7257 +       return 1;
7258 +}
7259 +
7260 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
7261 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
7262 +{
7263 +       struct crypto_hash *tfm;
7264 +       struct hash_desc desc;
7265 +       struct scatterlist sg;
7266 +
7267 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
7268 +       if (IS_ERR(tfm)) {
7269 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
7270 +               return 0;
7271 +       }
7272 +       desc.tfm = tfm;
7273 +       desc.flags = 0;
7274 +
7275 +       sg_init_one(&sg, message, messagelen);
7276 +       crypto_hash_setkey(tfm, key, keylen);
7277 +       crypto_hash_digest(&desc, &sg, messagelen, out);
7278 +       crypto_free_hash(tfm);
7279 +
7280 +       return 1;
7281 +}
7282 +#endif /* DWC_CRYPTOLIB */
7283 +
7284 +
7285 +/* Byte Ordering Conversions */
7286 +
7287 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
7288 +{
7289 +#ifdef __LITTLE_ENDIAN
7290 +       return *p;
7291 +#else
7292 +       uint8_t *u_p = (uint8_t *)p;
7293 +
7294 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7295 +#endif
7296 +}
7297 +
7298 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
7299 +{
7300 +#ifdef __BIG_ENDIAN
7301 +       return *p;
7302 +#else
7303 +       uint8_t *u_p = (uint8_t *)p;
7304 +
7305 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7306 +#endif
7307 +}
7308 +
7309 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
7310 +{
7311 +#ifdef __LITTLE_ENDIAN
7312 +       return *p;
7313 +#else
7314 +       uint8_t *u_p = (uint8_t *)p;
7315 +
7316 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7317 +#endif
7318 +}
7319 +
7320 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
7321 +{
7322 +#ifdef __BIG_ENDIAN
7323 +       return *p;
7324 +#else
7325 +       uint8_t *u_p = (uint8_t *)p;
7326 +
7327 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7328 +#endif
7329 +}
7330 +
7331 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
7332 +{
7333 +#ifdef __LITTLE_ENDIAN
7334 +       return *p;
7335 +#else
7336 +       uint8_t *u_p = (uint8_t *)p;
7337 +       return (u_p[1] | (u_p[0] << 8));
7338 +#endif
7339 +}
7340 +
7341 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
7342 +{
7343 +#ifdef __BIG_ENDIAN
7344 +       return *p;
7345 +#else
7346 +       uint8_t *u_p = (uint8_t *)p;
7347 +       return (u_p[1] | (u_p[0] << 8));
7348 +#endif
7349 +}
7350 +
7351 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
7352 +{
7353 +#ifdef __LITTLE_ENDIAN
7354 +       return *p;
7355 +#else
7356 +       uint8_t *u_p = (uint8_t *)p;
7357 +       return (u_p[1] | (u_p[0] << 8));
7358 +#endif
7359 +}
7360 +
7361 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
7362 +{
7363 +#ifdef __BIG_ENDIAN
7364 +       return *p;
7365 +#else
7366 +       uint8_t *u_p = (uint8_t *)p;
7367 +       return (u_p[1] | (u_p[0] << 8));
7368 +#endif
7369 +}
7370 +
7371 +
7372 +/* Registers */
7373 +
7374 +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
7375 +{
7376 +       return readl(reg);
7377 +}
7378 +
7379 +#if 0
7380 +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
7381 +{
7382 +}
7383 +#endif
7384 +
7385 +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
7386 +{
7387 +       writel(value, reg);
7388 +}
7389 +
7390 +#if 0
7391 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
7392 +{
7393 +}
7394 +#endif
7395 +
7396 +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
7397 +{
7398 +       writel((readl(reg) & ~clear_mask) | set_mask, reg);
7399 +}
7400 +
7401 +#if 0
7402 +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)
7403 +{
7404 +}
7405 +#endif
7406 +
7407 +
7408 +/* Locking */
7409 +
7410 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
7411 +{
7412 +       spinlock_t *sl = (spinlock_t *)1;
7413 +
7414 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7415 +       sl = DWC_ALLOC(sizeof(*sl));
7416 +       if (!sl) {
7417 +               DWC_ERROR("Cannot allocate memory for spinlock\n");
7418 +               return NULL;
7419 +       }
7420 +
7421 +       spin_lock_init(sl);
7422 +#endif
7423 +       return (dwc_spinlock_t *)sl;
7424 +}
7425 +
7426 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
7427 +{
7428 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7429 +       DWC_FREE(lock);
7430 +#endif
7431 +}
7432 +
7433 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
7434 +{
7435 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7436 +       spin_lock((spinlock_t *)lock);
7437 +#endif
7438 +}
7439 +
7440 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
7441 +{
7442 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7443 +       spin_unlock((spinlock_t *)lock);
7444 +#endif
7445 +}
7446 +
7447 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
7448 +{
7449 +       dwc_irqflags_t f;
7450 +
7451 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7452 +       spin_lock_irqsave((spinlock_t *)lock, f);
7453 +#else
7454 +       local_irq_save(f);
7455 +#endif
7456 +       *flags = f;
7457 +}
7458 +
7459 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
7460 +{
7461 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7462 +       spin_unlock_irqrestore((spinlock_t *)lock, flags);
7463 +#else
7464 +       local_irq_restore(flags);
7465 +#endif
7466 +}
7467 +
7468 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
7469 +{
7470 +       struct mutex *m;
7471 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));
7472 +
7473 +       if (!mutex) {
7474 +               DWC_ERROR("Cannot allocate memory for mutex\n");
7475 +               return NULL;
7476 +       }
7477 +
7478 +       m = (struct mutex *)mutex;
7479 +       mutex_init(m);
7480 +       return mutex;
7481 +}
7482 +
7483 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
7484 +#else
7485 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
7486 +{
7487 +       mutex_destroy((struct mutex *)mutex);
7488 +       DWC_FREE(mutex);
7489 +}
7490 +#endif
7491 +
7492 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
7493 +{
7494 +       struct mutex *m = (struct mutex *)mutex;
7495 +       mutex_lock(m);
7496 +}
7497 +
7498 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
7499 +{
7500 +       struct mutex *m = (struct mutex *)mutex;
7501 +       return mutex_trylock(m);
7502 +}
7503 +
7504 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
7505 +{
7506 +       struct mutex *m = (struct mutex *)mutex;
7507 +       mutex_unlock(m);
7508 +}
7509 +
7510 +
7511 +/* Timing */
7512 +
7513 +void DWC_UDELAY(uint32_t usecs)
7514 +{
7515 +       udelay(usecs);
7516 +}
7517 +
7518 +void DWC_MDELAY(uint32_t msecs)
7519 +{
7520 +       mdelay(msecs);
7521 +}
7522 +
7523 +void DWC_MSLEEP(uint32_t msecs)
7524 +{
7525 +       msleep(msecs);
7526 +}
7527 +
7528 +uint32_t DWC_TIME(void)
7529 +{
7530 +       return jiffies_to_msecs(jiffies);
7531 +}
7532 +
7533 +
7534 +/* Timers */
7535 +
7536 +struct dwc_timer {
7537 +       struct timer_list *t;
7538 +       char *name;
7539 +       dwc_timer_callback_t cb;
7540 +       void *data;
7541 +       uint8_t scheduled;
7542 +       dwc_spinlock_t *lock;
7543 +};
7544 +
7545 +static void timer_callback(unsigned long data)
7546 +{
7547 +       dwc_timer_t *timer = (dwc_timer_t *)data;
7548 +       dwc_irqflags_t flags;
7549 +
7550 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7551 +       timer->scheduled = 0;
7552 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7553 +       DWC_DEBUGC("Timer %s callback", timer->name);
7554 +       timer->cb(timer->data);
7555 +}
7556 +
7557 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
7558 +{
7559 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
7560 +
7561 +       if (!t) {
7562 +               DWC_ERROR("Cannot allocate memory for timer");
7563 +               return NULL;
7564 +       }
7565 +
7566 +       t->t = DWC_ALLOC(sizeof(*t->t));
7567 +       if (!t->t) {
7568 +               DWC_ERROR("Cannot allocate memory for timer->t");
7569 +               goto no_timer;
7570 +       }
7571 +
7572 +       t->name = DWC_STRDUP(name);
7573 +       if (!t->name) {
7574 +               DWC_ERROR("Cannot allocate memory for timer->name");
7575 +               goto no_name;
7576 +       }
7577 +
7578 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
7579 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(t->lock);
7580 +#else
7581 +       t->lock = DWC_SPINLOCK_ALLOC();
7582 +#endif
7583 +       if (!t->lock) {
7584 +               DWC_ERROR("Cannot allocate memory for lock");
7585 +               goto no_lock;
7586 +       }
7587 +
7588 +       t->scheduled = 0;
7589 +       t->t->base = &boot_tvec_bases;
7590 +       t->t->expires = jiffies;
7591 +       setup_timer(t->t, timer_callback, (unsigned long)t);
7592 +
7593 +       t->cb = cb;
7594 +       t->data = data;
7595 +
7596 +       return t;
7597 +
7598 + no_lock:
7599 +       DWC_FREE(t->name);
7600 + no_name:
7601 +       DWC_FREE(t->t);
7602 + no_timer:
7603 +       DWC_FREE(t);
7604 +       return NULL;
7605 +}
7606 +
7607 +void DWC_TIMER_FREE(dwc_timer_t *timer)
7608 +{
7609 +       dwc_irqflags_t flags;
7610 +
7611 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7612 +
7613 +       if (timer->scheduled) {
7614 +               del_timer(timer->t);
7615 +               timer->scheduled = 0;
7616 +       }
7617 +
7618 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7619 +       DWC_SPINLOCK_FREE(timer->lock);
7620 +       DWC_FREE(timer->t);
7621 +       DWC_FREE(timer->name);
7622 +       DWC_FREE(timer);
7623 +}
7624 +
7625 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
7626 +{
7627 +       dwc_irqflags_t flags;
7628 +
7629 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7630 +
7631 +       if (!timer->scheduled) {
7632 +               timer->scheduled = 1;
7633 +               DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);
7634 +               timer->t->expires = jiffies + msecs_to_jiffies(time);
7635 +               add_timer(timer->t);
7636 +       } else {
7637 +               DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);
7638 +               mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
7639 +       }
7640 +
7641 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7642 +}
7643 +
7644 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
7645 +{
7646 +       del_timer(timer->t);
7647 +}
7648 +
7649 +
7650 +/* Wait Queues */
7651 +
7652 +struct dwc_waitq {
7653 +       wait_queue_head_t queue;
7654 +       int abort;
7655 +};
7656 +
7657 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
7658 +{
7659 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
7660 +
7661 +       if (!wq) {
7662 +               DWC_ERROR("Cannot allocate memory for waitqueue\n");
7663 +               return NULL;
7664 +       }
7665 +
7666 +       init_waitqueue_head(&wq->queue);
7667 +       wq->abort = 0;
7668 +       return wq;
7669 +}
7670 +
7671 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
7672 +{
7673 +       DWC_FREE(wq);
7674 +}
7675 +
7676 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
7677 +{
7678 +       int result = wait_event_interruptible(wq->queue,
7679 +                                             cond(data) || wq->abort);
7680 +       if (result == -ERESTARTSYS) {
7681 +               wq->abort = 0;
7682 +               return -DWC_E_RESTART;
7683 +       }
7684 +
7685 +       if (wq->abort == 1) {
7686 +               wq->abort = 0;
7687 +               return -DWC_E_ABORT;
7688 +       }
7689 +
7690 +       wq->abort = 0;
7691 +
7692 +       if (result == 0) {
7693 +               return 0;
7694 +       }
7695 +
7696 +       return -DWC_E_UNKNOWN;
7697 +}
7698 +
7699 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
7700 +                              void *data, int32_t msecs)
7701 +{
7702 +       int32_t tmsecs;
7703 +       int result = wait_event_interruptible_timeout(wq->queue,
7704 +                                                     cond(data) || wq->abort,
7705 +                                                     msecs_to_jiffies(msecs));
7706 +       if (result == -ERESTARTSYS) {
7707 +               wq->abort = 0;
7708 +               return -DWC_E_RESTART;
7709 +       }
7710 +
7711 +       if (wq->abort == 1) {
7712 +               wq->abort = 0;
7713 +               return -DWC_E_ABORT;
7714 +       }
7715 +
7716 +       wq->abort = 0;
7717 +
7718 +       if (result > 0) {
7719 +               tmsecs = jiffies_to_msecs(result);
7720 +               if (!tmsecs) {
7721 +                       return 1;
7722 +               }
7723 +
7724 +               return tmsecs;
7725 +       }
7726 +
7727 +       if (result == 0) {
7728 +               return -DWC_E_TIMEOUT;
7729 +       }
7730 +
7731 +       return -DWC_E_UNKNOWN;
7732 +}
7733 +
7734 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
7735 +{
7736 +       wq->abort = 0;
7737 +       wake_up_interruptible(&wq->queue);
7738 +}
7739 +
7740 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
7741 +{
7742 +       wq->abort = 1;
7743 +       wake_up_interruptible(&wq->queue);
7744 +}
7745 +
7746 +
7747 +/* Threading */
7748 +
7749 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
7750 +{
7751 +       struct task_struct *thread = kthread_run(func, data, name);
7752 +
7753 +       if (thread == ERR_PTR(-ENOMEM)) {
7754 +               return NULL;
7755 +       }
7756 +
7757 +       return (dwc_thread_t *)thread;
7758 +}
7759 +
7760 +int DWC_THREAD_STOP(dwc_thread_t *thread)
7761 +{
7762 +       return kthread_stop((struct task_struct *)thread);
7763 +}
7764 +
7765 +dwc_bool_t DWC_THREAD_SHOULD_STOP(void)
7766 +{
7767 +       return kthread_should_stop();
7768 +}
7769 +
7770 +
7771 +/* tasklets
7772 + - run in interrupt context (cannot sleep)
7773 + - each tasklet runs on a single CPU
7774 + - different tasklets can be running simultaneously on different CPUs
7775 + */
7776 +struct dwc_tasklet {
7777 +       struct tasklet_struct t;
7778 +       dwc_tasklet_callback_t cb;
7779 +       void *data;
7780 +};
7781 +
7782 +static void tasklet_callback(unsigned long data)
7783 +{
7784 +       dwc_tasklet_t *t = (dwc_tasklet_t *)data;
7785 +       t->cb(t->data);
7786 +}
7787 +
7788 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
7789 +{
7790 +       dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
7791 +
7792 +       if (t) {
7793 +               t->cb = cb;
7794 +               t->data = data;
7795 +               tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
7796 +       } else {
7797 +               DWC_ERROR("Cannot allocate memory for tasklet\n");
7798 +       }
7799 +
7800 +       return t;
7801 +}
7802 +
7803 +void DWC_TASK_FREE(dwc_tasklet_t *task)
7804 +{
7805 +       DWC_FREE(task);
7806 +}
7807 +
7808 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
7809 +{
7810 +       tasklet_schedule(&task->t);
7811 +}
7812 +
7813 +
7814 +/* workqueues
7815 + - run in process context (can sleep)
7816 + */
7817 +typedef struct work_container {
7818 +       dwc_work_callback_t cb;
7819 +       void *data;
7820 +       dwc_workq_t *wq;
7821 +       char *name;
7822 +
7823 +#ifdef DEBUG
7824 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
7825 +#endif
7826 +       struct delayed_work work;
7827 +} work_container_t;
7828 +
7829 +#ifdef DEBUG
7830 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
7831 +#endif
7832 +
7833 +struct dwc_workq {
7834 +       struct workqueue_struct *wq;
7835 +       dwc_spinlock_t *lock;
7836 +       dwc_waitq_t *waitq;
7837 +       int pending;
7838 +
7839 +#ifdef DEBUG
7840 +       struct work_container_queue entries;
7841 +#endif
7842 +};
7843 +
7844 +static void do_work(struct work_struct *work)
7845 +{
7846 +       dwc_irqflags_t flags;
7847 +       struct delayed_work *dw = container_of(work, struct delayed_work, work);
7848 +       work_container_t *container = container_of(dw, struct work_container, work);
7849 +       dwc_workq_t *wq = container->wq;
7850 +
7851 +       container->cb(container->data);
7852 +
7853 +#ifdef DEBUG
7854 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
7855 +#endif
7856 +       DWC_DEBUGC("Work done: %s, container=%p", container->name, container);
7857 +       if (container->name) {
7858 +               DWC_FREE(container->name);
7859 +       }
7860 +       DWC_FREE(container);
7861 +
7862 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7863 +       wq->pending--;
7864 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7865 +       DWC_WAITQ_TRIGGER(wq->waitq);
7866 +}
7867 +
7868 +static int work_done(void *data)
7869 +{
7870 +       dwc_workq_t *workq = (dwc_workq_t *)data;
7871 +       return workq->pending == 0;
7872 +}
7873 +
7874 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
7875 +{
7876 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
7877 +}
7878 +
7879 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
7880 +{
7881 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
7882 +
7883 +       if (!wq) {
7884 +               return NULL;
7885 +       }
7886 +
7887 +       wq->wq = create_singlethread_workqueue(name);
7888 +       if (!wq->wq) {
7889 +               goto no_wq;
7890 +       }
7891 +
7892 +       wq->pending = 0;
7893 +
7894 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
7895 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(wq->lock);
7896 +#else
7897 +       wq->lock = DWC_SPINLOCK_ALLOC();
7898 +#endif
7899 +       if (!wq->lock) {
7900 +               goto no_lock;
7901 +       }
7902 +
7903 +       wq->waitq = DWC_WAITQ_ALLOC();
7904 +       if (!wq->waitq) {
7905 +               goto no_waitq;
7906 +       }
7907 +
7908 +#ifdef DEBUG
7909 +       DWC_CIRCLEQ_INIT(&wq->entries);
7910 +#endif
7911 +       return wq;
7912 +
7913 + no_waitq:
7914 +       DWC_SPINLOCK_FREE(wq->lock);
7915 + no_lock:
7916 +       destroy_workqueue(wq->wq);
7917 + no_wq:
7918 +       DWC_FREE(wq);
7919 +
7920 +       return NULL;
7921 +}
7922 +
7923 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
7924 +{
7925 +#ifdef DEBUG
7926 +       if (wq->pending != 0) {
7927 +               struct work_container *wc;
7928 +               DWC_ERROR("Destroying work queue with pending work");
7929 +               DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
7930 +                       DWC_ERROR("Work %s still pending", wc->name);
7931 +               }
7932 +       }
7933 +#endif
7934 +       destroy_workqueue(wq->wq);
7935 +       DWC_SPINLOCK_FREE(wq->lock);
7936 +       DWC_WAITQ_FREE(wq->waitq);
7937 +       DWC_FREE(wq);
7938 +}
7939 +
7940 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
7941 +                       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_WORK(&container->work.work, do_work);
7975 +
7976 +#ifdef DEBUG
7977 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
7978 +#endif
7979 +       queue_work(wq->wq, &container->work.work);
7980 +}
7981 +
7982 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
7983 +                               void *data, uint32_t time, char *format, ...)
7984 +{
7985 +       dwc_irqflags_t flags;
7986 +       work_container_t *container;
7987 +       static char name[128];
7988 +       va_list args;
7989 +
7990 +       va_start(args, format);
7991 +       DWC_VSNPRINTF(name, 128, format, args);
7992 +       va_end(args);
7993 +
7994 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7995 +       wq->pending++;
7996 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7997 +       DWC_WAITQ_TRIGGER(wq->waitq);
7998 +
7999 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
8000 +       if (!container) {
8001 +               DWC_ERROR("Cannot allocate memory for container\n");
8002 +               return;
8003 +       }
8004 +
8005 +       container->name = DWC_STRDUP(name);
8006 +       if (!container->name) {
8007 +               DWC_ERROR("Cannot allocate memory for container->name\n");
8008 +               DWC_FREE(container);
8009 +               return;
8010 +       }
8011 +
8012 +       container->cb = cb;
8013 +       container->data = data;
8014 +       container->wq = wq;
8015 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
8016 +       INIT_DELAYED_WORK(&container->work, do_work);
8017 +
8018 +#ifdef DEBUG
8019 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
8020 +#endif
8021 +       queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
8022 +}
8023 +
8024 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
8025 +{
8026 +       return wq->pending;
8027 +}
8028 +
8029 +
8030 +#ifdef DWC_LIBMODULE
8031 +
8032 +#ifdef DWC_CCLIB
8033 +/* CC */
8034 +EXPORT_SYMBOL(dwc_cc_if_alloc);
8035 +EXPORT_SYMBOL(dwc_cc_if_free);
8036 +EXPORT_SYMBOL(dwc_cc_clear);
8037 +EXPORT_SYMBOL(dwc_cc_add);
8038 +EXPORT_SYMBOL(dwc_cc_remove);
8039 +EXPORT_SYMBOL(dwc_cc_change);
8040 +EXPORT_SYMBOL(dwc_cc_data_for_save);
8041 +EXPORT_SYMBOL(dwc_cc_restore_from_data);
8042 +EXPORT_SYMBOL(dwc_cc_match_chid);
8043 +EXPORT_SYMBOL(dwc_cc_match_cdid);
8044 +EXPORT_SYMBOL(dwc_cc_ck);
8045 +EXPORT_SYMBOL(dwc_cc_chid);
8046 +EXPORT_SYMBOL(dwc_cc_cdid);
8047 +EXPORT_SYMBOL(dwc_cc_name);
8048 +#endif /* DWC_CCLIB */
8049 +
8050 +#ifdef DWC_CRYPTOLIB
8051 +# ifndef CONFIG_MACH_IPMATE
8052 +/* Modpow */
8053 +EXPORT_SYMBOL(dwc_modpow);
8054 +
8055 +/* DH */
8056 +EXPORT_SYMBOL(dwc_dh_modpow);
8057 +EXPORT_SYMBOL(dwc_dh_derive_keys);
8058 +EXPORT_SYMBOL(dwc_dh_pk);
8059 +# endif        /* CONFIG_MACH_IPMATE */
8060 +
8061 +/* Crypto */
8062 +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
8063 +EXPORT_SYMBOL(dwc_wusb_cmf);
8064 +EXPORT_SYMBOL(dwc_wusb_prf);
8065 +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
8066 +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
8067 +EXPORT_SYMBOL(dwc_wusb_gen_key);
8068 +EXPORT_SYMBOL(dwc_wusb_gen_mic);
8069 +#endif /* DWC_CRYPTOLIB */
8070 +
8071 +/* Notification */
8072 +#ifdef DWC_NOTIFYLIB
8073 +EXPORT_SYMBOL(dwc_alloc_notification_manager);
8074 +EXPORT_SYMBOL(dwc_free_notification_manager);
8075 +EXPORT_SYMBOL(dwc_register_notifier);
8076 +EXPORT_SYMBOL(dwc_unregister_notifier);
8077 +EXPORT_SYMBOL(dwc_add_observer);
8078 +EXPORT_SYMBOL(dwc_remove_observer);
8079 +EXPORT_SYMBOL(dwc_notify);
8080 +#endif
8081 +
8082 +/* Memory Debugging Routines */
8083 +#ifdef DWC_DEBUG_MEMORY
8084 +EXPORT_SYMBOL(dwc_alloc_debug);
8085 +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
8086 +EXPORT_SYMBOL(dwc_free_debug);
8087 +EXPORT_SYMBOL(dwc_dma_alloc_debug);
8088 +EXPORT_SYMBOL(dwc_dma_free_debug);
8089 +#endif
8090 +
8091 +EXPORT_SYMBOL(DWC_MEMSET);
8092 +EXPORT_SYMBOL(DWC_MEMCPY);
8093 +EXPORT_SYMBOL(DWC_MEMMOVE);
8094 +EXPORT_SYMBOL(DWC_MEMCMP);
8095 +EXPORT_SYMBOL(DWC_STRNCMP);
8096 +EXPORT_SYMBOL(DWC_STRCMP);
8097 +EXPORT_SYMBOL(DWC_STRLEN);
8098 +EXPORT_SYMBOL(DWC_STRCPY);
8099 +EXPORT_SYMBOL(DWC_STRDUP);
8100 +EXPORT_SYMBOL(DWC_ATOI);
8101 +EXPORT_SYMBOL(DWC_ATOUI);
8102 +
8103 +#ifdef DWC_UTFLIB
8104 +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
8105 +#endif /* DWC_UTFLIB */
8106 +
8107 +EXPORT_SYMBOL(DWC_IN_IRQ);
8108 +EXPORT_SYMBOL(DWC_IN_BH);
8109 +EXPORT_SYMBOL(DWC_VPRINTF);
8110 +EXPORT_SYMBOL(DWC_VSNPRINTF);
8111 +EXPORT_SYMBOL(DWC_PRINTF);
8112 +EXPORT_SYMBOL(DWC_SPRINTF);
8113 +EXPORT_SYMBOL(DWC_SNPRINTF);
8114 +EXPORT_SYMBOL(__DWC_WARN);
8115 +EXPORT_SYMBOL(__DWC_ERROR);
8116 +EXPORT_SYMBOL(DWC_EXCEPTION);
8117 +
8118 +#ifdef DEBUG
8119 +EXPORT_SYMBOL(__DWC_DEBUG);
8120 +#endif
8121 +
8122 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
8123 +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
8124 +EXPORT_SYMBOL(__DWC_DMA_FREE);
8125 +EXPORT_SYMBOL(__DWC_ALLOC);
8126 +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
8127 +EXPORT_SYMBOL(__DWC_FREE);
8128 +
8129 +#ifdef DWC_CRYPTOLIB
8130 +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
8131 +EXPORT_SYMBOL(DWC_AES_CBC);
8132 +EXPORT_SYMBOL(DWC_SHA256);
8133 +EXPORT_SYMBOL(DWC_HMAC_SHA256);
8134 +#endif
8135 +
8136 +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
8137 +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
8138 +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
8139 +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
8140 +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
8141 +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
8142 +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
8143 +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
8144 +EXPORT_SYMBOL(DWC_READ_REG32);
8145 +EXPORT_SYMBOL(DWC_WRITE_REG32);
8146 +EXPORT_SYMBOL(DWC_MODIFY_REG32);
8147 +
8148 +#if 0
8149 +EXPORT_SYMBOL(DWC_READ_REG64);
8150 +EXPORT_SYMBOL(DWC_WRITE_REG64);
8151 +EXPORT_SYMBOL(DWC_MODIFY_REG64);
8152 +#endif
8153 +
8154 +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
8155 +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
8156 +EXPORT_SYMBOL(DWC_SPINLOCK);
8157 +EXPORT_SYMBOL(DWC_SPINUNLOCK);
8158 +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
8159 +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
8160 +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
8161 +
8162 +#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))
8163 +EXPORT_SYMBOL(DWC_MUTEX_FREE);
8164 +#endif
8165 +
8166 +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
8167 +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
8168 +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
8169 +EXPORT_SYMBOL(DWC_UDELAY);
8170 +EXPORT_SYMBOL(DWC_MDELAY);
8171 +EXPORT_SYMBOL(DWC_MSLEEP);
8172 +EXPORT_SYMBOL(DWC_TIME);
8173 +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
8174 +EXPORT_SYMBOL(DWC_TIMER_FREE);
8175 +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
8176 +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
8177 +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
8178 +EXPORT_SYMBOL(DWC_WAITQ_FREE);
8179 +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
8180 +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
8181 +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
8182 +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
8183 +EXPORT_SYMBOL(DWC_THREAD_RUN);
8184 +EXPORT_SYMBOL(DWC_THREAD_STOP);
8185 +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
8186 +EXPORT_SYMBOL(DWC_TASK_ALLOC);
8187 +EXPORT_SYMBOL(DWC_TASK_FREE);
8188 +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
8189 +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
8190 +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
8191 +EXPORT_SYMBOL(DWC_WORKQ_FREE);
8192 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
8193 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
8194 +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
8195 +
8196 +static int dwc_common_port_init_module(void)
8197 +{
8198 +       int result = 0;
8199 +
8200 +       printk(KERN_DEBUG "Module dwc_common_port init\n" );
8201 +
8202 +#ifdef DWC_DEBUG_MEMORY
8203 +       result = dwc_memory_debug_start(NULL);
8204 +       if (result) {
8205 +               printk(KERN_ERR
8206 +                      "dwc_memory_debug_start() failed with error %d\n",
8207 +                      result);
8208 +               return result;
8209 +       }
8210 +#endif
8211 +
8212 +#ifdef DWC_NOTIFYLIB
8213 +       result = dwc_alloc_notification_manager(NULL, NULL);
8214 +       if (result) {
8215 +               printk(KERN_ERR
8216 +                      "dwc_alloc_notification_manager() failed with error %d\n",
8217 +                      result);
8218 +               return result;
8219 +       }
8220 +#endif
8221 +       return result;
8222 +}
8223 +
8224 +static void dwc_common_port_exit_module(void)
8225 +{
8226 +       printk(KERN_DEBUG "Module dwc_common_port exit\n" );
8227 +
8228 +#ifdef DWC_NOTIFYLIB
8229 +       dwc_free_notification_manager();
8230 +#endif
8231 +
8232 +#ifdef DWC_DEBUG_MEMORY
8233 +       dwc_memory_debug_stop();
8234 +#endif
8235 +}
8236 +
8237 +module_init(dwc_common_port_init_module);
8238 +module_exit(dwc_common_port_exit_module);
8239 +
8240 +MODULE_DESCRIPTION("DWC Common Library - Portable version");
8241 +MODULE_AUTHOR("Synopsys Inc.");
8242 +MODULE_LICENSE ("GPL");
8243 +
8244 +#endif /* DWC_LIBMODULE */
8245 diff --git a/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
8246 new file mode 100644
8247 index 0000000..49b07e1
8248 --- /dev/null
8249 +++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
8250 @@ -0,0 +1,1275 @@
8251 +#include "dwc_os.h"
8252 +#include "dwc_list.h"
8253 +
8254 +#ifdef DWC_CCLIB
8255 +# include "dwc_cc.h"
8256 +#endif
8257 +
8258 +#ifdef DWC_CRYPTOLIB
8259 +# include "dwc_modpow.h"
8260 +# include "dwc_dh.h"
8261 +# include "dwc_crypto.h"
8262 +#endif
8263 +
8264 +#ifdef DWC_NOTIFYLIB
8265 +# include "dwc_notifier.h"
8266 +#endif
8267 +
8268 +/* OS-Level Implementations */
8269 +
8270 +/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */
8271 +
8272 +
8273 +/* MISC */
8274 +
8275 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
8276 +{
8277 +       return memset(dest, byte, size);
8278 +}
8279 +
8280 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
8281 +{
8282 +       return memcpy(dest, src, size);
8283 +}
8284 +
8285 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
8286 +{
8287 +       bcopy(src, dest, size);
8288 +       return dest;
8289 +}
8290 +
8291 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
8292 +{
8293 +       return memcmp(m1, m2, size);
8294 +}
8295 +
8296 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
8297 +{
8298 +       return strncmp(s1, s2, size);
8299 +}
8300 +
8301 +int DWC_STRCMP(void *s1, void *s2)
8302 +{
8303 +       return strcmp(s1, s2);
8304 +}
8305 +
8306 +int DWC_STRLEN(char const *str)
8307 +{
8308 +       return strlen(str);
8309 +}
8310 +
8311 +char *DWC_STRCPY(char *to, char const *from)
8312 +{
8313 +       return strcpy(to, from);
8314 +}
8315 +
8316 +char *DWC_STRDUP(char const *str)
8317 +{
8318 +       int len = DWC_STRLEN(str) + 1;
8319 +       char *new = DWC_ALLOC_ATOMIC(len);
8320 +
8321 +       if (!new) {
8322 +               return NULL;
8323 +       }
8324 +
8325 +       DWC_MEMCPY(new, str, len);
8326 +       return new;
8327 +}
8328 +
8329 +int DWC_ATOI(char *str, int32_t *value)
8330 +{
8331 +       char *end = NULL;
8332 +
8333 +       /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'
8334 +        * should be equivalent on 2's complement machines
8335 +        */
8336 +       *value = strtoul(str, &end, 0);
8337 +       if (*end == '\0') {
8338 +               return 0;
8339 +       }
8340 +
8341 +       return -1;
8342 +}
8343 +
8344 +int DWC_ATOUI(char *str, uint32_t *value)
8345 +{
8346 +       char *end = NULL;
8347 +
8348 +       *value = strtoul(str, &end, 0);
8349 +       if (*end == '\0') {
8350 +               return 0;
8351 +       }
8352 +
8353 +       return -1;
8354 +}
8355 +
8356 +
8357 +#ifdef DWC_UTFLIB
8358 +/* From usbstring.c */
8359 +
8360 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
8361 +{
8362 +       int     count = 0;
8363 +       u8      c;
8364 +       u16     uchar;
8365 +
8366 +       /* this insists on correct encodings, though not minimal ones.
8367 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
8368 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
8369 +        */
8370 +       while (len != 0 && (c = (u8) *s++) != 0) {
8371 +               if (unlikely(c & 0x80)) {
8372 +                       // 2-byte sequence:
8373 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
8374 +                       if ((c & 0xe0) == 0xc0) {
8375 +                               uchar = (c & 0x1f) << 6;
8376 +
8377 +                               c = (u8) *s++;
8378 +                               if ((c & 0xc0) != 0xc0)
8379 +                                       goto fail;
8380 +                               c &= 0x3f;
8381 +                               uchar |= c;
8382 +
8383 +                       // 3-byte sequence (most CJKV characters):
8384 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
8385 +                       } else if ((c & 0xf0) == 0xe0) {
8386 +                               uchar = (c & 0x0f) << 12;
8387 +
8388 +                               c = (u8) *s++;
8389 +                               if ((c & 0xc0) != 0xc0)
8390 +                                       goto fail;
8391 +                               c &= 0x3f;
8392 +                               uchar |= c << 6;
8393 +
8394 +                               c = (u8) *s++;
8395 +                               if ((c & 0xc0) != 0xc0)
8396 +                                       goto fail;
8397 +                               c &= 0x3f;
8398 +                               uchar |= c;
8399 +
8400 +                               /* no bogus surrogates */
8401 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
8402 +                                       goto fail;
8403 +
8404 +                       // 4-byte sequence (surrogate pairs, currently rare):
8405 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
8406 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
8407 +                       // (uuuuu = wwww + 1)
8408 +                       // FIXME accept the surrogate code points (only)
8409 +                       } else
8410 +                               goto fail;
8411 +               } else
8412 +                       uchar = c;
8413 +               put_unaligned (cpu_to_le16 (uchar), cp++);
8414 +               count++;
8415 +               len--;
8416 +       }
8417 +       return count;
8418 +fail:
8419 +       return -1;
8420 +}
8421 +
8422 +#endif /* DWC_UTFLIB */
8423 +
8424 +
8425 +/* dwc_debug.h */
8426 +
8427 +dwc_bool_t DWC_IN_IRQ(void)
8428 +{
8429 +//     return in_irq();
8430 +       return 0;
8431 +}
8432 +
8433 +dwc_bool_t DWC_IN_BH(void)
8434 +{
8435 +//     return in_softirq();
8436 +       return 0;
8437 +}
8438 +
8439 +void DWC_VPRINTF(char *format, va_list args)
8440 +{
8441 +       vprintf(format, args);
8442 +}
8443 +
8444 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
8445 +{
8446 +       return vsnprintf(str, size, format, args);
8447 +}
8448 +
8449 +void DWC_PRINTF(char *format, ...)
8450 +{
8451 +       va_list args;
8452 +
8453 +       va_start(args, format);
8454 +       DWC_VPRINTF(format, args);
8455 +       va_end(args);
8456 +}
8457 +
8458 +int DWC_SPRINTF(char *buffer, char *format, ...)
8459 +{
8460 +       int retval;
8461 +       va_list args;
8462 +
8463 +       va_start(args, format);
8464 +       retval = vsprintf(buffer, format, args);
8465 +       va_end(args);
8466 +       return retval;
8467 +}
8468 +
8469 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
8470 +{
8471 +       int retval;
8472 +       va_list args;
8473 +
8474 +       va_start(args, format);
8475 +       retval = vsnprintf(buffer, size, format, args);
8476 +       va_end(args);
8477 +       return retval;
8478 +}
8479 +
8480 +void __DWC_WARN(char *format, ...)
8481 +{
8482 +       va_list args;
8483 +
8484 +       va_start(args, format);
8485 +       DWC_VPRINTF(format, args);
8486 +       va_end(args);
8487 +}
8488 +
8489 +void __DWC_ERROR(char *format, ...)
8490 +{
8491 +       va_list args;
8492 +
8493 +       va_start(args, format);
8494 +       DWC_VPRINTF(format, args);
8495 +       va_end(args);
8496 +}
8497 +
8498 +void DWC_EXCEPTION(char *format, ...)
8499 +{
8500 +       va_list args;
8501 +
8502 +       va_start(args, format);
8503 +       DWC_VPRINTF(format, args);
8504 +       va_end(args);
8505 +//     BUG_ON(1);      ???
8506 +}
8507 +
8508 +#ifdef DEBUG
8509 +void __DWC_DEBUG(char *format, ...)
8510 +{
8511 +       va_list args;
8512 +
8513 +       va_start(args, format);
8514 +       DWC_VPRINTF(format, args);
8515 +       va_end(args);
8516 +}
8517 +#endif
8518 +
8519 +
8520 +/* dwc_mem.h */
8521 +
8522 +#if 0
8523 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
8524 +                               uint32_t align,
8525 +                               uint32_t alloc)
8526 +{
8527 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
8528 +                                               size, align, alloc);
8529 +       return (dwc_pool_t *)pool;
8530 +}
8531 +
8532 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
8533 +{
8534 +       dma_pool_destroy((struct dma_pool *)pool);
8535 +}
8536 +
8537 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8538 +{
8539 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
8540 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
8541 +}
8542 +
8543 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8544 +{
8545 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
8546 +       memset(..);
8547 +}
8548 +
8549 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
8550 +{
8551 +       dma_pool_free(pool, vaddr, daddr);
8552 +}
8553 +#endif
8554 +
8555 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
8556 +{
8557 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8558 +       int error;
8559 +
8560 +       error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,
8561 +                                sizeof(dma->segs) / sizeof(dma->segs[0]),
8562 +                                &dma->nsegs, BUS_DMA_NOWAIT);
8563 +       if (error) {
8564 +               printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,
8565 +                      (uintmax_t)size, error);
8566 +               goto fail_0;
8567 +       }
8568 +
8569 +       error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,
8570 +                              (caddr_t *)&dma->dma_vaddr,
8571 +                              BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
8572 +       if (error) {
8573 +               printf("%s: bus_dmamem_map failed: %d\n", __func__, error);
8574 +               goto fail_1;
8575 +       }
8576 +
8577 +       error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
8578 +                                 BUS_DMA_NOWAIT, &dma->dma_map);
8579 +       if (error) {
8580 +               printf("%s: bus_dmamap_create failed: %d\n", __func__, error);
8581 +               goto fail_2;
8582 +       }
8583 +
8584 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
8585 +                               size, NULL, BUS_DMA_NOWAIT);
8586 +       if (error) {
8587 +               printf("%s: bus_dmamap_load failed: %d\n", __func__, error);
8588 +               goto fail_3;
8589 +       }
8590 +
8591 +       dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;
8592 +       *dma_addr = dma->dma_paddr;
8593 +       return dma->dma_vaddr;
8594 +
8595 +fail_3:
8596 +       bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8597 +fail_2:
8598 +       bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8599 +fail_1:
8600 +       bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8601 +fail_0:
8602 +       dma->dma_map = NULL;
8603 +       dma->dma_vaddr = NULL;
8604 +       dma->nsegs = 0;
8605 +
8606 +       return NULL;
8607 +}
8608 +
8609 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
8610 +{
8611 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8612 +
8613 +       if (dma->dma_map != NULL) {
8614 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,
8615 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
8616 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
8617 +               bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8618 +               bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8619 +               bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8620 +               dma->dma_paddr = 0;
8621 +               dma->dma_map = NULL;
8622 +               dma->dma_vaddr = NULL;
8623 +               dma->nsegs = 0;
8624 +       }
8625 +}
8626 +
8627 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
8628 +{
8629 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
8630 +}
8631 +
8632 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
8633 +{
8634 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
8635 +}
8636 +
8637 +void __DWC_FREE(void *mem_ctx, void *addr)
8638 +{
8639 +       free(addr, M_DEVBUF);
8640 +}
8641 +
8642 +
8643 +#ifdef DWC_CRYPTOLIB
8644 +/* dwc_crypto.h */
8645 +
8646 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
8647 +{
8648 +       get_random_bytes(buffer, length);
8649 +}
8650 +
8651 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
8652 +{
8653 +       struct crypto_blkcipher *tfm;
8654 +       struct blkcipher_desc desc;
8655 +       struct scatterlist sgd;
8656 +       struct scatterlist sgs;
8657 +
8658 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
8659 +       if (tfm == NULL) {
8660 +               printk("failed to load transform for aes CBC\n");
8661 +               return -1;
8662 +       }
8663 +
8664 +       crypto_blkcipher_setkey(tfm, key, keylen);
8665 +       crypto_blkcipher_set_iv(tfm, iv, 16);
8666 +
8667 +       sg_init_one(&sgd, out, messagelen);
8668 +       sg_init_one(&sgs, message, messagelen);
8669 +
8670 +       desc.tfm = tfm;
8671 +       desc.flags = 0;
8672 +
8673 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
8674 +               crypto_free_blkcipher(tfm);
8675 +               DWC_ERROR("AES CBC encryption failed");
8676 +               return -1;
8677 +       }
8678 +
8679 +       crypto_free_blkcipher(tfm);
8680 +       return 0;
8681 +}
8682 +
8683 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
8684 +{
8685 +       struct crypto_hash *tfm;
8686 +       struct hash_desc desc;
8687 +       struct scatterlist sg;
8688 +
8689 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
8690 +       if (IS_ERR(tfm)) {
8691 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
8692 +               return 0;
8693 +       }
8694 +       desc.tfm = tfm;
8695 +       desc.flags = 0;
8696 +
8697 +       sg_init_one(&sg, message, len);
8698 +       crypto_hash_digest(&desc, &sg, len, out);
8699 +       crypto_free_hash(tfm);
8700 +
8701 +       return 1;
8702 +}
8703 +
8704 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
8705 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
8706 +{
8707 +       struct crypto_hash *tfm;
8708 +       struct hash_desc desc;
8709 +       struct scatterlist sg;
8710 +
8711 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
8712 +       if (IS_ERR(tfm)) {
8713 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
8714 +               return 0;
8715 +       }
8716 +       desc.tfm = tfm;
8717 +       desc.flags = 0;
8718 +
8719 +       sg_init_one(&sg, message, messagelen);
8720 +       crypto_hash_setkey(tfm, key, keylen);
8721 +       crypto_hash_digest(&desc, &sg, messagelen, out);
8722 +       crypto_free_hash(tfm);
8723 +
8724 +       return 1;
8725 +}
8726 +
8727 +#endif /* DWC_CRYPTOLIB */
8728 +
8729 +
8730 +/* Byte Ordering Conversions */
8731 +
8732 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
8733 +{
8734 +#ifdef __LITTLE_ENDIAN
8735 +       return *p;
8736 +#else
8737 +       uint8_t *u_p = (uint8_t *)p;
8738 +
8739 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8740 +#endif
8741 +}
8742 +
8743 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
8744 +{
8745 +#ifdef __BIG_ENDIAN
8746 +       return *p;
8747 +#else
8748 +       uint8_t *u_p = (uint8_t *)p;
8749 +
8750 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8751 +#endif
8752 +}
8753 +
8754 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
8755 +{
8756 +#ifdef __LITTLE_ENDIAN
8757 +       return *p;
8758 +#else
8759 +       uint8_t *u_p = (uint8_t *)p;
8760 +
8761 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8762 +#endif
8763 +}
8764 +
8765 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
8766 +{
8767 +#ifdef __BIG_ENDIAN
8768 +       return *p;
8769 +#else
8770 +       uint8_t *u_p = (uint8_t *)p;
8771 +
8772 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8773 +#endif
8774 +}
8775 +
8776 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
8777 +{
8778 +#ifdef __LITTLE_ENDIAN
8779 +       return *p;
8780 +#else
8781 +       uint8_t *u_p = (uint8_t *)p;
8782 +       return (u_p[1] | (u_p[0] << 8));
8783 +#endif
8784 +}
8785 +
8786 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
8787 +{
8788 +#ifdef __BIG_ENDIAN
8789 +       return *p;
8790 +#else
8791 +       uint8_t *u_p = (uint8_t *)p;
8792 +       return (u_p[1] | (u_p[0] << 8));
8793 +#endif
8794 +}
8795 +
8796 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
8797 +{
8798 +#ifdef __LITTLE_ENDIAN
8799 +       return *p;
8800 +#else
8801 +       uint8_t *u_p = (uint8_t *)p;
8802 +       return (u_p[1] | (u_p[0] << 8));
8803 +#endif
8804 +}
8805 +
8806 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
8807 +{
8808 +#ifdef __BIG_ENDIAN
8809 +       return *p;
8810 +#else
8811 +       uint8_t *u_p = (uint8_t *)p;
8812 +       return (u_p[1] | (u_p[0] << 8));
8813 +#endif
8814 +}
8815 +
8816 +
8817 +/* Registers */
8818 +
8819 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
8820 +{
8821 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8822 +       bus_size_t ior = (bus_size_t)reg;
8823 +
8824 +       return bus_space_read_4(io->iot, io->ioh, ior);
8825 +}
8826 +
8827 +#if 0
8828 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
8829 +{
8830 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8831 +       bus_size_t ior = (bus_size_t)reg;
8832 +
8833 +       return bus_space_read_8(io->iot, io->ioh, ior);
8834 +}
8835 +#endif
8836 +
8837 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
8838 +{
8839 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8840 +       bus_size_t ior = (bus_size_t)reg;
8841 +
8842 +       bus_space_write_4(io->iot, io->ioh, ior, value);
8843 +}
8844 +
8845 +#if 0
8846 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
8847 +{
8848 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8849 +       bus_size_t ior = (bus_size_t)reg;
8850 +
8851 +       bus_space_write_8(io->iot, io->ioh, ior, value);
8852 +}
8853 +#endif
8854 +
8855 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
8856 +                     uint32_t set_mask)
8857 +{
8858 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8859 +       bus_size_t ior = (bus_size_t)reg;
8860 +
8861 +       bus_space_write_4(io->iot, io->ioh, ior,
8862 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
8863 +                          ~clear_mask) | set_mask);
8864 +}
8865 +
8866 +#if 0
8867 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
8868 +                     uint64_t set_mask)
8869 +{
8870 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8871 +       bus_size_t ior = (bus_size_t)reg;
8872 +
8873 +       bus_space_write_8(io->iot, io->ioh, ior,
8874 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
8875 +                          ~clear_mask) | set_mask);
8876 +}
8877 +#endif
8878 +
8879 +
8880 +/* Locking */
8881 +
8882 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
8883 +{
8884 +       struct simplelock *sl = DWC_ALLOC(sizeof(*sl));
8885 +
8886 +       if (!sl) {
8887 +               DWC_ERROR("Cannot allocate memory for spinlock");
8888 +               return NULL;
8889 +       }
8890 +
8891 +       simple_lock_init(sl);
8892 +       return (dwc_spinlock_t *)sl;
8893 +}
8894 +
8895 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
8896 +{
8897 +       struct simplelock *sl = (struct simplelock *)lock;
8898 +
8899 +       DWC_FREE(sl);
8900 +}
8901 +
8902 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
8903 +{
8904 +       simple_lock((struct simplelock *)lock);
8905 +}
8906 +
8907 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
8908 +{
8909 +       simple_unlock((struct simplelock *)lock);
8910 +}
8911 +
8912 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
8913 +{
8914 +       simple_lock((struct simplelock *)lock);
8915 +       *flags = splbio();
8916 +}
8917 +
8918 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
8919 +{
8920 +       splx(flags);
8921 +       simple_unlock((struct simplelock *)lock);
8922 +}
8923 +
8924 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
8925 +{
8926 +       dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));
8927 +
8928 +       if (!mutex) {
8929 +               DWC_ERROR("Cannot allocate memory for mutex");
8930 +               return NULL;
8931 +       }
8932 +
8933 +       lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);
8934 +       return mutex;
8935 +}
8936 +
8937 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
8938 +#else
8939 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
8940 +{
8941 +       DWC_FREE(mutex);
8942 +}
8943 +#endif
8944 +
8945 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
8946 +{
8947 +       lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);
8948 +}
8949 +
8950 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
8951 +{
8952 +       int status;
8953 +
8954 +       status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);
8955 +       return status == 0;
8956 +}
8957 +
8958 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
8959 +{
8960 +       lockmgr((struct lock *)mutex, LK_RELEASE, NULL);
8961 +}
8962 +
8963 +
8964 +/* Timing */
8965 +
8966 +void DWC_UDELAY(uint32_t usecs)
8967 +{
8968 +       DELAY(usecs);
8969 +}
8970 +
8971 +void DWC_MDELAY(uint32_t msecs)
8972 +{
8973 +       do {
8974 +               DELAY(1000);
8975 +       } while (--msecs);
8976 +}
8977 +
8978 +void DWC_MSLEEP(uint32_t msecs)
8979 +{
8980 +       struct timeval tv;
8981 +
8982 +       tv.tv_sec = msecs / 1000;
8983 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
8984 +       tsleep(&tv, 0, "dw3slp", tvtohz(&tv));
8985 +}
8986 +
8987 +uint32_t DWC_TIME(void)
8988 +{
8989 +       struct timeval tv;
8990 +
8991 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
8992 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
8993 +}
8994 +
8995 +
8996 +/* Timers */
8997 +
8998 +struct dwc_timer {
8999 +       struct callout t;
9000 +       char *name;
9001 +       dwc_spinlock_t *lock;
9002 +       dwc_timer_callback_t cb;
9003 +       void *data;
9004 +};
9005 +
9006 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
9007 +{
9008 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
9009 +
9010 +       if (!t) {
9011 +               DWC_ERROR("Cannot allocate memory for timer");
9012 +               return NULL;
9013 +       }
9014 +
9015 +       callout_init(&t->t);
9016 +
9017 +       t->name = DWC_STRDUP(name);
9018 +       if (!t->name) {
9019 +               DWC_ERROR("Cannot allocate memory for timer->name");
9020 +               goto no_name;
9021 +       }
9022 +
9023 +       t->lock = DWC_SPINLOCK_ALLOC();
9024 +       if (!t->lock) {
9025 +               DWC_ERROR("Cannot allocate memory for timer->lock");
9026 +               goto no_lock;
9027 +       }
9028 +
9029 +       t->cb = cb;
9030 +       t->data = data;
9031 +
9032 +       return t;
9033 +
9034 + no_lock:
9035 +       DWC_FREE(t->name);
9036 + no_name:
9037 +       DWC_FREE(t);
9038 +
9039 +       return NULL;
9040 +}
9041 +
9042 +void DWC_TIMER_FREE(dwc_timer_t *timer)
9043 +{
9044 +       callout_stop(&timer->t);
9045 +       DWC_SPINLOCK_FREE(timer->lock);
9046 +       DWC_FREE(timer->name);
9047 +       DWC_FREE(timer);
9048 +}
9049 +
9050 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
9051 +{
9052 +       struct timeval tv;
9053 +
9054 +       tv.tv_sec = time / 1000;
9055 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9056 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
9057 +}
9058 +
9059 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
9060 +{
9061 +       callout_stop(&timer->t);
9062 +}
9063 +
9064 +
9065 +/* Wait Queues */
9066 +
9067 +struct dwc_waitq {
9068 +       struct simplelock lock;
9069 +       int abort;
9070 +};
9071 +
9072 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
9073 +{
9074 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
9075 +
9076 +       if (!wq) {
9077 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9078 +               return NULL;
9079 +       }
9080 +
9081 +       simple_lock_init(&wq->lock);
9082 +       wq->abort = 0;
9083 +
9084 +       return wq;
9085 +}
9086 +
9087 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
9088 +{
9089 +       DWC_FREE(wq);
9090 +}
9091 +
9092 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
9093 +{
9094 +       int ipl;
9095 +       int result = 0;
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 +               result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout
9104 +               ipl = splbio();
9105 +       }
9106 +
9107 +       if (result == 0) {                      // awoken
9108 +               if (wq->abort) {
9109 +                       wq->abort = 0;
9110 +                       result = -DWC_E_ABORT;
9111 +               } else {
9112 +                       result = 0;
9113 +               }
9114 +
9115 +               splx(ipl);
9116 +               simple_unlock(&wq->lock);
9117 +       } else {
9118 +               wq->abort = 0;
9119 +               splx(ipl);
9120 +               simple_unlock(&wq->lock);
9121 +
9122 +               if (result == ERESTART) {       // signaled - restart
9123 +                       result = -DWC_E_RESTART;
9124 +               } else {                        // signaled - must be EINTR
9125 +                       result = -DWC_E_ABORT;
9126 +               }
9127 +       }
9128 +
9129 +       return result;
9130 +}
9131 +
9132 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
9133 +                              void *data, int32_t msecs)
9134 +{
9135 +       struct timeval tv, tv1, tv2;
9136 +       int ipl;
9137 +       int result = 0;
9138 +
9139 +       tv.tv_sec = msecs / 1000;
9140 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
9141 +
9142 +       simple_lock(&wq->lock);
9143 +       ipl = splbio();
9144 +
9145 +       /* Skip the sleep if already aborted or triggered */
9146 +       if (!wq->abort && !cond(data)) {
9147 +               splx(ipl);
9148 +               getmicrouptime(&tv1);
9149 +               result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);
9150 +               getmicrouptime(&tv2);
9151 +               ipl = splbio();
9152 +       }
9153 +
9154 +       if (result == 0) {                      // awoken
9155 +               if (wq->abort) {
9156 +                       wq->abort = 0;
9157 +                       splx(ipl);
9158 +                       simple_unlock(&wq->lock);
9159 +                       result = -DWC_E_ABORT;
9160 +               } else {
9161 +                       splx(ipl);
9162 +                       simple_unlock(&wq->lock);
9163 +
9164 +                       tv2.tv_usec -= tv1.tv_usec;
9165 +                       if (tv2.tv_usec < 0) {
9166 +                               tv2.tv_usec += 1000000;
9167 +                               tv2.tv_sec--;
9168 +                       }
9169 +
9170 +                       tv2.tv_sec -= tv1.tv_sec;
9171 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
9172 +                       result = msecs - result;
9173 +                       if (result <= 0)
9174 +                               result = 1;
9175 +               }
9176 +       } else {
9177 +               wq->abort = 0;
9178 +               splx(ipl);
9179 +               simple_unlock(&wq->lock);
9180 +
9181 +               if (result == ERESTART) {       // signaled - restart
9182 +                       result = -DWC_E_RESTART;
9183 +
9184 +               } else if (result == EINTR) {           // signaled - interrupt
9185 +                       result = -DWC_E_ABORT;
9186 +
9187 +               } else {                                // timed out
9188 +                       result = -DWC_E_TIMEOUT;
9189 +               }
9190 +       }
9191 +
9192 +       return result;
9193 +}
9194 +
9195 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
9196 +{
9197 +       wakeup(wq);
9198 +}
9199 +
9200 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
9201 +{
9202 +       int ipl;
9203 +
9204 +       simple_lock(&wq->lock);
9205 +       ipl = splbio();
9206 +       wq->abort = 1;
9207 +       wakeup(wq);
9208 +       splx(ipl);
9209 +       simple_unlock(&wq->lock);
9210 +}
9211 +
9212 +
9213 +/* Threading */
9214 +
9215 +struct dwc_thread {
9216 +       struct proc *proc;
9217 +       int abort;
9218 +};
9219 +
9220 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
9221 +{
9222 +       int retval;
9223 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
9224 +
9225 +       if (!thread) {
9226 +               return NULL;
9227 +       }
9228 +
9229 +       thread->abort = 0;
9230 +       retval = kthread_create1((void (*)(void *))func, data, &thread->proc,
9231 +                                "%s", name);
9232 +       if (retval) {
9233 +               DWC_FREE(thread);
9234 +               return NULL;
9235 +       }
9236 +
9237 +       return thread;
9238 +}
9239 +
9240 +int DWC_THREAD_STOP(dwc_thread_t *thread)
9241 +{
9242 +       int retval;
9243 +
9244 +       thread->abort = 1;
9245 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
9246 +
9247 +       if (retval == 0) {
9248 +               /* DWC_THREAD_EXIT() will free the thread struct */
9249 +               return 0;
9250 +       }
9251 +
9252 +       /* NOTE: We leak the thread struct if thread doesn't die */
9253 +
9254 +       if (retval == EWOULDBLOCK) {
9255 +               return -DWC_E_TIMEOUT;
9256 +       }
9257 +
9258 +       return -DWC_E_UNKNOWN;
9259 +}
9260 +
9261 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
9262 +{
9263 +       return thread->abort;
9264 +}
9265 +
9266 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
9267 +{
9268 +       wakeup(&thread->abort);
9269 +       DWC_FREE(thread);
9270 +       kthread_exit(0);
9271 +}
9272 +
9273 +/* tasklets
9274 + - Runs in interrupt context (cannot sleep)
9275 + - Each tasklet runs on a single CPU
9276 + - Different tasklets can be running simultaneously on different CPUs
9277 + [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-
9278 +   halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]
9279 + */
9280 +struct dwc_tasklet {
9281 +       dwc_tasklet_callback_t cb;
9282 +       void *data;
9283 +};
9284 +
9285 +static void tasklet_callback(void *data)
9286 +{
9287 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
9288 +
9289 +       task->cb(task->data);
9290 +}
9291 +
9292 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
9293 +{
9294 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
9295 +
9296 +       if (task) {
9297 +               task->cb = cb;
9298 +               task->data = data;
9299 +       } else {
9300 +               DWC_ERROR("Cannot allocate memory for tasklet");
9301 +       }
9302 +
9303 +       return task;
9304 +}
9305 +
9306 +void DWC_TASK_FREE(dwc_tasklet_t *task)
9307 +{
9308 +       DWC_FREE(task);
9309 +}
9310 +
9311 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
9312 +{
9313 +       tasklet_callback(task);
9314 +}
9315 +
9316 +
9317 +/* workqueues
9318 + - Runs in process context (can sleep)
9319 + */
9320 +typedef struct work_container {
9321 +       dwc_work_callback_t cb;
9322 +       void *data;
9323 +       dwc_workq_t *wq;
9324 +       char *name;
9325 +       int hz;
9326 +       struct work task;
9327 +} work_container_t;
9328 +
9329 +struct dwc_workq {
9330 +       struct workqueue *taskq;
9331 +       dwc_spinlock_t *lock;
9332 +       dwc_waitq_t *waitq;
9333 +       int pending;
9334 +       struct work_container *container;
9335 +};
9336 +
9337 +static void do_work(struct work *task, void *data)
9338 +{
9339 +       dwc_workq_t *wq = (dwc_workq_t *)data;
9340 +       work_container_t *container = wq->container;
9341 +       dwc_irqflags_t flags;
9342 +
9343 +       if (container->hz) {
9344 +               tsleep(container, 0, "dw3wrk", container->hz);
9345 +       }
9346 +
9347 +       container->cb(container->data);
9348 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
9349 +
9350 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9351 +       if (container->name)
9352 +               DWC_FREE(container->name);
9353 +       DWC_FREE(container);
9354 +       wq->pending--;
9355 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9356 +       DWC_WAITQ_TRIGGER(wq->waitq);
9357 +}
9358 +
9359 +static int work_done(void *data)
9360 +{
9361 +       dwc_workq_t *workq = (dwc_workq_t *)data;
9362 +
9363 +       return workq->pending == 0;
9364 +}
9365 +
9366 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
9367 +{
9368 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
9369 +}
9370 +
9371 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
9372 +{
9373 +       int result;
9374 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
9375 +
9376 +       if (!wq) {
9377 +               DWC_ERROR("Cannot allocate memory for workqueue");
9378 +               return NULL;
9379 +       }
9380 +
9381 +       result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,
9382 +                                 IPL_BIO, 0);
9383 +       if (result) {
9384 +               DWC_ERROR("Cannot create workqueue");
9385 +               goto no_taskq;
9386 +       }
9387 +
9388 +       wq->pending = 0;
9389 +
9390 +       wq->lock = DWC_SPINLOCK_ALLOC();
9391 +       if (!wq->lock) {
9392 +               DWC_ERROR("Cannot allocate memory for spinlock");
9393 +               goto no_lock;
9394 +       }
9395 +
9396 +       wq->waitq = DWC_WAITQ_ALLOC();
9397 +       if (!wq->waitq) {
9398 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9399 +               goto no_waitq;
9400 +       }
9401 +
9402 +       return wq;
9403 +
9404 + no_waitq:
9405 +       DWC_SPINLOCK_FREE(wq->lock);
9406 + no_lock:
9407 +       workqueue_destroy(wq->taskq);
9408 + no_taskq:
9409 +       DWC_FREE(wq);
9410 +
9411 +       return NULL;
9412 +}
9413 +
9414 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
9415 +{
9416 +#ifdef DEBUG
9417 +       dwc_irqflags_t flags;
9418 +
9419 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9420 +
9421 +       if (wq->pending != 0) {
9422 +               struct work_container *container = wq->container;
9423 +
9424 +               DWC_ERROR("Destroying work queue with pending work");
9425 +
9426 +               if (container && container->name) {
9427 +                       DWC_ERROR("Work %s still pending", container->name);
9428 +               }
9429 +       }
9430 +
9431 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9432 +#endif
9433 +       DWC_WAITQ_FREE(wq->waitq);
9434 +       DWC_SPINLOCK_FREE(wq->lock);
9435 +       workqueue_destroy(wq->taskq);
9436 +       DWC_FREE(wq);
9437 +}
9438 +
9439 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
9440 +                       char *format, ...)
9441 +{
9442 +       dwc_irqflags_t flags;
9443 +       work_container_t *container;
9444 +       static char name[128];
9445 +       va_list args;
9446 +
9447 +       va_start(args, format);
9448 +       DWC_VSNPRINTF(name, 128, format, args);
9449 +       va_end(args);
9450 +
9451 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9452 +       wq->pending++;
9453 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9454 +       DWC_WAITQ_TRIGGER(wq->waitq);
9455 +
9456 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9457 +       if (!container) {
9458 +               DWC_ERROR("Cannot allocate memory for container");
9459 +               return;
9460 +       }
9461 +
9462 +       container->name = DWC_STRDUP(name);
9463 +       if (!container->name) {
9464 +               DWC_ERROR("Cannot allocate memory for container->name");
9465 +               DWC_FREE(container);
9466 +               return;
9467 +       }
9468 +
9469 +       container->cb = cb;
9470 +       container->data = data;
9471 +       container->wq = wq;
9472 +       container->hz = 0;
9473 +       wq->container = container;
9474 +
9475 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9476 +       workqueue_enqueue(wq->taskq, &container->task);
9477 +}
9478 +
9479 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
9480 +                               void *data, uint32_t time, char *format, ...)
9481 +{
9482 +       dwc_irqflags_t flags;
9483 +       work_container_t *container;
9484 +       static char name[128];
9485 +       struct timeval tv;
9486 +       va_list args;
9487 +
9488 +       va_start(args, format);
9489 +       DWC_VSNPRINTF(name, 128, format, args);
9490 +       va_end(args);
9491 +
9492 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9493 +       wq->pending++;
9494 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9495 +       DWC_WAITQ_TRIGGER(wq->waitq);
9496 +
9497 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9498 +       if (!container) {
9499 +               DWC_ERROR("Cannot allocate memory for container");
9500 +               return;
9501 +       }
9502 +
9503 +       container->name = DWC_STRDUP(name);
9504 +       if (!container->name) {
9505 +               DWC_ERROR("Cannot allocate memory for container->name");
9506 +               DWC_FREE(container);
9507 +               return;
9508 +       }
9509 +
9510 +       container->cb = cb;
9511 +       container->data = data;
9512 +       container->wq = wq;
9513 +       tv.tv_sec = time / 1000;
9514 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9515 +       container->hz = tvtohz(&tv);
9516 +       wq->container = container;
9517 +
9518 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9519 +       workqueue_enqueue(wq->taskq, &container->task);
9520 +}
9521 +
9522 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
9523 +{
9524 +       return wq->pending;
9525 +}
9526 diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.c b/drivers/usb/host/dwc_common_port/dwc_crypto.c
9527 new file mode 100644
9528 index 0000000..3b03532
9529 --- /dev/null
9530 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
9531 @@ -0,0 +1,308 @@
9532 +/* =========================================================================
9533 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
9534 + * $Revision: #5 $
9535 + * $Date: 2010/09/28 $
9536 + * $Change: 1596182 $
9537 + *
9538 + * Synopsys Portability Library Software and documentation
9539 + * (hereinafter, "Software") is an Unsupported proprietary work of
9540 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9541 + * between Synopsys and you.
9542 + *
9543 + * The Software IS NOT an item of Licensed Software or Licensed Product
9544 + * under any End User Software License Agreement or Agreement for
9545 + * Licensed Product with Synopsys or any supplement thereto. You are
9546 + * permitted to use and redistribute this Software in source and binary
9547 + * forms, with or without modification, provided that redistributions
9548 + * of source code must retain this notice. You may not view, use,
9549 + * disclose, copy or distribute this file or any information contained
9550 + * herein except pursuant to this license grant from Synopsys. If you
9551 + * do not agree with this notice, including the disclaimer below, then
9552 + * you are not authorized to use the Software.
9553 + *
9554 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9555 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9556 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9557 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9558 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9559 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9560 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9561 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9562 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9563 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9564 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9565 + * DAMAGE.
9566 + * ========================================================================= */
9567 +
9568 +/** @file
9569 + * This file contains the WUSB cryptographic routines.
9570 + */
9571 +
9572 +#ifdef DWC_CRYPTOLIB
9573 +
9574 +#include "dwc_crypto.h"
9575 +#include "usb.h"
9576 +
9577 +#ifdef DEBUG
9578 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
9579 +{
9580 +       int i;
9581 +       DWC_PRINTF("%s: ", name);
9582 +       for (i=0; i<len; i++) {
9583 +               DWC_PRINTF("%02x ", bytes[i]);
9584 +       }
9585 +       DWC_PRINTF("\n");
9586 +}
9587 +#else
9588 +#define dump_bytes(x...)
9589 +#endif
9590 +
9591 +/* Display a block */
9592 +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
9593 +{
9594 +#ifdef DWC_DEBUG_CRYPTO
9595 +       int i, blksize = 16;
9596 +
9597 +       DWC_DEBUG("%s", prefix);
9598 +
9599 +       if (suffix == NULL) {
9600 +               suffix = "\n";
9601 +               blksize = a;
9602 +       }
9603 +
9604 +       for (i = 0; i < blksize; i++)
9605 +               DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
9606 +       DWC_PRINT(suffix);
9607 +#endif
9608 +}
9609 +
9610 +/**
9611 + * Encrypts an array of bytes using the AES encryption engine.
9612 + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
9613 + * in-place.
9614 + *
9615 + * @return  0 on success, negative error code on error.
9616 + */
9617 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
9618 +{
9619 +       u8 block_t[16];
9620 +       DWC_MEMSET(block_t, 0, 16);
9621 +
9622 +       return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
9623 +}
9624 +
9625 +/**
9626 + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
9627 + * This function takes a data string and returns the encrypted CBC
9628 + * Counter-mode MIC.
9629 + *
9630 + * @param key     The 128-bit symmetric key.
9631 + * @param nonce   The CCM nonce.
9632 + * @param label   The unique 14-byte ASCII text label.
9633 + * @param bytes   The byte array to be encrypted.
9634 + * @param len     Length of the byte array.
9635 + * @param result  Byte array to receive the 8-byte encrypted MIC.
9636 + */
9637 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9638 +                 char *label, u8 *bytes, int len, u8 *result)
9639 +{
9640 +       u8 block_m[16];
9641 +       u8 block_x[16];
9642 +       u8 block_t[8];
9643 +       int idx, blkNum;
9644 +       u16 la = (u16)(len + 14);
9645 +
9646 +       /* Set the AES-128 key */
9647 +       //dwc_aes_setkey(tfm, key, 16);
9648 +
9649 +       /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
9650 +       block_m[0] = 0x59;
9651 +       for (idx = 0; idx < 13; idx++)
9652 +               block_m[idx + 1] = nonce[idx];
9653 +       block_m[14] = 0;
9654 +       block_m[15] = 0;
9655 +
9656 +       /* Produce the CBC IV */
9657 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9658 +       show_block(block_m, "CBC IV in: ", "\n", 0);
9659 +       show_block(block_x, "CBC IV out:", "\n", 0);
9660 +
9661 +       /* Fill block B1 from l(a) = Blen + 14, and A */
9662 +       block_x[0] ^= (u8)(la >> 8);
9663 +       block_x[1] ^= (u8)la;
9664 +       for (idx = 0; idx < 14; idx++)
9665 +               block_x[idx + 2] ^= label[idx];
9666 +       show_block(block_x, "After xor: ", "b1\n", 16);
9667 +
9668 +       dwc_wusb_aes_encrypt(block_x, key, block_x);
9669 +       show_block(block_x, "After AES: ", "b1\n", 16);
9670 +
9671 +       idx = 0;
9672 +       blkNum = 0;
9673 +
9674 +       /* Fill remaining blocks with B */
9675 +       while (len-- > 0) {
9676 +               block_x[idx] ^= *bytes++;
9677 +               if (++idx >= 16) {
9678 +                       idx = 0;
9679 +                       show_block(block_x, "After xor: ", "\n", blkNum);
9680 +                       dwc_wusb_aes_encrypt(block_x, key, block_x);
9681 +                       show_block(block_x, "After AES: ", "\n", blkNum);
9682 +                       blkNum++;
9683 +               }
9684 +       }
9685 +
9686 +       /* Handle partial last block */
9687 +       if (idx > 0) {
9688 +               show_block(block_x, "After xor: ", "\n", blkNum);
9689 +               dwc_wusb_aes_encrypt(block_x, key, block_x);
9690 +               show_block(block_x, "After AES: ", "\n", blkNum);
9691 +       }
9692 +
9693 +       /* Save the MIC tag */
9694 +       DWC_MEMCPY(block_t, block_x, 8);
9695 +       show_block(block_t, "MIC tag  : ", NULL, 8);
9696 +
9697 +       /* Fill block A0 from flags = 0x01, N, and counter = 0 */
9698 +       block_m[0] = 0x01;
9699 +       block_m[14] = 0;
9700 +       block_m[15] = 0;
9701 +
9702 +       /* Encrypt the counter */
9703 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9704 +       show_block(block_x, "CTR[MIC] : ", NULL, 8);
9705 +
9706 +       /* XOR with MIC tag */
9707 +       for (idx = 0; idx < 8; idx++) {
9708 +               block_t[idx] ^= block_x[idx];
9709 +       }
9710 +
9711 +       /* Return result to caller */
9712 +       DWC_MEMCPY(result, block_t, 8);
9713 +       show_block(result, "CCM-MIC  : ", NULL, 8);
9714 +
9715 +}
9716 +
9717 +/**
9718 + * The PRF function described in section 6.5 of the WUSB spec. This function
9719 + * concatenates MIC values returned from dwc_cmf() to create a value of
9720 + * the requested length.
9721 + *
9722 + * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
9723 + * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
9724 + * @param result   Byte array to receive the result.
9725 + */
9726 +void dwc_wusb_prf(int prf_len, u8 *key,
9727 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
9728 +{
9729 +       int i;
9730 +
9731 +       nonce[0] = 0;
9732 +       for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
9733 +               dwc_wusb_cmf(key, nonce, label, bytes, len, result);
9734 +               result += 8;
9735 +       }
9736 +}
9737 +
9738 +/**
9739 + * Fills in CCM Nonce per the WUSB spec.
9740 + *
9741 + * @param[in] haddr Host address.
9742 + * @param[in] daddr Device address.
9743 + * @param[in] tkid Session Key(PTK) identifier.
9744 + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
9745 + */
9746 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9747 +                            uint8_t *nonce)
9748 +{
9749 +
9750 +       DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
9751 +
9752 +       DWC_MEMSET(&nonce[0], 0, 16);
9753 +
9754 +       DWC_MEMCPY(&nonce[6], tkid, 3);
9755 +       nonce[9] = daddr & 0xFF;
9756 +       nonce[10] = (daddr >> 8) & 0xFF;
9757 +       nonce[11] = haddr & 0xFF;
9758 +       nonce[12] = (haddr >> 8) & 0xFF;
9759 +
9760 +       dump_bytes("CCM nonce", nonce, 16);
9761 +}
9762 +
9763 +/**
9764 + * Generates a 16-byte cryptographic-grade random number for the Host/Device
9765 + * Nonce.
9766 + */
9767 +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
9768 +{
9769 +       uint8_t inonce[16];
9770 +       uint32_t temp[4];
9771 +
9772 +       /* Fill in the Nonce */
9773 +       DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
9774 +       inonce[9] = addr & 0xFF;
9775 +       inonce[10] = (addr >> 8) & 0xFF;
9776 +       inonce[11] = inonce[9];
9777 +       inonce[12] = inonce[10];
9778 +
9779 +       /* Collect "randomness samples" */
9780 +       DWC_RANDOM_BYTES((uint8_t *)temp, 16);
9781 +
9782 +       dwc_wusb_prf_128((uint8_t *)temp, nonce,
9783 +                        "Random Numbers", (uint8_t *)temp, sizeof(temp),
9784 +                        nonce);
9785 +}
9786 +
9787 +/**
9788 + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
9789 + * WUSB spec.
9790 + *
9791 + * @param[in] ccm_nonce Pointer to CCM Nonce.
9792 + * @param[in] mk Master Key to derive the session from
9793 + * @param[in] hnonce Pointer to Host Nonce.
9794 + * @param[in] dnonce Pointer to Device Nonce.
9795 + * @param[out] kck Pointer to where the KCK output is to be written.
9796 + * @param[out] ptk Pointer to where the PTK output is to be written.
9797 + */
9798 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
9799 +                     uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
9800 +{
9801 +       uint8_t idata[32];
9802 +       uint8_t odata[32];
9803 +
9804 +       dump_bytes("ck", mk, 16);
9805 +       dump_bytes("hnonce", hnonce, 16);
9806 +       dump_bytes("dnonce", dnonce, 16);
9807 +
9808 +       /* The data is the HNonce and DNonce concatenated */
9809 +       DWC_MEMCPY(&idata[0], hnonce, 16);
9810 +       DWC_MEMCPY(&idata[16], dnonce, 16);
9811 +
9812 +       dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
9813 +
9814 +       /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
9815 +       DWC_MEMCPY(kck, &odata[0], 16);
9816 +       DWC_MEMCPY(ptk, &odata[16], 16);
9817 +
9818 +       dump_bytes("kck", kck, 16);
9819 +       dump_bytes("ptk", ptk, 16);
9820 +}
9821 +
9822 +/**
9823 + * Generates the Message Integrity Code over the Handshake data per the
9824 + * WUSB spec.
9825 + *
9826 + * @param ccm_nonce Pointer to CCM Nonce.
9827 + * @param kck   Pointer to Key Confirmation Key.
9828 + * @param data  Pointer to Handshake data to be checked.
9829 + * @param mic   Pointer to where the MIC output is to be written.
9830 + */
9831 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
9832 +                     uint8_t *data, uint8_t *mic)
9833 +{
9834 +
9835 +       dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
9836 +                       data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
9837 +}
9838 +
9839 +#endif /* DWC_CRYPTOLIB */
9840 diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.h b/drivers/usb/host/dwc_common_port/dwc_crypto.h
9841 new file mode 100644
9842 index 0000000..26fcddc
9843 --- /dev/null
9844 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
9845 @@ -0,0 +1,111 @@
9846 +/* =========================================================================
9847 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
9848 + * $Revision: #3 $
9849 + * $Date: 2010/09/28 $
9850 + * $Change: 1596182 $
9851 + *
9852 + * Synopsys Portability Library Software and documentation
9853 + * (hereinafter, "Software") is an Unsupported proprietary work of
9854 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9855 + * between Synopsys and you.
9856 + *
9857 + * The Software IS NOT an item of Licensed Software or Licensed Product
9858 + * under any End User Software License Agreement or Agreement for
9859 + * Licensed Product with Synopsys or any supplement thereto. You are
9860 + * permitted to use and redistribute this Software in source and binary
9861 + * forms, with or without modification, provided that redistributions
9862 + * of source code must retain this notice. You may not view, use,
9863 + * disclose, copy or distribute this file or any information contained
9864 + * herein except pursuant to this license grant from Synopsys. If you
9865 + * do not agree with this notice, including the disclaimer below, then
9866 + * you are not authorized to use the Software.
9867 + *
9868 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9869 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9870 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9871 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9872 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9873 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9874 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9875 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9876 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9877 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9878 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9879 + * DAMAGE.
9880 + * ========================================================================= */
9881 +
9882 +#ifndef _DWC_CRYPTO_H_
9883 +#define _DWC_CRYPTO_H_
9884 +
9885 +#ifdef __cplusplus
9886 +extern "C" {
9887 +#endif
9888 +
9889 +/** @file
9890 + *
9891 + * This file contains declarations for the WUSB Cryptographic routines as
9892 + * defined in the WUSB spec.  They are only to be used internally by the DWC UWB
9893 + * modules.
9894 + */
9895 +
9896 +#include "dwc_os.h"
9897 +
9898 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
9899 +
9900 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9901 +                 char *label, u8 *bytes, int len, u8 *result);
9902 +void dwc_wusb_prf(int prf_len, u8 *key,
9903 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
9904 +
9905 +/**
9906 + * The PRF-64 function described in section 6.5 of the WUSB spec.
9907 + *
9908 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9909 + */
9910 +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
9911 +                                  char *label, u8 *bytes, int len, u8 *result)
9912 +{
9913 +       dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
9914 +}
9915 +
9916 +/**
9917 + * The PRF-128 function described in section 6.5 of the WUSB spec.
9918 + *
9919 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9920 + */
9921 +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
9922 +                                   char *label, u8 *bytes, int len, u8 *result)
9923 +{
9924 +       dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
9925 +}
9926 +
9927 +/**
9928 + * The PRF-256 function described in section 6.5 of the WUSB spec.
9929 + *
9930 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9931 + */
9932 +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
9933 +                                   char *label, u8 *bytes, int len, u8 *result)
9934 +{
9935 +       dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
9936 +}
9937 +
9938 +
9939 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9940 +                              uint8_t *nonce);
9941 +void dwc_wusb_gen_nonce(uint16_t addr,
9942 +                         uint8_t *nonce);
9943 +
9944 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
9945 +                       uint8_t *hnonce, uint8_t *dnonce,
9946 +                       uint8_t *kck, uint8_t *ptk);
9947 +
9948 +
9949 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
9950 +                       *kck, uint8_t *data, uint8_t *mic);
9951 +
9952 +#ifdef __cplusplus
9953 +}
9954 +#endif
9955 +
9956 +#endif /* _DWC_CRYPTO_H_ */
9957 diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.c b/drivers/usb/host/dwc_common_port/dwc_dh.c
9958 new file mode 100644
9959 index 0000000..2b429a3
9960 --- /dev/null
9961 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
9962 @@ -0,0 +1,291 @@
9963 +/* =========================================================================
9964 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
9965 + * $Revision: #3 $
9966 + * $Date: 2010/09/28 $
9967 + * $Change: 1596182 $
9968 + *
9969 + * Synopsys Portability Library Software and documentation
9970 + * (hereinafter, "Software") is an Unsupported proprietary work of
9971 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9972 + * between Synopsys and you.
9973 + *
9974 + * The Software IS NOT an item of Licensed Software or Licensed Product
9975 + * under any End User Software License Agreement or Agreement for
9976 + * Licensed Product with Synopsys or any supplement thereto. You are
9977 + * permitted to use and redistribute this Software in source and binary
9978 + * forms, with or without modification, provided that redistributions
9979 + * of source code must retain this notice. You may not view, use,
9980 + * disclose, copy or distribute this file or any information contained
9981 + * herein except pursuant to this license grant from Synopsys. If you
9982 + * do not agree with this notice, including the disclaimer below, then
9983 + * you are not authorized to use the Software.
9984 + *
9985 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9986 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9987 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9988 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9989 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9990 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9991 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9992 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9993 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9994 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9995 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9996 + * DAMAGE.
9997 + * ========================================================================= */
9998 +#ifdef DWC_CRYPTOLIB
9999 +
10000 +#ifndef CONFIG_MACH_IPMATE
10001 +
10002 +#include "dwc_dh.h"
10003 +#include "dwc_modpow.h"
10004 +
10005 +#ifdef DEBUG
10006 +/* This function prints out a buffer in the format described in the Association
10007 + * Model specification. */
10008 +static void dh_dump(char *str, void *_num, int len)
10009 +{
10010 +       uint8_t *num = _num;
10011 +       int i;
10012 +       DWC_PRINTF("%s\n", str);
10013 +       for (i = 0; i < len; i ++) {
10014 +               DWC_PRINTF("%02x", num[i]);
10015 +               if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
10016 +               if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
10017 +       }
10018 +
10019 +       DWC_PRINTF("\n");
10020 +}
10021 +#else
10022 +#define dh_dump(_x...) do {; } while(0)
10023 +#endif
10024 +
10025 +/* Constant g value */
10026 +static __u32 dh_g[] = {
10027 +       0x02000000,
10028 +};
10029 +
10030 +/* Constant p value */
10031 +static __u32 dh_p[] = {
10032 +       0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
10033 +       0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
10034 +       0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
10035 +       0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
10036 +       0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
10037 +       0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
10038 +       0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
10039 +       0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
10040 +       0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
10041 +       0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
10042 +       0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
10043 +       0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
10044 +};
10045 +
10046 +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
10047 +{
10048 +       uint8_t *in = _in;
10049 +       uint8_t *out = _out;
10050 +       int i;
10051 +       for (i=0; i<len; i++) {
10052 +               out[i] = in[len-1-i];
10053 +       }
10054 +}
10055 +
10056 +/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
10057 + * big endian numbers of size len, in bytes.  Each len value must be a multiple
10058 + * of 4. */
10059 +int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10060 +                 void *exp, uint32_t exp_len,
10061 +                 void *mod, uint32_t mod_len,
10062 +                 void *out)
10063 +{
10064 +       /* modpow() takes little endian numbers.  AM uses big-endian.  This
10065 +        * function swaps bytes of numbers before passing onto modpow. */
10066 +
10067 +       int retval = 0;
10068 +       uint32_t *result;
10069 +
10070 +       uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
10071 +       uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
10072 +       uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
10073 +
10074 +       dh_swap_bytes(num, &bignum_num[1], num_len);
10075 +       bignum_num[0] = num_len / 4;
10076 +
10077 +       dh_swap_bytes(exp, &bignum_exp[1], exp_len);
10078 +       bignum_exp[0] = exp_len / 4;
10079 +
10080 +       dh_swap_bytes(mod, &bignum_mod[1], mod_len);
10081 +       bignum_mod[0] = mod_len / 4;
10082 +
10083 +       result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
10084 +       if (!result) {
10085 +               retval = -1;
10086 +               goto dh_modpow_nomem;
10087 +       }
10088 +
10089 +       dh_swap_bytes(&result[1], out, result[0] * 4);
10090 +       dwc_free(mem_ctx, result);
10091 +
10092 + dh_modpow_nomem:
10093 +       dwc_free(mem_ctx, bignum_num);
10094 +       dwc_free(mem_ctx, bignum_exp);
10095 +       dwc_free(mem_ctx, bignum_mod);
10096 +       return retval;
10097 +}
10098 +
10099 +
10100 +int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
10101 +{
10102 +       int retval;
10103 +       uint8_t m3[385];
10104 +
10105 +#ifndef DH_TEST_VECTORS
10106 +       DWC_RANDOM_BYTES(exp, 32);
10107 +#endif
10108 +
10109 +       /* Compute the pkd */
10110 +       if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
10111 +                                   exp, 32,
10112 +                                   dh_p, 384, pk))) {
10113 +               return retval;
10114 +       }
10115 +
10116 +       m3[384] = nd;
10117 +       DWC_MEMCPY(&m3[0], pk, 384);
10118 +       DWC_SHA256(m3, 385, hash);
10119 +
10120 +       dh_dump("PK", pk, 384);
10121 +       dh_dump("SHA-256(M3)", hash, 32);
10122 +       return 0;
10123 +}
10124 +
10125 +int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10126 +                      uint8_t *exp, int is_host,
10127 +                      char *dd, uint8_t *ck, uint8_t *kdk)
10128 +{
10129 +       int retval;
10130 +       uint8_t mv[784];
10131 +       uint8_t sha_result[32];
10132 +       uint8_t dhkey[384];
10133 +       uint8_t shared_secret[384];
10134 +       char *message;
10135 +       uint32_t vd;
10136 +
10137 +       uint8_t *pk;
10138 +
10139 +       if (is_host) {
10140 +               pk = pkd;
10141 +       }
10142 +       else {
10143 +               pk = pkh;
10144 +       }
10145 +
10146 +       if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
10147 +                                   exp, 32,
10148 +                                   dh_p, 384, shared_secret))) {
10149 +               return retval;
10150 +       }
10151 +       dh_dump("Shared Secret", shared_secret, 384);
10152 +
10153 +       DWC_SHA256(shared_secret, 384, dhkey);
10154 +       dh_dump("DHKEY", dhkey, 384);
10155 +
10156 +       DWC_MEMCPY(&mv[0], pkd, 384);
10157 +       DWC_MEMCPY(&mv[384], pkh, 384);
10158 +       DWC_MEMCPY(&mv[768], "displayed digest", 16);
10159 +       dh_dump("MV", mv, 784);
10160 +
10161 +       DWC_SHA256(mv, 784, sha_result);
10162 +       dh_dump("SHA-256(MV)", sha_result, 32);
10163 +       dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
10164 +
10165 +       dh_swap_bytes(sha_result, &vd, 4);
10166 +#ifdef DEBUG
10167 +       DWC_PRINTF("Vd (decimal) = %d\n", vd);
10168 +#endif
10169 +
10170 +       switch (nd) {
10171 +       case 2:
10172 +               vd = vd % 100;
10173 +               DWC_SPRINTF(dd, "%02d", vd);
10174 +               break;
10175 +       case 3:
10176 +               vd = vd % 1000;
10177 +               DWC_SPRINTF(dd, "%03d", vd);
10178 +               break;
10179 +       case 4:
10180 +               vd = vd % 10000;
10181 +               DWC_SPRINTF(dd, "%04d", vd);
10182 +               break;
10183 +       }
10184 +#ifdef DEBUG
10185 +       DWC_PRINTF("Display Digits: %s\n", dd);
10186 +#endif
10187 +
10188 +       message = "connection key";
10189 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10190 +       dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
10191 +       DWC_MEMCPY(ck, sha_result, 16);
10192 +
10193 +       message = "key derivation key";
10194 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10195 +       dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
10196 +       DWC_MEMCPY(kdk, sha_result, 32);
10197 +
10198 +       return 0;
10199 +}
10200 +
10201 +
10202 +#ifdef DH_TEST_VECTORS
10203 +
10204 +static __u8 dh_a[] = {
10205 +       0x44, 0x00, 0x51, 0xd6,
10206 +       0xf0, 0xb5, 0x5e, 0xa9,
10207 +       0x67, 0xab, 0x31, 0xc6,
10208 +       0x8a, 0x8b, 0x5e, 0x37,
10209 +       0xd9, 0x10, 0xda, 0xe0,
10210 +       0xe2, 0xd4, 0x59, 0xa4,
10211 +       0x86, 0x45, 0x9c, 0xaa,
10212 +       0xdf, 0x36, 0x75, 0x16,
10213 +};
10214 +
10215 +static __u8 dh_b[] = {
10216 +       0x5d, 0xae, 0xc7, 0x86,
10217 +       0x79, 0x80, 0xa3, 0x24,
10218 +       0x8c, 0xe3, 0x57, 0x8f,
10219 +       0xc7, 0x5f, 0x1b, 0x0f,
10220 +       0x2d, 0xf8, 0x9d, 0x30,
10221 +       0x6f, 0xa4, 0x52, 0xcd,
10222 +       0xe0, 0x7a, 0x04, 0x8a,
10223 +       0xde, 0xd9, 0x26, 0x56,
10224 +};
10225 +
10226 +void dwc_run_dh_test_vectors(void *mem_ctx)
10227 +{
10228 +       uint8_t pkd[384];
10229 +       uint8_t pkh[384];
10230 +       uint8_t hashd[32];
10231 +       uint8_t hashh[32];
10232 +       uint8_t ck[16];
10233 +       uint8_t kdk[32];
10234 +       char dd[5];
10235 +
10236 +       DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
10237 +
10238 +       /* compute the PKd and SHA-256(PKd || Nd) */
10239 +       DWC_PRINTF("Computing PKd\n");
10240 +       dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
10241 +
10242 +       /* compute the PKd and SHA-256(PKh || Nd) */
10243 +       DWC_PRINTF("Computing PKh\n");
10244 +       dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
10245 +
10246 +       /* compute the dhkey */
10247 +       dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
10248 +}
10249 +#endif /* DH_TEST_VECTORS */
10250 +
10251 +#endif /* !CONFIG_MACH_IPMATE */
10252 +
10253 +#endif /* DWC_CRYPTOLIB */
10254 diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.h b/drivers/usb/host/dwc_common_port/dwc_dh.h
10255 new file mode 100644
10256 index 0000000..25c1cc0
10257 --- /dev/null
10258 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
10259 @@ -0,0 +1,106 @@
10260 +/* =========================================================================
10261 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
10262 + * $Revision: #4 $
10263 + * $Date: 2010/09/28 $
10264 + * $Change: 1596182 $
10265 + *
10266 + * Synopsys Portability Library Software and documentation
10267 + * (hereinafter, "Software") is an Unsupported proprietary work of
10268 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
10269 + * between Synopsys and you.
10270 + *
10271 + * The Software IS NOT an item of Licensed Software or Licensed Product
10272 + * under any End User Software License Agreement or Agreement for
10273 + * Licensed Product with Synopsys or any supplement thereto. You are
10274 + * permitted to use and redistribute this Software in source and binary
10275 + * forms, with or without modification, provided that redistributions
10276 + * of source code must retain this notice. You may not view, use,
10277 + * disclose, copy or distribute this file or any information contained
10278 + * herein except pursuant to this license grant from Synopsys. If you
10279 + * do not agree with this notice, including the disclaimer below, then
10280 + * you are not authorized to use the Software.
10281 + *
10282 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
10283 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10284 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
10285 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
10286 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10287 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10288 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10289 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
10290 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10291 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
10292 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
10293 + * DAMAGE.
10294 + * ========================================================================= */
10295 +#ifndef _DWC_DH_H_
10296 +#define _DWC_DH_H_
10297 +
10298 +#ifdef __cplusplus
10299 +extern "C" {
10300 +#endif
10301 +
10302 +#include "dwc_os.h"
10303 +
10304 +/** @file
10305 + *
10306 + * This file defines the common functions on device and host for performing
10307 + * numeric association as defined in the WUSB spec.  They are only to be
10308 + * used internally by the DWC UWB modules. */
10309 +
10310 +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
10311 +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
10312 +                             uint8_t *key, uint32_t keylen,
10313 +                             uint8_t *out);
10314 +extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10315 +                        void *exp, uint32_t exp_len,
10316 +                        void *mod, uint32_t mod_len,
10317 +                        void *out);
10318 +
10319 +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
10320 + *
10321 + * PK = g^exp mod p.
10322 + *
10323 + * Input:
10324 + * Nd = Number of digits on the device.
10325 + *
10326 + * Output:
10327 + * exp = A 32-byte buffer to be filled with a randomly generated number.
10328 + *       used as either A or B.
10329 + * pk = A 384-byte buffer to be filled with the PKH or PKD.
10330 + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
10331 + */
10332 +extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
10333 +
10334 +/** Computes the DHKEY, and VD.
10335 + *
10336 + * If called from host, then it will comput DHKEY=PKD^exp % p.
10337 + * If called from device, then it will comput DHKEY=PKH^exp % p.
10338 + *
10339 + * Input:
10340 + * pkd = The PKD value.
10341 + * pkh = The PKH value.
10342 + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
10343 + * is_host = Set to non zero if a WUSB host is calling this function.
10344 + *
10345 + * Output:
10346 +
10347 + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
10348 + *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a
10349 + *      null termination character.  This buffer can be used directly for display.
10350 + * ck = A 16-byte buffer to be filled with the CK.
10351 + * kdk = A 32-byte buffer to be filled with the KDK.
10352 + */
10353 +extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10354 +                             uint8_t *exp, int is_host,
10355 +                             char *dd, uint8_t *ck, uint8_t *kdk);
10356 +
10357 +#ifdef DH_TEST_VECTORS
10358 +extern void dwc_run_dh_test_vectors(void);
10359 +#endif
10360 +
10361 +#ifdef __cplusplus
10362 +}
10363 +#endif
10364 +
10365 +#endif /* _DWC_DH_H_ */
10366 diff --git a/drivers/usb/host/dwc_common_port/dwc_list.h b/drivers/usb/host/dwc_common_port/dwc_list.h
10367 new file mode 100644
10368 index 0000000..89cc325
10369 --- /dev/null
10370 +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
10371 @@ -0,0 +1,594 @@
10372 +/*     $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $       */
10373 +/*     $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $       */
10374 +
10375 +/*
10376 + * Copyright (c) 1991, 1993
10377 + *     The Regents of the University of California.  All rights reserved.
10378 + *
10379 + * Redistribution and use in source and binary forms, with or without
10380 + * modification, are permitted provided that the following conditions
10381 + * are met:
10382 + * 1. Redistributions of source code must retain the above copyright
10383 + *    notice, this list of conditions and the following disclaimer.
10384 + * 2. Redistributions in binary form must reproduce the above copyright
10385 + *    notice, this list of conditions and the following disclaimer in the
10386 + *    documentation and/or other materials provided with the distribution.
10387 + * 3. Neither the name of the University nor the names of its contributors
10388 + *    may be used to endorse or promote products derived from this software
10389 + *    without specific prior written permission.
10390 + *
10391 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
10392 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10393 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10394 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
10395 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10396 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10397 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10398 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10399 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10400 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10401 + * SUCH DAMAGE.
10402 + *
10403 + *     @(#)queue.h     8.5 (Berkeley) 8/20/94
10404 + */
10405 +
10406 +#ifndef _DWC_LIST_H_
10407 +#define _DWC_LIST_H_
10408 +
10409 +#ifdef __cplusplus
10410 +extern "C" {
10411 +#endif
10412 +
10413 +/** @file
10414 + *
10415 + * This file defines linked list operations.  It is derived from BSD with
10416 + * only the MACRO names being prefixed with DWC_.  This is because a few of
10417 + * these names conflict with those on Linux.  For documentation on use, see the
10418 + * inline comments in the source code.  The original license for this source
10419 + * code applies and is preserved in the dwc_list.h source file.
10420 + */
10421 +
10422 +/*
10423 + * This file defines five types of data structures: singly-linked lists,
10424 + * lists, simple queues, tail queues, and circular queues.
10425 + *
10426 + *
10427 + * A singly-linked list is headed by a single forward pointer. The elements
10428 + * are singly linked for minimum space and pointer manipulation overhead at
10429 + * the expense of O(n) removal for arbitrary elements. New elements can be
10430 + * added to the list after an existing element or at the head of the list.
10431 + * Elements being removed from the head of the list should use the explicit
10432 + * macro for this purpose for optimum efficiency. A singly-linked list may
10433 + * only be traversed in the forward direction.  Singly-linked lists are ideal
10434 + * for applications with large datasets and few or no removals or for
10435 + * implementing a LIFO queue.
10436 + *
10437 + * A list is headed by a single forward pointer (or an array of forward
10438 + * pointers for a hash table header). The elements are doubly linked
10439 + * so that an arbitrary element can be removed without a need to
10440 + * traverse the list. New elements can be added to the list before
10441 + * or after an existing element or at the head of the list. A list
10442 + * may only be traversed in the forward direction.
10443 + *
10444 + * A simple queue is headed by a pair of pointers, one the head of the
10445 + * list and the other to the tail of the list. The elements are singly
10446 + * linked to save space, so elements can only be removed from the
10447 + * head of the list. New elements can be added to the list before or after
10448 + * an existing element, at the head of the list, or at the end of the
10449 + * list. A simple queue may only be traversed in the forward direction.
10450 + *
10451 + * A tail queue is headed by a pair of pointers, one to the head of the
10452 + * list and the other to the tail of the list. The elements are doubly
10453 + * linked so that an arbitrary element can be removed without a need to
10454 + * traverse the list. New elements can be added to the list before or
10455 + * after an existing element, at the head of the list, or at the end of
10456 + * the list. A tail queue may be traversed in either direction.
10457 + *
10458 + * A circle queue is headed by a pair of pointers, one to the head of the
10459 + * list and the other to the tail of the list. The elements are doubly
10460 + * linked so that an arbitrary element can be removed without a need to
10461 + * traverse the list. New elements can be added to the list before or after
10462 + * an existing element, at the head of the list, or at the end of the list.
10463 + * A circle queue may be traversed in either direction, but has a more
10464 + * complex end of list detection.
10465 + *
10466 + * For details on the use of these macros, see the queue(3) manual page.
10467 + */
10468 +
10469 +/*
10470 + * Double-linked List.
10471 + */
10472 +
10473 +typedef struct dwc_list_link {
10474 +       struct dwc_list_link *next;
10475 +       struct dwc_list_link *prev;
10476 +} dwc_list_link_t;
10477 +
10478 +#define DWC_LIST_INIT(link) do {       \
10479 +       (link)->next = (link);          \
10480 +       (link)->prev = (link);          \
10481 +} while (0)
10482 +
10483 +#define DWC_LIST_FIRST(link)   ((link)->next)
10484 +#define DWC_LIST_LAST(link)    ((link)->prev)
10485 +#define DWC_LIST_END(link)     (link)
10486 +#define DWC_LIST_NEXT(link)    ((link)->next)
10487 +#define DWC_LIST_PREV(link)    ((link)->prev)
10488 +#define DWC_LIST_EMPTY(link)   \
10489 +       (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
10490 +#define DWC_LIST_ENTRY(link, type, field)                      \
10491 +       (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))
10492 +
10493 +#if 0
10494 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10495 +       (link)->next = (list)->next;                            \
10496 +       (link)->prev = (list);                                  \
10497 +       (list)->next->prev = (link);                            \
10498 +       (list)->next = (link);                                  \
10499 +} while (0)
10500 +
10501 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10502 +       (link)->next = (list);                                  \
10503 +       (link)->prev = (list)->prev;                            \
10504 +       (list)->prev->next = (link);                            \
10505 +       (list)->prev = (link);                                  \
10506 +} while (0)
10507 +#else
10508 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10509 +       dwc_list_link_t *__next__ = (list)->next;               \
10510 +       __next__->prev = (link);                                \
10511 +       (link)->next = __next__;                                \
10512 +       (link)->prev = (list);                                  \
10513 +       (list)->next = (link);                                  \
10514 +} while (0)
10515 +
10516 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10517 +       dwc_list_link_t *__prev__ = (list)->prev;               \
10518 +       (list)->prev = (link);                                  \
10519 +       (link)->next = (list);                                  \
10520 +       (link)->prev = __prev__;                                \
10521 +       __prev__->next = (link);                                \
10522 +} while (0)
10523 +#endif
10524 +
10525 +#if 0
10526 +static inline void __list_add(struct list_head *new,
10527 +                              struct list_head *prev,
10528 +                              struct list_head *next)
10529 +{
10530 +        next->prev = new;
10531 +        new->next = next;
10532 +        new->prev = prev;
10533 +        prev->next = new;
10534 +}
10535 +
10536 +static inline void list_add(struct list_head *new, struct list_head *head)
10537 +{
10538 +        __list_add(new, head, head->next);
10539 +}
10540 +
10541 +static inline void list_add_tail(struct list_head *new, struct list_head *head)
10542 +{
10543 +        __list_add(new, head->prev, head);
10544 +}
10545 +
10546 +static inline void __list_del(struct list_head * prev, struct list_head * next)
10547 +{
10548 +        next->prev = prev;
10549 +        prev->next = next;
10550 +}
10551 +
10552 +static inline void list_del(struct list_head *entry)
10553 +{
10554 +        __list_del(entry->prev, entry->next);
10555 +        entry->next = LIST_POISON1;
10556 +        entry->prev = LIST_POISON2;
10557 +}
10558 +#endif
10559 +
10560 +#define DWC_LIST_REMOVE(link) do {                             \
10561 +       (link)->next->prev = (link)->prev;                      \
10562 +       (link)->prev->next = (link)->next;                      \
10563 +} while (0)
10564 +
10565 +#define DWC_LIST_REMOVE_INIT(link) do {                                \
10566 +       DWC_LIST_REMOVE(link);                                  \
10567 +       DWC_LIST_INIT(link);                                    \
10568 +} while (0)
10569 +
10570 +#define DWC_LIST_MOVE_HEAD(list, link) do {                    \
10571 +       DWC_LIST_REMOVE(link);                                  \
10572 +       DWC_LIST_INSERT_HEAD(list, link);                       \
10573 +} while (0)
10574 +
10575 +#define DWC_LIST_MOVE_TAIL(list, link) do {                    \
10576 +       DWC_LIST_REMOVE(link);                                  \
10577 +       DWC_LIST_INSERT_TAIL(list, link);                       \
10578 +} while (0)
10579 +
10580 +#define DWC_LIST_FOREACH(var, list)                            \
10581 +       for((var) = DWC_LIST_FIRST(list);                       \
10582 +           (var) != DWC_LIST_END(list);                        \
10583 +           (var) = DWC_LIST_NEXT(var))
10584 +
10585 +#define DWC_LIST_FOREACH_SAFE(var, var2, list)                 \
10586 +       for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var);  \
10587 +           (var) != DWC_LIST_END(list);                        \
10588 +           (var) = (var2), (var2) = DWC_LIST_NEXT(var2))
10589 +
10590 +#define DWC_LIST_FOREACH_REVERSE(var, list)                    \
10591 +       for((var) = DWC_LIST_LAST(list);                        \
10592 +           (var) != DWC_LIST_END(list);                        \
10593 +           (var) = DWC_LIST_PREV(var))
10594 +
10595 +/*
10596 + * Singly-linked List definitions.
10597 + */
10598 +#define DWC_SLIST_HEAD(name, type)                                     \
10599 +struct name {                                                          \
10600 +       struct type *slh_first; /* first element */                     \
10601 +}
10602 +
10603 +#define DWC_SLIST_HEAD_INITIALIZER(head)                               \
10604 +       { NULL }
10605 +
10606 +#define DWC_SLIST_ENTRY(type)                                          \
10607 +struct {                                                               \
10608 +       struct type *sle_next;  /* next element */                      \
10609 +}
10610 +
10611 +/*
10612 + * Singly-linked List access methods.
10613 + */
10614 +#define DWC_SLIST_FIRST(head)  ((head)->slh_first)
10615 +#define DWC_SLIST_END(head)            NULL
10616 +#define DWC_SLIST_EMPTY(head)  (SLIST_FIRST(head) == SLIST_END(head))
10617 +#define DWC_SLIST_NEXT(elm, field)     ((elm)->field.sle_next)
10618 +
10619 +#define DWC_SLIST_FOREACH(var, head, field)                            \
10620 +       for((var) = SLIST_FIRST(head);                                  \
10621 +           (var) != SLIST_END(head);                                   \
10622 +           (var) = SLIST_NEXT(var, field))
10623 +
10624 +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)              \
10625 +       for((varp) = &SLIST_FIRST((head));                              \
10626 +           ((var) = *(varp)) != SLIST_END(head);                       \
10627 +           (varp) = &SLIST_NEXT((var), field))
10628 +
10629 +/*
10630 + * Singly-linked List functions.
10631 + */
10632 +#define DWC_SLIST_INIT(head) {                                         \
10633 +       SLIST_FIRST(head) = SLIST_END(head);                            \
10634 +}
10635 +
10636 +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {              \
10637 +       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
10638 +       (slistelm)->field.sle_next = (elm);                             \
10639 +} while (0)
10640 +
10641 +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {                   \
10642 +       (elm)->field.sle_next = (head)->slh_first;                      \
10643 +       (head)->slh_first = (elm);                                      \
10644 +} while (0)
10645 +
10646 +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {                   \
10647 +       (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
10648 +} while (0)
10649 +
10650 +#define DWC_SLIST_REMOVE_HEAD(head, field) do {                                \
10651 +       (head)->slh_first = (head)->slh_first->field.sle_next;          \
10652 +} while (0)
10653 +
10654 +#define DWC_SLIST_REMOVE(head, elm, type, field) do {                  \
10655 +       if ((head)->slh_first == (elm)) {                               \
10656 +               SLIST_REMOVE_HEAD((head), field);                       \
10657 +       }                                                               \
10658 +       else {                                                          \
10659 +               struct type *curelm = (head)->slh_first;                \
10660 +               while( curelm->field.sle_next != (elm) )                \
10661 +                       curelm = curelm->field.sle_next;                \
10662 +               curelm->field.sle_next =                                \
10663 +                   curelm->field.sle_next->field.sle_next;             \
10664 +       }                                                               \
10665 +} while (0)
10666 +
10667 +/*
10668 + * Simple queue definitions.
10669 + */
10670 +#define DWC_SIMPLEQ_HEAD(name, type)                                   \
10671 +struct name {                                                          \
10672 +       struct type *sqh_first; /* first element */                     \
10673 +       struct type **sqh_last; /* addr of last next element */         \
10674 +}
10675 +
10676 +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)                             \
10677 +       { NULL, &(head).sqh_first }
10678 +
10679 +#define DWC_SIMPLEQ_ENTRY(type)                                                \
10680 +struct {                                                               \
10681 +       struct type *sqe_next;  /* next element */                      \
10682 +}
10683 +
10684 +/*
10685 + * Simple queue access methods.
10686 + */
10687 +#define DWC_SIMPLEQ_FIRST(head)            ((head)->sqh_first)
10688 +#define DWC_SIMPLEQ_END(head)      NULL
10689 +#define DWC_SIMPLEQ_EMPTY(head)            (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
10690 +#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
10691 +
10692 +#define DWC_SIMPLEQ_FOREACH(var, head, field)                          \
10693 +       for((var) = SIMPLEQ_FIRST(head);                                \
10694 +           (var) != SIMPLEQ_END(head);                                 \
10695 +           (var) = SIMPLEQ_NEXT(var, field))
10696 +
10697 +/*
10698 + * Simple queue functions.
10699 + */
10700 +#define DWC_SIMPLEQ_INIT(head) do {                                    \
10701 +       (head)->sqh_first = NULL;                                       \
10702 +       (head)->sqh_last = &(head)->sqh_first;                          \
10703 +} while (0)
10704 +
10705 +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {                 \
10706 +       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
10707 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10708 +       (head)->sqh_first = (elm);                                      \
10709 +} while (0)
10710 +
10711 +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {                 \
10712 +       (elm)->field.sqe_next = NULL;                                   \
10713 +       *(head)->sqh_last = (elm);                                      \
10714 +       (head)->sqh_last = &(elm)->field.sqe_next;                      \
10715 +} while (0)
10716 +
10717 +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10718 +       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
10719 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10720 +       (listelm)->field.sqe_next = (elm);                              \
10721 +} while (0)
10722 +
10723 +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {                      \
10724 +       if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
10725 +               (head)->sqh_last = &(head)->sqh_first;                  \
10726 +} while (0)
10727 +
10728 +/*
10729 + * Tail queue definitions.
10730 + */
10731 +#define DWC_TAILQ_HEAD(name, type)                                     \
10732 +struct name {                                                          \
10733 +       struct type *tqh_first; /* first element */                     \
10734 +       struct type **tqh_last; /* addr of last next element */         \
10735 +}
10736 +
10737 +#define DWC_TAILQ_HEAD_INITIALIZER(head)                               \
10738 +       { NULL, &(head).tqh_first }
10739 +
10740 +#define DWC_TAILQ_ENTRY(type)                                          \
10741 +struct {                                                               \
10742 +       struct type *tqe_next;  /* next element */                      \
10743 +       struct type **tqe_prev; /* address of previous next element */  \
10744 +}
10745 +
10746 +/*
10747 + * tail queue access methods
10748 + */
10749 +#define DWC_TAILQ_FIRST(head)          ((head)->tqh_first)
10750 +#define DWC_TAILQ_END(head)            NULL
10751 +#define DWC_TAILQ_NEXT(elm, field)     ((elm)->field.tqe_next)
10752 +#define DWC_TAILQ_LAST(head, headname)                                 \
10753 +       (*(((struct headname *)((head)->tqh_last))->tqh_last))
10754 +/* XXX */
10755 +#define DWC_TAILQ_PREV(elm, headname, field)                           \
10756 +       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
10757 +#define DWC_TAILQ_EMPTY(head)                                          \
10758 +       (TAILQ_FIRST(head) == TAILQ_END(head))
10759 +
10760 +#define DWC_TAILQ_FOREACH(var, head, field)                            \
10761 +       for((var) = TAILQ_FIRST(head);                                  \
10762 +           (var) != TAILQ_END(head);                                   \
10763 +           (var) = TAILQ_NEXT(var, field))
10764 +
10765 +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)          \
10766 +       for((var) = TAILQ_LAST(head, headname);                         \
10767 +           (var) != TAILQ_END(head);                                   \
10768 +           (var) = TAILQ_PREV(var, headname, field))
10769 +
10770 +/*
10771 + * Tail queue functions.
10772 + */
10773 +#define DWC_TAILQ_INIT(head) do {                                      \
10774 +       (head)->tqh_first = NULL;                                       \
10775 +       (head)->tqh_last = &(head)->tqh_first;                          \
10776 +} while (0)
10777 +
10778 +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {                   \
10779 +       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
10780 +               (head)->tqh_first->field.tqe_prev =                     \
10781 +                   &(elm)->field.tqe_next;                             \
10782 +       else                                                            \
10783 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10784 +       (head)->tqh_first = (elm);                                      \
10785 +       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
10786 +} while (0)
10787 +
10788 +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {                   \
10789 +       (elm)->field.tqe_next = NULL;                                   \
10790 +       (elm)->field.tqe_prev = (head)->tqh_last;                       \
10791 +       *(head)->tqh_last = (elm);                                      \
10792 +       (head)->tqh_last = &(elm)->field.tqe_next;                      \
10793 +} while (0)
10794 +
10795 +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {         \
10796 +       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
10797 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10798 +                   &(elm)->field.tqe_next;                             \
10799 +       else                                                            \
10800 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10801 +       (listelm)->field.tqe_next = (elm);                              \
10802 +       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
10803 +} while (0)
10804 +
10805 +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {              \
10806 +       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
10807 +       (elm)->field.tqe_next = (listelm);                              \
10808 +       *(listelm)->field.tqe_prev = (elm);                             \
10809 +       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
10810 +} while (0)
10811 +
10812 +#define DWC_TAILQ_REMOVE(head, elm, field) do {                                \
10813 +       if (((elm)->field.tqe_next) != NULL)                            \
10814 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10815 +                   (elm)->field.tqe_prev;                              \
10816 +       else                                                            \
10817 +               (head)->tqh_last = (elm)->field.tqe_prev;               \
10818 +       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
10819 +} while (0)
10820 +
10821 +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {                 \
10822 +       if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
10823 +               (elm2)->field.tqe_next->field.tqe_prev =                \
10824 +                   &(elm2)->field.tqe_next;                            \
10825 +       else                                                            \
10826 +               (head)->tqh_last = &(elm2)->field.tqe_next;             \
10827 +       (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
10828 +       *(elm2)->field.tqe_prev = (elm2);                               \
10829 +} while (0)
10830 +
10831 +/*
10832 + * Circular queue definitions.
10833 + */
10834 +#define DWC_CIRCLEQ_HEAD(name, type)                                   \
10835 +struct name {                                                          \
10836 +       struct type *cqh_first;         /* first element */             \
10837 +       struct type *cqh_last;          /* last element */              \
10838 +}
10839 +
10840 +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)                             \
10841 +       { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
10842 +
10843 +#define DWC_CIRCLEQ_ENTRY(type)                                                \
10844 +struct {                                                               \
10845 +       struct type *cqe_next;          /* next element */              \
10846 +       struct type *cqe_prev;          /* previous element */          \
10847 +}
10848 +
10849 +/*
10850 + * Circular queue access methods
10851 + */
10852 +#define DWC_CIRCLEQ_FIRST(head)                ((head)->cqh_first)
10853 +#define DWC_CIRCLEQ_LAST(head)         ((head)->cqh_last)
10854 +#define DWC_CIRCLEQ_END(head)          ((void *)(head))
10855 +#define DWC_CIRCLEQ_NEXT(elm, field)   ((elm)->field.cqe_next)
10856 +#define DWC_CIRCLEQ_PREV(elm, field)   ((elm)->field.cqe_prev)
10857 +#define DWC_CIRCLEQ_EMPTY(head)                                                \
10858 +       (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
10859 +
10860 +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
10861 +
10862 +#define DWC_CIRCLEQ_FOREACH(var, head, field)                          \
10863 +       for((var) = DWC_CIRCLEQ_FIRST(head);                            \
10864 +           (var) != DWC_CIRCLEQ_END(head);                             \
10865 +           (var) = DWC_CIRCLEQ_NEXT(var, field))
10866 +
10867 +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)                       \
10868 +       for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \
10869 +           (var) != DWC_CIRCLEQ_END(head);                                     \
10870 +           (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
10871 +
10872 +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)                  \
10873 +       for((var) = DWC_CIRCLEQ_LAST(head);                             \
10874 +           (var) != DWC_CIRCLEQ_END(head);                             \
10875 +           (var) = DWC_CIRCLEQ_PREV(var, field))
10876 +
10877 +/*
10878 + * Circular queue functions.
10879 + */
10880 +#define DWC_CIRCLEQ_INIT(head) do {                                    \
10881 +       (head)->cqh_first = DWC_CIRCLEQ_END(head);                      \
10882 +       (head)->cqh_last = DWC_CIRCLEQ_END(head);                       \
10883 +} while (0)
10884 +
10885 +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do {                                \
10886 +       (elm)->field.cqe_next = NULL;                                   \
10887 +       (elm)->field.cqe_prev = NULL;                                   \
10888 +} while (0)
10889 +
10890 +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10891 +       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
10892 +       (elm)->field.cqe_prev = (listelm);                              \
10893 +       if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))         \
10894 +               (head)->cqh_last = (elm);                               \
10895 +       else                                                            \
10896 +               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
10897 +       (listelm)->field.cqe_next = (elm);                              \
10898 +} while (0)
10899 +
10900 +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {      \
10901 +       (elm)->field.cqe_next = (listelm);                              \
10902 +       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
10903 +       if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))         \
10904 +               (head)->cqh_first = (elm);                              \
10905 +       else                                                            \
10906 +               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
10907 +       (listelm)->field.cqe_prev = (elm);                              \
10908 +} while (0)
10909 +
10910 +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {                 \
10911 +       (elm)->field.cqe_next = (head)->cqh_first;                      \
10912 +       (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);                  \
10913 +       if ((head)->cqh_last == DWC_CIRCLEQ_END(head))                  \
10914 +               (head)->cqh_last = (elm);                               \
10915 +       else                                                            \
10916 +               (head)->cqh_first->field.cqe_prev = (elm);              \
10917 +       (head)->cqh_first = (elm);                                      \
10918 +} while (0)
10919 +
10920 +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {                 \
10921 +       (elm)->field.cqe_next = DWC_CIRCLEQ_END(head);                  \
10922 +       (elm)->field.cqe_prev = (head)->cqh_last;                       \
10923 +       if ((head)->cqh_first == DWC_CIRCLEQ_END(head))                 \
10924 +               (head)->cqh_first = (elm);                              \
10925 +       else                                                            \
10926 +               (head)->cqh_last->field.cqe_next = (elm);               \
10927 +       (head)->cqh_last = (elm);                                       \
10928 +} while (0)
10929 +
10930 +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {                      \
10931 +       if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))             \
10932 +               (head)->cqh_last = (elm)->field.cqe_prev;               \
10933 +       else                                                            \
10934 +               (elm)->field.cqe_next->field.cqe_prev =                 \
10935 +                   (elm)->field.cqe_prev;                              \
10936 +       if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))             \
10937 +               (head)->cqh_first = (elm)->field.cqe_next;              \
10938 +       else                                                            \
10939 +               (elm)->field.cqe_prev->field.cqe_next =                 \
10940 +                   (elm)->field.cqe_next;                              \
10941 +} while (0)
10942 +
10943 +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do {                 \
10944 +       DWC_CIRCLEQ_REMOVE(head, elm, field);                           \
10945 +       DWC_CIRCLEQ_INIT_ENTRY(elm, field);                             \
10946 +} while (0)
10947 +
10948 +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {               \
10949 +       if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
10950 +           DWC_CIRCLEQ_END(head))                                      \
10951 +               (head).cqh_last = (elm2);                               \
10952 +       else                                                            \
10953 +               (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
10954 +       if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
10955 +           DWC_CIRCLEQ_END(head))                                      \
10956 +               (head).cqh_first = (elm2);                              \
10957 +       else                                                            \
10958 +               (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
10959 +} while (0)
10960 +
10961 +#ifdef __cplusplus
10962 +}
10963 +#endif
10964 +
10965 +#endif /* _DWC_LIST_H_ */
10966 diff --git a/drivers/usb/host/dwc_common_port/dwc_mem.c b/drivers/usb/host/dwc_common_port/dwc_mem.c
10967 new file mode 100644
10968 index 0000000..ad645ff
10969 --- /dev/null
10970 +++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
10971 @@ -0,0 +1,245 @@
10972 +/* Memory Debugging */
10973 +#ifdef DWC_DEBUG_MEMORY
10974 +
10975 +#include "dwc_os.h"
10976 +#include "dwc_list.h"
10977 +
10978 +struct allocation {
10979 +       void *addr;
10980 +       void *ctx;
10981 +       char *func;
10982 +       int line;
10983 +       uint32_t size;
10984 +       int dma;
10985 +       DWC_CIRCLEQ_ENTRY(allocation) entry;
10986 +};
10987 +
10988 +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
10989 +
10990 +struct allocation_manager {
10991 +       void *mem_ctx;
10992 +       struct allocation_queue allocations;
10993 +
10994 +       /* statistics */
10995 +       int num;
10996 +       int num_freed;
10997 +       int num_active;
10998 +       uint32_t total;
10999 +       uint32_t cur;
11000 +       uint32_t max;
11001 +};
11002 +
11003 +static struct allocation_manager *manager = NULL;
11004 +
11005 +static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
11006 +                         int dma)
11007 +{
11008 +       struct allocation *a;
11009 +
11010 +       DWC_ASSERT(manager != NULL, "manager not allocated");
11011 +
11012 +       a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
11013 +       if (!a) {
11014 +               return -DWC_E_NO_MEMORY;
11015 +       }
11016 +
11017 +       a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
11018 +       if (!a->func) {
11019 +               __DWC_FREE(manager->mem_ctx, a);
11020 +               return -DWC_E_NO_MEMORY;
11021 +       }
11022 +
11023 +       DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
11024 +       a->addr = addr;
11025 +       a->ctx = ctx;
11026 +       a->line = line;
11027 +       a->size = size;
11028 +       a->dma = dma;
11029 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
11030 +
11031 +       /* Update stats */
11032 +       manager->num++;
11033 +       manager->num_active++;
11034 +       manager->total += size;
11035 +       manager->cur += size;
11036 +
11037 +       if (manager->max < manager->cur) {
11038 +               manager->max = manager->cur;
11039 +       }
11040 +
11041 +       return 0;
11042 +}
11043 +
11044 +static struct allocation *find_allocation(void *ctx, void *addr)
11045 +{
11046 +       struct allocation *a;
11047 +
11048 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11049 +               if (a->ctx == ctx && a->addr == addr) {
11050 +                       return a;
11051 +               }
11052 +       }
11053 +
11054 +       return NULL;
11055 +}
11056 +
11057 +static void free_allocation(void *ctx, void *addr, char const *func, int line)
11058 +{
11059 +       struct allocation *a = find_allocation(ctx, addr);
11060 +
11061 +       if (!a) {
11062 +               DWC_ASSERT(0,
11063 +                          "Free of address %p that was never allocated or already freed %s:%d",
11064 +                          addr, func, line);
11065 +               return;
11066 +       }
11067 +
11068 +       DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
11069 +
11070 +       manager->num_active--;
11071 +       manager->num_freed++;
11072 +       manager->cur -= a->size;
11073 +       __DWC_FREE(manager->mem_ctx, a->func);
11074 +       __DWC_FREE(manager->mem_ctx, a);
11075 +}
11076 +
11077 +int dwc_memory_debug_start(void *mem_ctx)
11078 +{
11079 +       DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
11080 +
11081 +       if (manager) {
11082 +               return -DWC_E_BUSY;
11083 +       }
11084 +
11085 +       manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
11086 +       if (!manager) {
11087 +               return -DWC_E_NO_MEMORY;
11088 +       }
11089 +
11090 +       DWC_CIRCLEQ_INIT(&manager->allocations);
11091 +       manager->mem_ctx = mem_ctx;
11092 +       manager->num = 0;
11093 +       manager->num_freed = 0;
11094 +       manager->num_active = 0;
11095 +       manager->total = 0;
11096 +       manager->cur = 0;
11097 +       manager->max = 0;
11098 +
11099 +       return 0;
11100 +}
11101 +
11102 +void dwc_memory_debug_stop(void)
11103 +{
11104 +       struct allocation *a;
11105 +
11106 +       dwc_memory_debug_report();
11107 +
11108 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11109 +               DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
11110 +               free_allocation(a->ctx, a->addr, NULL, -1);
11111 +       }
11112 +
11113 +       __DWC_FREE(manager->mem_ctx, manager);
11114 +}
11115 +
11116 +void dwc_memory_debug_report(void)
11117 +{
11118 +       struct allocation *a;
11119 +
11120 +       DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
11121 +       DWC_PRINTF("Num Allocations = %d\n", manager->num);
11122 +       DWC_PRINTF("Freed = %d\n", manager->num_freed);
11123 +       DWC_PRINTF("Active = %d\n", manager->num_active);
11124 +       DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
11125 +       DWC_PRINTF("Total Memory Used = %d\n", manager->total);
11126 +       DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
11127 +       DWC_PRINTF("Unfreed allocations:\n");
11128 +
11129 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11130 +               DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n",
11131 +                          a->addr, a->size, a->func, a->line, a->dma);
11132 +       }
11133 +}
11134 +
11135 +/* The replacement functions */
11136 +void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
11137 +{
11138 +       void *addr = __DWC_ALLOC(mem_ctx, size);
11139 +
11140 +       if (!addr) {
11141 +               return NULL;
11142 +       }
11143 +
11144 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11145 +               __DWC_FREE(mem_ctx, addr);
11146 +               return NULL;
11147 +       }
11148 +
11149 +       return addr;
11150 +}
11151 +
11152 +void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
11153 +                            int line)
11154 +{
11155 +       void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);
11156 +
11157 +       if (!addr) {
11158 +               return NULL;
11159 +       }
11160 +
11161 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11162 +               __DWC_FREE(mem_ctx, addr);
11163 +               return NULL;
11164 +       }
11165 +
11166 +       return addr;
11167 +}
11168 +
11169 +void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)
11170 +{
11171 +       free_allocation(mem_ctx, addr, func, line);
11172 +       __DWC_FREE(mem_ctx, addr);
11173 +}
11174 +
11175 +void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
11176 +                         char const *func, int line)
11177 +{
11178 +       void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
11179 +
11180 +       if (!addr) {
11181 +               return NULL;
11182 +       }
11183 +
11184 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11185 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11186 +               return NULL;
11187 +       }
11188 +
11189 +       return addr;
11190 +}
11191 +
11192 +void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
11193 +                                dwc_dma_t *dma_addr, char const *func, int line)
11194 +{
11195 +       void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);
11196 +
11197 +       if (!addr) {
11198 +               return NULL;
11199 +       }
11200 +
11201 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11202 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11203 +               return NULL;
11204 +       }
11205 +
11206 +       return addr;
11207 +}
11208 +
11209 +void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
11210 +                       dwc_dma_t dma_addr, char const *func, int line)
11211 +{
11212 +       free_allocation(dma_ctx, virt_addr, func, line);
11213 +       __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
11214 +}
11215 +
11216 +#endif /* DWC_DEBUG_MEMORY */
11217 diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.c b/drivers/usb/host/dwc_common_port/dwc_modpow.c
11218 new file mode 100644
11219 index 0000000..2004538
11220 --- /dev/null
11221 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
11222 @@ -0,0 +1,636 @@
11223 +/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.
11224 + *
11225 + * PuTTY is copyright 1997-2007 Simon Tatham.
11226 + *
11227 + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
11228 + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
11229 + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
11230 + * Kuhn, and CORE SDI S.A.
11231 + *
11232 + * Permission is hereby granted, free of charge, to any person
11233 + * obtaining a copy of this software and associated documentation files
11234 + * (the "Software"), to deal in the Software without restriction,
11235 + * including without limitation the rights to use, copy, modify, merge,
11236 + * publish, distribute, sublicense, and/or sell copies of the Software,
11237 + * and to permit persons to whom the Software is furnished to do so,
11238 + * subject to the following conditions:
11239 + *
11240 + * The above copyright notice and this permission notice shall be
11241 + * included in all copies or substantial portions of the Software.
11242 +
11243 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11244 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11245 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11246 + * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
11247 + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
11248 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
11249 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11250 + *
11251 + */
11252 +#ifdef DWC_CRYPTOLIB
11253 +
11254 +#ifndef CONFIG_MACH_IPMATE
11255 +
11256 +#include "dwc_modpow.h"
11257 +
11258 +#define BIGNUM_INT_MASK  0xFFFFFFFFUL
11259 +#define BIGNUM_TOP_BIT   0x80000000UL
11260 +#define BIGNUM_INT_BITS  32
11261 +
11262 +
11263 +static void *snmalloc(void *mem_ctx, size_t n, size_t size)
11264 +{
11265 +    void *p;
11266 +    size *= n;
11267 +    if (size == 0) size = 1;
11268 +    p = dwc_alloc(mem_ctx, size);
11269 +    return p;
11270 +}
11271 +
11272 +#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))
11273 +#define sfree dwc_free
11274 +
11275 +/*
11276 + * Usage notes:
11277 + *  * Do not call the DIVMOD_WORD macro with expressions such as array
11278 + *    subscripts, as some implementations object to this (see below).
11279 + *  * Note that none of the division methods below will cope if the
11280 + *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
11281 + *    to avoid this case.
11282 + *    If this condition occurs, in the case of the x86 DIV instruction,
11283 + *    an overflow exception will occur, which (according to a correspondent)
11284 + *    will manifest on Windows as something like
11285 + *      0xC0000095: Integer overflow
11286 + *    The C variant won't give the right answer, either.
11287 + */
11288 +
11289 +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
11290 +
11291 +#if defined __GNUC__ && defined __i386__
11292 +#define DIVMOD_WORD(q, r, hi, lo, w) \
11293 +    __asm__("div %2" : \
11294 +           "=d" (r), "=a" (q) : \
11295 +           "r" (w), "d" (hi), "a" (lo))
11296 +#else
11297 +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
11298 +    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
11299 +    q = n / w; \
11300 +    r = n % w; \
11301 +} while (0)
11302 +#endif
11303 +
11304 +//    q = n / w;
11305 +//    r = n % w;
11306 +
11307 +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
11308 +
11309 +#define BIGNUM_INTERNAL
11310 +
11311 +static Bignum newbn(void *mem_ctx, int length)
11312 +{
11313 +    Bignum b = snewn(mem_ctx, length + 1, BignumInt);
11314 +    //if (!b)
11315 +    //abort();                /* FIXME */
11316 +    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
11317 +    b[0] = length;
11318 +    return b;
11319 +}
11320 +
11321 +void freebn(void *mem_ctx, Bignum b)
11322 +{
11323 +    /*
11324 +     * Burn the evidence, just in case.
11325 +     */
11326 +    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
11327 +    sfree(mem_ctx, b);
11328 +}
11329 +
11330 +/*
11331 + * Compute c = a * b.
11332 + * Input is in the first len words of a and b.
11333 + * Result is returned in the first 2*len words of c.
11334 + */
11335 +static void internal_mul(BignumInt *a, BignumInt *b,
11336 +                        BignumInt *c, int len)
11337 +{
11338 +    int i, j;
11339 +    BignumDblInt t;
11340 +
11341 +    for (j = 0; j < 2 * len; j++)
11342 +       c[j] = 0;
11343 +
11344 +    for (i = len - 1; i >= 0; i--) {
11345 +       t = 0;
11346 +       for (j = len - 1; j >= 0; j--) {
11347 +           t += MUL_WORD(a[i], (BignumDblInt) b[j]);
11348 +           t += (BignumDblInt) c[i + j + 1];
11349 +           c[i + j + 1] = (BignumInt) t;
11350 +           t = t >> BIGNUM_INT_BITS;
11351 +       }
11352 +       c[i] = (BignumInt) t;
11353 +    }
11354 +}
11355 +
11356 +static void internal_add_shifted(BignumInt *number,
11357 +                                unsigned n, int shift)
11358 +{
11359 +    int word = 1 + (shift / BIGNUM_INT_BITS);
11360 +    int bshift = shift % BIGNUM_INT_BITS;
11361 +    BignumDblInt addend;
11362 +
11363 +    addend = (BignumDblInt)n << bshift;
11364 +
11365 +    while (addend) {
11366 +       addend += number[word];
11367 +       number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
11368 +       addend >>= BIGNUM_INT_BITS;
11369 +       word++;
11370 +    }
11371 +}
11372 +
11373 +/*
11374 + * Compute a = a % m.
11375 + * Input in first alen words of a and first mlen words of m.
11376 + * Output in first alen words of a
11377 + * (of which first alen-mlen words will be zero).
11378 + * The MSW of m MUST have its high bit set.
11379 + * Quotient is accumulated in the `quotient' array, which is a Bignum
11380 + * rather than the internal bigendian format. Quotient parts are shifted
11381 + * left by `qshift' before adding into quot.
11382 + */
11383 +static void internal_mod(BignumInt *a, int alen,
11384 +                        BignumInt *m, int mlen,
11385 +                        BignumInt *quot, int qshift)
11386 +{
11387 +    BignumInt m0, m1;
11388 +    unsigned int h;
11389 +    int i, k;
11390 +
11391 +    m0 = m[0];
11392 +    if (mlen > 1)
11393 +       m1 = m[1];
11394 +    else
11395 +       m1 = 0;
11396 +
11397 +    for (i = 0; i <= alen - mlen; i++) {
11398 +       BignumDblInt t;
11399 +       unsigned int q, r, c, ai1;
11400 +
11401 +       if (i == 0) {
11402 +           h = 0;
11403 +       } else {
11404 +           h = a[i - 1];
11405 +           a[i - 1] = 0;
11406 +       }
11407 +
11408 +       if (i == alen - 1)
11409 +           ai1 = 0;
11410 +       else
11411 +           ai1 = a[i + 1];
11412 +
11413 +       /* Find q = h:a[i] / m0 */
11414 +       if (h >= m0) {
11415 +           /*
11416 +            * Special case.
11417 +            *
11418 +            * To illustrate it, suppose a BignumInt is 8 bits, and
11419 +            * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
11420 +            * our initial division will be 0xA123 / 0xA1, which
11421 +            * will give a quotient of 0x100 and a divide overflow.
11422 +            * However, the invariants in this division algorithm
11423 +            * are not violated, since the full number A1:23:... is
11424 +            * _less_ than the quotient prefix A1:B2:... and so the
11425 +            * following correction loop would have sorted it out.
11426 +            *
11427 +            * In this situation we set q to be the largest
11428 +            * quotient we _can_ stomach (0xFF, of course).
11429 +            */
11430 +           q = BIGNUM_INT_MASK;
11431 +       } else {
11432 +           /* Macro doesn't want an array subscript expression passed
11433 +            * into it (see definition), so use a temporary. */
11434 +           BignumInt tmplo = a[i];
11435 +           DIVMOD_WORD(q, r, h, tmplo, m0);
11436 +
11437 +           /* Refine our estimate of q by looking at
11438 +            h:a[i]:a[i+1] / m0:m1 */
11439 +           t = MUL_WORD(m1, q);
11440 +           if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
11441 +               q--;
11442 +               t -= m1;
11443 +               r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */
11444 +               if (r >= (BignumDblInt) m0 &&
11445 +                   t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
11446 +           }
11447 +       }
11448 +
11449 +       /* Subtract q * m from a[i...] */
11450 +       c = 0;
11451 +       for (k = mlen - 1; k >= 0; k--) {
11452 +           t = MUL_WORD(q, m[k]);
11453 +           t += c;
11454 +           c = (unsigned)(t >> BIGNUM_INT_BITS);
11455 +           if ((BignumInt) t > a[i + k])
11456 +               c++;
11457 +           a[i + k] -= (BignumInt) t;
11458 +       }
11459 +
11460 +       /* Add back m in case of borrow */
11461 +       if (c != h) {
11462 +           t = 0;
11463 +           for (k = mlen - 1; k >= 0; k--) {
11464 +               t += m[k];
11465 +               t += a[i + k];
11466 +               a[i + k] = (BignumInt) t;
11467 +               t = t >> BIGNUM_INT_BITS;
11468 +           }
11469 +           q--;
11470 +       }
11471 +       if (quot)
11472 +           internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
11473 +    }
11474 +}
11475 +
11476 +/*
11477 + * Compute p % mod.
11478 + * The most significant word of mod MUST be non-zero.
11479 + * We assume that the result array is the same size as the mod array.
11480 + * We optionally write out a quotient if `quotient' is non-NULL.
11481 + * We can avoid writing out the result if `result' is NULL.
11482 + */
11483 +void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)
11484 +{
11485 +    BignumInt *n, *m;
11486 +    int mshift;
11487 +    int plen, mlen, i, j;
11488 +
11489 +    /* Allocate m of size mlen, copy mod to m */
11490 +    /* We use big endian internally */
11491 +    mlen = mod[0];
11492 +    m = snewn(mem_ctx, mlen, BignumInt);
11493 +    //if (!m)
11494 +    //abort();                /* FIXME */
11495 +    for (j = 0; j < mlen; j++)
11496 +       m[j] = mod[mod[0] - j];
11497 +
11498 +    /* Shift m left to make msb bit set */
11499 +    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
11500 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11501 +           break;
11502 +    if (mshift) {
11503 +       for (i = 0; i < mlen - 1; i++)
11504 +           m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
11505 +       m[mlen - 1] = m[mlen - 1] << mshift;
11506 +    }
11507 +
11508 +    plen = p[0];
11509 +    /* Ensure plen > mlen */
11510 +    if (plen <= mlen)
11511 +       plen = mlen + 1;
11512 +
11513 +    /* Allocate n of size plen, copy p to n */
11514 +    n = snewn(mem_ctx, plen, BignumInt);
11515 +    //if (!n)
11516 +    //abort();                /* FIXME */
11517 +    for (j = 0; j < plen; j++)
11518 +       n[j] = 0;
11519 +    for (j = 1; j <= (int)p[0]; j++)
11520 +       n[plen - j] = p[j];
11521 +
11522 +    /* Main computation */
11523 +    internal_mod(n, plen, m, mlen, quotient, mshift);
11524 +
11525 +    /* Fixup result in case the modulus was shifted */
11526 +    if (mshift) {
11527 +       for (i = plen - mlen - 1; i < plen - 1; i++)
11528 +           n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
11529 +       n[plen - 1] = n[plen - 1] << mshift;
11530 +       internal_mod(n, plen, m, mlen, quotient, 0);
11531 +       for (i = plen - 1; i >= plen - mlen; i--)
11532 +           n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
11533 +    }
11534 +
11535 +    /* Copy result to buffer */
11536 +    if (result) {
11537 +       for (i = 1; i <= (int)result[0]; i++) {
11538 +           int j = plen - i;
11539 +           result[i] = j >= 0 ? n[j] : 0;
11540 +       }
11541 +    }
11542 +
11543 +    /* Free temporary arrays */
11544 +    for (i = 0; i < mlen; i++)
11545 +       m[i] = 0;
11546 +    sfree(mem_ctx, m);
11547 +    for (i = 0; i < plen; i++)
11548 +       n[i] = 0;
11549 +    sfree(mem_ctx, n);
11550 +}
11551 +
11552 +/*
11553 + * Simple remainder.
11554 + */
11555 +Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)
11556 +{
11557 +    Bignum r = newbn(mem_ctx, b[0]);
11558 +    bigdivmod(mem_ctx, a, b, r, NULL);
11559 +    return r;
11560 +}
11561 +
11562 +/*
11563 + * Compute (base ^ exp) % mod.
11564 + */
11565 +Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)
11566 +{
11567 +    BignumInt *a, *b, *n, *m;
11568 +    int mshift;
11569 +    int mlen, i, j;
11570 +    Bignum base, result;
11571 +
11572 +    /*
11573 +     * The most significant word of mod needs to be non-zero. It
11574 +     * should already be, but let's make sure.
11575 +     */
11576 +    //assert(mod[mod[0]] != 0);
11577 +
11578 +    /*
11579 +     * Make sure the base is smaller than the modulus, by reducing
11580 +     * it modulo the modulus if not.
11581 +     */
11582 +    base = bigmod(mem_ctx, base_in, mod);
11583 +
11584 +    /* Allocate m of size mlen, copy mod to m */
11585 +    /* We use big endian internally */
11586 +    mlen = mod[0];
11587 +    m = snewn(mem_ctx, mlen, BignumInt);
11588 +    //if (!m)
11589 +    //abort();                /* FIXME */
11590 +    for (j = 0; j < mlen; j++)
11591 +       m[j] = mod[mod[0] - j];
11592 +
11593 +    /* Shift m left to make msb bit set */
11594 +    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
11595 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11596 +           break;
11597 +    if (mshift) {
11598 +       for (i = 0; i < mlen - 1; i++)
11599 +           m[i] =
11600 +               (m[i] << mshift) | (m[i + 1] >>
11601 +                                   (BIGNUM_INT_BITS - mshift));
11602 +       m[mlen - 1] = m[mlen - 1] << mshift;
11603 +    }
11604 +
11605 +    /* Allocate n of size mlen, copy base to n */
11606 +    n = snewn(mem_ctx, mlen, BignumInt);
11607 +    //if (!n)
11608 +    //abort();                /* FIXME */
11609 +    i = mlen - base[0];
11610 +    for (j = 0; j < i; j++)
11611 +       n[j] = 0;
11612 +    for (j = 0; j < base[0]; j++)
11613 +       n[i + j] = base[base[0] - j];
11614 +
11615 +    /* Allocate a and b of size 2*mlen. Set a = 1 */
11616 +    a = snewn(mem_ctx, 2 * mlen, BignumInt);
11617 +    //if (!a)
11618 +    //abort();                /* FIXME */
11619 +    b = snewn(mem_ctx, 2 * mlen, BignumInt);
11620 +    //if (!b)
11621 +    //abort();                /* FIXME */
11622 +    for (i = 0; i < 2 * mlen; i++)
11623 +       a[i] = 0;
11624 +    a[2 * mlen - 1] = 1;
11625 +
11626 +    /* Skip leading zero bits of exp. */
11627 +    i = 0;
11628 +    j = BIGNUM_INT_BITS - 1;
11629 +    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
11630 +       j--;
11631 +       if (j < 0) {
11632 +           i++;
11633 +           j = BIGNUM_INT_BITS - 1;
11634 +       }
11635 +    }
11636 +
11637 +    /* Main computation */
11638 +    while (i < exp[0]) {
11639 +       while (j >= 0) {
11640 +           internal_mul(a + mlen, a + mlen, b, mlen);
11641 +           internal_mod(b, mlen * 2, m, mlen, NULL, 0);
11642 +           if ((exp[exp[0] - i] & (1 << j)) != 0) {
11643 +               internal_mul(b + mlen, n, a, mlen);
11644 +               internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11645 +           } else {
11646 +               BignumInt *t;
11647 +               t = a;
11648 +               a = b;
11649 +               b = t;
11650 +           }
11651 +           j--;
11652 +       }
11653 +       i++;
11654 +       j = BIGNUM_INT_BITS - 1;
11655 +    }
11656 +
11657 +    /* Fixup result in case the modulus was shifted */
11658 +    if (mshift) {
11659 +       for (i = mlen - 1; i < 2 * mlen - 1; i++)
11660 +           a[i] =
11661 +               (a[i] << mshift) | (a[i + 1] >>
11662 +                                   (BIGNUM_INT_BITS - mshift));
11663 +       a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
11664 +       internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11665 +       for (i = 2 * mlen - 1; i >= mlen; i--)
11666 +           a[i] =
11667 +               (a[i] >> mshift) | (a[i - 1] <<
11668 +                                   (BIGNUM_INT_BITS - mshift));
11669 +    }
11670 +
11671 +    /* Copy result to buffer */
11672 +    result = newbn(mem_ctx, mod[0]);
11673 +    for (i = 0; i < mlen; i++)
11674 +       result[result[0] - i] = a[i + mlen];
11675 +    while (result[0] > 1 && result[result[0]] == 0)
11676 +       result[0]--;
11677 +
11678 +    /* Free temporary arrays */
11679 +    for (i = 0; i < 2 * mlen; i++)
11680 +       a[i] = 0;
11681 +    sfree(mem_ctx, a);
11682 +    for (i = 0; i < 2 * mlen; i++)
11683 +       b[i] = 0;
11684 +    sfree(mem_ctx, b);
11685 +    for (i = 0; i < mlen; i++)
11686 +       m[i] = 0;
11687 +    sfree(mem_ctx, m);
11688 +    for (i = 0; i < mlen; i++)
11689 +       n[i] = 0;
11690 +    sfree(mem_ctx, n);
11691 +
11692 +    freebn(mem_ctx, base);
11693 +
11694 +    return result;
11695 +}
11696 +
11697 +
11698 +#ifdef UNITTEST
11699 +
11700 +static __u32 dh_p[] = {
11701 +       96,
11702 +       0xFFFFFFFF,
11703 +       0xFFFFFFFF,
11704 +       0xA93AD2CA,
11705 +       0x4B82D120,
11706 +       0xE0FD108E,
11707 +       0x43DB5BFC,
11708 +       0x74E5AB31,
11709 +       0x08E24FA0,
11710 +       0xBAD946E2,
11711 +       0x770988C0,
11712 +       0x7A615D6C,
11713 +       0xBBE11757,
11714 +       0x177B200C,
11715 +       0x521F2B18,
11716 +       0x3EC86A64,
11717 +       0xD8760273,
11718 +       0xD98A0864,
11719 +       0xF12FFA06,
11720 +       0x1AD2EE6B,
11721 +       0xCEE3D226,
11722 +       0x4A25619D,
11723 +       0x1E8C94E0,
11724 +       0xDB0933D7,
11725 +       0xABF5AE8C,
11726 +       0xA6E1E4C7,
11727 +       0xB3970F85,
11728 +       0x5D060C7D,
11729 +       0x8AEA7157,
11730 +       0x58DBEF0A,
11731 +       0xECFB8504,
11732 +       0xDF1CBA64,
11733 +       0xA85521AB,
11734 +       0x04507A33,
11735 +       0xAD33170D,
11736 +       0x8AAAC42D,
11737 +       0x15728E5A,
11738 +       0x98FA0510,
11739 +       0x15D22618,
11740 +       0xEA956AE5,
11741 +       0x3995497C,
11742 +       0x95581718,
11743 +       0xDE2BCBF6,
11744 +       0x6F4C52C9,
11745 +       0xB5C55DF0,
11746 +       0xEC07A28F,
11747 +       0x9B2783A2,
11748 +       0x180E8603,
11749 +       0xE39E772C,
11750 +       0x2E36CE3B,
11751 +       0x32905E46,
11752 +       0xCA18217C,
11753 +       0xF1746C08,
11754 +       0x4ABC9804,
11755 +       0x670C354E,
11756 +       0x7096966D,
11757 +       0x9ED52907,
11758 +       0x208552BB,
11759 +       0x1C62F356,
11760 +       0xDCA3AD96,
11761 +       0x83655D23,
11762 +       0xFD24CF5F,
11763 +       0x69163FA8,
11764 +       0x1C55D39A,
11765 +       0x98DA4836,
11766 +       0xA163BF05,
11767 +       0xC2007CB8,
11768 +       0xECE45B3D,
11769 +       0x49286651,
11770 +       0x7C4B1FE6,
11771 +       0xAE9F2411,
11772 +       0x5A899FA5,
11773 +       0xEE386BFB,
11774 +       0xF406B7ED,
11775 +       0x0BFF5CB6,
11776 +       0xA637ED6B,
11777 +       0xF44C42E9,
11778 +       0x625E7EC6,
11779 +       0xE485B576,
11780 +       0x6D51C245,
11781 +       0x4FE1356D,
11782 +       0xF25F1437,
11783 +       0x302B0A6D,
11784 +       0xCD3A431B,
11785 +       0xEF9519B3,
11786 +       0x8E3404DD,
11787 +       0x514A0879,
11788 +       0x3B139B22,
11789 +       0x020BBEA6,
11790 +       0x8A67CC74,
11791 +       0x29024E08,
11792 +       0x80DC1CD1,
11793 +       0xC4C6628B,
11794 +       0x2168C234,
11795 +       0xC90FDAA2,
11796 +       0xFFFFFFFF,
11797 +       0xFFFFFFFF,
11798 +};
11799 +
11800 +static __u32 dh_a[] = {
11801 +       8,
11802 +       0xdf367516,
11803 +       0x86459caa,
11804 +       0xe2d459a4,
11805 +       0xd910dae0,
11806 +       0x8a8b5e37,
11807 +       0x67ab31c6,
11808 +       0xf0b55ea9,
11809 +       0x440051d6,
11810 +};
11811 +
11812 +static __u32 dh_b[] = {
11813 +       8,
11814 +       0xded92656,
11815 +       0xe07a048a,
11816 +       0x6fa452cd,
11817 +       0x2df89d30,
11818 +       0xc75f1b0f,
11819 +       0x8ce3578f,
11820 +       0x7980a324,
11821 +       0x5daec786,
11822 +};
11823 +
11824 +static __u32 dh_g[] = {
11825 +       1,
11826 +       2,
11827 +};
11828 +
11829 +int main(void)
11830 +{
11831 +       int i;
11832 +       __u32 *k;
11833 +       k = dwc_modpow(NULL, dh_g, dh_a, dh_p);
11834 +
11835 +       printf("\n\n");
11836 +       for (i=0; i<k[0]; i++) {
11837 +               __u32 word32 = k[k[0] - i];
11838 +               __u16 l = word32 & 0xffff;
11839 +               __u16 m = (word32 & 0xffff0000) >> 16;
11840 +               printf("%04x %04x ", m, l);
11841 +               if (!((i + 1)%13)) printf("\n");
11842 +       }
11843 +       printf("\n\n");
11844 +
11845 +       if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
11846 +               printf("PASS\n\n");
11847 +       }
11848 +       else {
11849 +               printf("FAIL\n\n");
11850 +       }
11851 +
11852 +}
11853 +
11854 +#endif /* UNITTEST */
11855 +
11856 +#endif /* CONFIG_MACH_IPMATE */
11857 +
11858 +#endif /*DWC_CRYPTOLIB */
11859 diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.h b/drivers/usb/host/dwc_common_port/dwc_modpow.h
11860 new file mode 100644
11861 index 0000000..64f00c2
11862 --- /dev/null
11863 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
11864 @@ -0,0 +1,34 @@
11865 +/*
11866 + * dwc_modpow.h
11867 + * See dwc_modpow.c for license and changes
11868 + */
11869 +#ifndef _DWC_MODPOW_H
11870 +#define _DWC_MODPOW_H
11871 +
11872 +#ifdef __cplusplus
11873 +extern "C" {
11874 +#endif
11875 +
11876 +#include "dwc_os.h"
11877 +
11878 +/** @file
11879 + *
11880 + * This file defines the module exponentiation function which is only used
11881 + * internally by the DWC UWB modules for calculation of PKs during numeric
11882 + * association.  The routine is taken from the PUTTY, an open source terminal
11883 + * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.
11884 + *
11885 + */
11886 +
11887 +typedef uint32_t BignumInt;
11888 +typedef uint64_t BignumDblInt;
11889 +typedef BignumInt *Bignum;
11890 +
11891 +/* Compute modular exponentiaion */
11892 +extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);
11893 +
11894 +#ifdef __cplusplus
11895 +}
11896 +#endif
11897 +
11898 +#endif /* _LINUX_BIGNUM_H */
11899 diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.c b/drivers/usb/host/dwc_common_port/dwc_notifier.c
11900 new file mode 100644
11901 index 0000000..8b3772a
11902 --- /dev/null
11903 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
11904 @@ -0,0 +1,319 @@
11905 +#ifdef DWC_NOTIFYLIB
11906 +
11907 +#include "dwc_notifier.h"
11908 +#include "dwc_list.h"
11909 +
11910 +typedef struct dwc_observer {
11911 +       void *observer;
11912 +       dwc_notifier_callback_t callback;
11913 +       void *data;
11914 +       char *notification;
11915 +       DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
11916 +} observer_t;
11917 +
11918 +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
11919 +
11920 +typedef struct dwc_notifier {
11921 +       void *mem_ctx;
11922 +       void *object;
11923 +       struct observer_queue observers;
11924 +       DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
11925 +} notifier_t;
11926 +
11927 +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
11928 +
11929 +typedef struct manager {
11930 +       void *mem_ctx;
11931 +       void *wkq_ctx;
11932 +       dwc_workq_t *wq;
11933 +//     dwc_mutex_t *mutex;
11934 +       struct notifier_queue notifiers;
11935 +} manager_t;
11936 +
11937 +static manager_t *manager = NULL;
11938 +
11939 +static int create_manager(void *mem_ctx, void *wkq_ctx)
11940 +{
11941 +       manager = dwc_alloc(mem_ctx, sizeof(manager_t));
11942 +       if (!manager) {
11943 +               return -DWC_E_NO_MEMORY;
11944 +       }
11945 +
11946 +       DWC_CIRCLEQ_INIT(&manager->notifiers);
11947 +
11948 +       manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");
11949 +       if (!manager->wq) {
11950 +               return -DWC_E_NO_MEMORY;
11951 +       }
11952 +
11953 +       return 0;
11954 +}
11955 +
11956 +static void free_manager(void)
11957 +{
11958 +       dwc_workq_free(manager->wq);
11959 +
11960 +       /* All notifiers must have unregistered themselves before this module
11961 +        * can be removed.  Hitting this assertion indicates a programmer
11962 +        * error. */
11963 +       DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),
11964 +                  "Notification manager being freed before all notifiers have been removed");
11965 +       dwc_free(manager->mem_ctx, manager);
11966 +}
11967 +
11968 +#ifdef DEBUG
11969 +static void dump_manager(void)
11970 +{
11971 +       notifier_t *n;
11972 +       observer_t *o;
11973 +
11974 +       DWC_ASSERT(manager, "Notification manager not found");
11975 +
11976 +       DWC_DEBUG("List of all notifiers and observers:\n");
11977 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
11978 +               DWC_DEBUG("Notifier %p has observers:\n", n->object);
11979 +               DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
11980 +                       DWC_DEBUG("    %p watching %s\n", o->observer, o->notification);
11981 +               }
11982 +       }
11983 +}
11984 +#else
11985 +#define dump_manager(...)
11986 +#endif
11987 +
11988 +static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,
11989 +                                 dwc_notifier_callback_t callback, void *data)
11990 +{
11991 +       observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));
11992 +
11993 +       if (!new_observer) {
11994 +               return NULL;
11995 +       }
11996 +
11997 +       DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
11998 +       new_observer->observer = observer;
11999 +       new_observer->notification = notification;
12000 +       new_observer->callback = callback;
12001 +       new_observer->data = data;
12002 +       return new_observer;
12003 +}
12004 +
12005 +static void free_observer(void *mem_ctx, observer_t *observer)
12006 +{
12007 +       dwc_free(mem_ctx, observer);
12008 +}
12009 +
12010 +static notifier_t *alloc_notifier(void *mem_ctx, void *object)
12011 +{
12012 +       notifier_t *notifier;
12013 +
12014 +       if (!object) {
12015 +               return NULL;
12016 +       }
12017 +
12018 +       notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));
12019 +       if (!notifier) {
12020 +               return NULL;
12021 +       }
12022 +
12023 +       DWC_CIRCLEQ_INIT(&notifier->observers);
12024 +       DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
12025 +
12026 +       notifier->mem_ctx = mem_ctx;
12027 +       notifier->object = object;
12028 +       return notifier;
12029 +}
12030 +
12031 +static void free_notifier(notifier_t *notifier)
12032 +{
12033 +       observer_t *observer;
12034 +
12035 +       DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
12036 +               free_observer(notifier->mem_ctx, observer);
12037 +       }
12038 +
12039 +       dwc_free(notifier->mem_ctx, notifier);
12040 +}
12041 +
12042 +static notifier_t *find_notifier(void *object)
12043 +{
12044 +       notifier_t *notifier;
12045 +
12046 +       DWC_ASSERT(manager, "Notification manager not found");
12047 +
12048 +       if (!object) {
12049 +               return NULL;
12050 +       }
12051 +
12052 +       DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
12053 +               if (notifier->object == object) {
12054 +                       return notifier;
12055 +               }
12056 +       }
12057 +
12058 +       return NULL;
12059 +}
12060 +
12061 +int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)
12062 +{
12063 +       return create_manager(mem_ctx, wkq_ctx);
12064 +}
12065 +
12066 +void dwc_free_notification_manager(void)
12067 +{
12068 +       free_manager();
12069 +}
12070 +
12071 +dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)
12072 +{
12073 +       notifier_t *notifier;
12074 +
12075 +       DWC_ASSERT(manager, "Notification manager not found");
12076 +
12077 +       notifier = find_notifier(object);
12078 +       if (notifier) {
12079 +               DWC_ERROR("Notifier %p is already registered\n", object);
12080 +               return NULL;
12081 +       }
12082 +
12083 +       notifier = alloc_notifier(mem_ctx, object);
12084 +       if (!notifier) {
12085 +               return NULL;
12086 +       }
12087 +
12088 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
12089 +
12090 +       DWC_INFO("Notifier %p registered", object);
12091 +       dump_manager();
12092 +
12093 +       return notifier;
12094 +}
12095 +
12096 +void dwc_unregister_notifier(dwc_notifier_t *notifier)
12097 +{
12098 +       DWC_ASSERT(manager, "Notification manager not found");
12099 +
12100 +       if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
12101 +               observer_t *o;
12102 +
12103 +               DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);
12104 +               DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12105 +                       DWC_DEBUGC("    %p watching %s\n", o->observer, o->notification);
12106 +               }
12107 +
12108 +               DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers),
12109 +                          "Notifier %p has active observers when removing", notifier);
12110 +       }
12111 +
12112 +       DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
12113 +       free_notifier(notifier);
12114 +
12115 +       DWC_INFO("Notifier unregistered");
12116 +       dump_manager();
12117 +}
12118 +
12119 +/* Add an observer to observe the notifier for a particular state, event, or notification. */
12120 +int dwc_add_observer(void *observer, void *object, char *notification,
12121 +                    dwc_notifier_callback_t callback, void *data)
12122 +{
12123 +       notifier_t *notifier = find_notifier(object);
12124 +       observer_t *new_observer;
12125 +
12126 +       if (!notifier) {
12127 +               DWC_ERROR("Notifier %p is not found when adding observer\n", object);
12128 +               return -DWC_E_INVALID;
12129 +       }
12130 +
12131 +       new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);
12132 +       if (!new_observer) {
12133 +               return -DWC_E_NO_MEMORY;
12134 +       }
12135 +
12136 +       DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
12137 +
12138 +       DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
12139 +                observer, object, notification, callback, data);
12140 +
12141 +       dump_manager();
12142 +       return 0;
12143 +}
12144 +
12145 +int dwc_remove_observer(void *observer)
12146 +{
12147 +       notifier_t *n;
12148 +
12149 +       DWC_ASSERT(manager, "Notification manager not found");
12150 +
12151 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
12152 +               observer_t *o;
12153 +               observer_t *o2;
12154 +
12155 +               DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
12156 +                       if (o->observer == observer) {
12157 +                               DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
12158 +                               DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
12159 +                                        o->observer, n->object, o->notification);
12160 +                               free_observer(n->mem_ctx, o);
12161 +                       }
12162 +               }
12163 +       }
12164 +
12165 +       dump_manager();
12166 +       return 0;
12167 +}
12168 +
12169 +typedef struct callback_data {
12170 +       void *mem_ctx;
12171 +       dwc_notifier_callback_t cb;
12172 +       void *observer;
12173 +       void *data;
12174 +       void *object;
12175 +       char *notification;
12176 +       void *notification_data;
12177 +} cb_data_t;
12178 +
12179 +static void cb_task(void *data)
12180 +{
12181 +       cb_data_t *cb = (cb_data_t *)data;
12182 +
12183 +       cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
12184 +       dwc_free(cb->mem_ctx, cb);
12185 +}
12186 +
12187 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
12188 +{
12189 +       observer_t *o;
12190 +
12191 +       DWC_ASSERT(manager, "Notification manager not found");
12192 +
12193 +       DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12194 +               int len = DWC_STRLEN(notification);
12195 +
12196 +               if (DWC_STRLEN(o->notification) != len) {
12197 +                       continue;
12198 +               }
12199 +
12200 +               if (DWC_STRNCMP(o->notification, notification, len) == 0) {
12201 +                       cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));
12202 +
12203 +                       if (!cb_data) {
12204 +                               DWC_ERROR("Failed to allocate callback data\n");
12205 +                               return;
12206 +                       }
12207 +
12208 +                       cb_data->mem_ctx = notifier->mem_ctx;
12209 +                       cb_data->cb = o->callback;
12210 +                       cb_data->observer = o->observer;
12211 +                       cb_data->data = o->data;
12212 +                       cb_data->object = notifier->object;
12213 +                       cb_data->notification = notification;
12214 +                       cb_data->notification_data = notification_data;
12215 +                       DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);
12216 +                       DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
12217 +                                          "Notify callback from %p for Notification %s, to observer %p",
12218 +                                          cb_data->object, notification, cb_data->observer);
12219 +               }
12220 +       }
12221 +}
12222 +
12223 +#endif /* DWC_NOTIFYLIB */
12224 diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.h b/drivers/usb/host/dwc_common_port/dwc_notifier.h
12225 new file mode 100644
12226 index 0000000..4a8cdfe
12227 --- /dev/null
12228 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
12229 @@ -0,0 +1,122 @@
12230 +
12231 +#ifndef __DWC_NOTIFIER_H__
12232 +#define __DWC_NOTIFIER_H__
12233 +
12234 +#ifdef __cplusplus
12235 +extern "C" {
12236 +#endif
12237 +
12238 +#include "dwc_os.h"
12239 +
12240 +/** @file
12241 + *
12242 + * A simple implementation of the Observer pattern.  Any "module" can
12243 + * register as an observer or notifier.  The notion of "module" is abstract and
12244 + * can mean anything used to identify either an observer or notifier.  Usually
12245 + * it will be a pointer to a data structure which contains some state, ie an
12246 + * object.
12247 + *
12248 + * Before any notifiers can be added, the global notification manager must be
12249 + * brought up with dwc_alloc_notification_manager().
12250 + * dwc_free_notification_manager() will bring it down and free all resources.
12251 + * These would typically be called upon module load and unload.  The
12252 + * notification manager is a single global instance that handles all registered
12253 + * observable modules and observers so this should be done only once.
12254 + *
12255 + * A module can be observable by using Notifications to publicize some general
12256 + * information about it's state or operation.  It does not care who listens, or
12257 + * even if anyone listens, or what they do with the information.  The observable
12258 + * modules do not need to know any information about it's observers or their
12259 + * interface, or their state or data.
12260 + *
12261 + * Any module can register to emit Notifications.  It should publish a list of
12262 + * notifications that it can emit and their behavior, such as when they will get
12263 + * triggered, and what information will be provided to the observer.  Then it
12264 + * should register itself as an observable module. See dwc_register_notifier().
12265 + *
12266 + * Any module can observe any observable, registered module, provided it has a
12267 + * handle to the other module and knows what notifications to observe.  See
12268 + * dwc_add_observer().
12269 + *
12270 + * A function of type dwc_notifier_callback_t is called whenever a notification
12271 + * is triggered with one or more observers observing it.  This function is
12272 + * called in it's own process so it may sleep or block if needed.  It is
12273 + * guaranteed to be called sometime after the notification has occurred and will
12274 + * be called once per each time the notification is triggered.  It will NOT be
12275 + * called in the same process context used to trigger the notification.
12276 + *
12277 + * @section Limitiations
12278 + *
12279 + * Keep in mind that Notifications that can be triggered in rapid sucession may
12280 + * schedule too many processes too handle.  Be aware of this limitation when
12281 + * designing to use notifications, and only add notifications for appropriate
12282 + * observable information.
12283 + *
12284 + * Also Notification callbacks are not synchronous.  If you need to synchronize
12285 + * the behavior between module/observer you must use other means.  And perhaps
12286 + * that will mean Notifications are not the proper solution.
12287 + */
12288 +
12289 +struct dwc_notifier;
12290 +typedef struct dwc_notifier dwc_notifier_t;
12291 +
12292 +/** The callback function must be of this type.
12293 + *
12294 + * @param object This is the object that is being observed.
12295 + * @param notification This is the notification that was triggered.
12296 + * @param observer This is the observer
12297 + * @param notification_data This is notification-specific data that the notifier
12298 + * has included in this notification.  The value of this should be published in
12299 + * the documentation of the observable module with the notifications.
12300 + * @param user_data This is any custom data that the observer provided when
12301 + * adding itself as an observer to the notification. */
12302 +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
12303 +                                       void *notification_data, void *user_data);
12304 +
12305 +/** Brings up the notification manager. */
12306 +extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
12307 +/** Brings down the notification manager. */
12308 +extern void dwc_free_notification_manager(void);
12309 +
12310 +/** This function registers an observable module.  A dwc_notifier_t object is
12311 + * returned to the observable module.  This is an opaque object that is used by
12312 + * the observable module to trigger notifications.  This object should only be
12313 + * accessible to functions that are authorized to trigger notifications for this
12314 + * module.  Observers do not need this object. */
12315 +extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
12316 +
12317 +/** This function unregisters an observable module.  All observers have to be
12318 + * removed prior to unregistration. */
12319 +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
12320 +
12321 +/** Add a module as an observer to the observable module.  The observable module
12322 + * needs to have previously registered with the notification manager.
12323 + *
12324 + * @param observer The observer module
12325 + * @param object The module to observe
12326 + * @param notification The notification to observe
12327 + * @param callback The callback function to call
12328 + * @param user_data Any additional user data to pass into the callback function */
12329 +extern int dwc_add_observer(void *observer, void *object, char *notification,
12330 +                           dwc_notifier_callback_t callback, void *user_data);
12331 +
12332 +/** Removes the specified observer from all notifications that it is currently
12333 + * observing. */
12334 +extern int dwc_remove_observer(void *observer);
12335 +
12336 +/** This function triggers a Notification.  It should be called by the
12337 + * observable module, or any module or library which the observable module
12338 + * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.
12339 + *
12340 + * dwc_notify is a non-blocking function.  Callbacks are scheduled called in
12341 + * their own process context for each trigger.  Callbacks can be blocking.
12342 + * dwc_notify can be called from interrupt context if needed.
12343 + *
12344 + */
12345 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
12346 +
12347 +#ifdef __cplusplus
12348 +}
12349 +#endif
12350 +
12351 +#endif /* __DWC_NOTIFIER_H__ */
12352 diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h
12353 new file mode 100644
12354 index 0000000..8117731
12355 --- /dev/null
12356 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
12357 @@ -0,0 +1,1274 @@
12358 +/* =========================================================================
12359 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
12360 + * $Revision: #14 $
12361 + * $Date: 2010/11/04 $
12362 + * $Change: 1621695 $
12363 + *
12364 + * Synopsys Portability Library Software and documentation
12365 + * (hereinafter, "Software") is an Unsupported proprietary work of
12366 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
12367 + * between Synopsys and you.
12368 + *
12369 + * The Software IS NOT an item of Licensed Software or Licensed Product
12370 + * under any End User Software License Agreement or Agreement for
12371 + * Licensed Product with Synopsys or any supplement thereto. You are
12372 + * permitted to use and redistribute this Software in source and binary
12373 + * forms, with or without modification, provided that redistributions
12374 + * of source code must retain this notice. You may not view, use,
12375 + * disclose, copy or distribute this file or any information contained
12376 + * herein except pursuant to this license grant from Synopsys. If you
12377 + * do not agree with this notice, including the disclaimer below, then
12378 + * you are not authorized to use the Software.
12379 + *
12380 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
12381 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12382 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12383 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
12384 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
12385 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
12386 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
12387 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
12388 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12389 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
12390 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12391 + * DAMAGE.
12392 + * ========================================================================= */
12393 +#ifndef _DWC_OS_H_
12394 +#define _DWC_OS_H_
12395 +
12396 +#ifdef __cplusplus
12397 +extern "C" {
12398 +#endif
12399 +
12400 +/** @file
12401 + *
12402 + * DWC portability library, low level os-wrapper functions
12403 + *
12404 + */
12405 +
12406 +/* These basic types need to be defined by some OS header file or custom header
12407 + * file for your specific target architecture.
12408 + *
12409 + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
12410 + *
12411 + * Any custom or alternate header file must be added and enabled here.
12412 + */
12413 +
12414 +#ifdef DWC_LINUX
12415 +# include <linux/types.h>
12416 +# ifdef CONFIG_DEBUG_MUTEXES
12417 +#  include <linux/mutex.h>
12418 +# endif
12419 +# include <linux/spinlock.h>
12420 +# include <linux/errno.h>
12421 +# include <stdarg.h>
12422 +#endif
12423 +
12424 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12425 +# include <os_dep.h>
12426 +#endif
12427 +
12428 +
12429 +/** @name Primitive Types and Values */
12430 +
12431 +/** We define a boolean type for consistency.  Can be either YES or NO */
12432 +typedef uint8_t dwc_bool_t;
12433 +#define YES  1
12434 +#define NO   0
12435 +
12436 +#ifdef DWC_LINUX
12437 +
12438 +/** @name Error Codes */
12439 +#define DWC_E_INVALID          EINVAL
12440 +#define DWC_E_NO_MEMORY                ENOMEM
12441 +#define DWC_E_NO_DEVICE                ENODEV
12442 +#define DWC_E_NOT_SUPPORTED    EOPNOTSUPP
12443 +#define DWC_E_TIMEOUT          ETIMEDOUT
12444 +#define DWC_E_BUSY             EBUSY
12445 +#define DWC_E_AGAIN            EAGAIN
12446 +#define DWC_E_RESTART          ERESTART
12447 +#define DWC_E_ABORT            ECONNABORTED
12448 +#define DWC_E_SHUTDOWN         ESHUTDOWN
12449 +#define DWC_E_NO_DATA          ENODATA
12450 +#define DWC_E_DISCONNECT       ECONNRESET
12451 +#define DWC_E_UNKNOWN          EINVAL
12452 +#define DWC_E_NO_STREAM_RES    ENOSR
12453 +#define DWC_E_COMMUNICATION    ECOMM
12454 +#define DWC_E_OVERFLOW         EOVERFLOW
12455 +#define DWC_E_PROTOCOL         EPROTO
12456 +#define DWC_E_IN_PROGRESS      EINPROGRESS
12457 +#define DWC_E_PIPE             EPIPE
12458 +#define DWC_E_IO               EIO
12459 +#define DWC_E_NO_SPACE         ENOSPC
12460 +
12461 +#else
12462 +
12463 +/** @name Error Codes */
12464 +#define DWC_E_INVALID          1001
12465 +#define DWC_E_NO_MEMORY                1002
12466 +#define DWC_E_NO_DEVICE                1003
12467 +#define DWC_E_NOT_SUPPORTED    1004
12468 +#define DWC_E_TIMEOUT          1005
12469 +#define DWC_E_BUSY             1006
12470 +#define DWC_E_AGAIN            1007
12471 +#define DWC_E_RESTART          1008
12472 +#define DWC_E_ABORT            1009
12473 +#define DWC_E_SHUTDOWN         1010
12474 +#define DWC_E_NO_DATA          1011
12475 +#define DWC_E_DISCONNECT       2000
12476 +#define DWC_E_UNKNOWN          3000
12477 +#define DWC_E_NO_STREAM_RES    4001
12478 +#define DWC_E_COMMUNICATION    4002
12479 +#define DWC_E_OVERFLOW         4003
12480 +#define DWC_E_PROTOCOL         4004
12481 +#define DWC_E_IN_PROGRESS      4005
12482 +#define DWC_E_PIPE             4006
12483 +#define DWC_E_IO               4007
12484 +#define DWC_E_NO_SPACE         4008
12485 +
12486 +#endif
12487 +
12488 +
12489 +/** @name Tracing/Logging Functions
12490 + *
12491 + * These function provide the capability to add tracing, debugging, and error
12492 + * messages, as well exceptions as assertions.  The WUDEV uses these
12493 + * extensively.  These could be logged to the main console, the serial port, an
12494 + * internal buffer, etc.  These functions could also be no-op if they are too
12495 + * expensive on your system.  By default undefining the DEBUG macro already
12496 + * no-ops some of these functions. */
12497 +
12498 +/** Returns non-zero if in interrupt context. */
12499 +extern dwc_bool_t DWC_IN_IRQ(void);
12500 +#define dwc_in_irq DWC_IN_IRQ
12501 +
12502 +/** Returns "IRQ" if DWC_IN_IRQ is true. */
12503 +static inline char *dwc_irq(void) {
12504 +       return DWC_IN_IRQ() ? "IRQ" : "";
12505 +}
12506 +
12507 +/** Returns non-zero if in bottom-half context. */
12508 +extern dwc_bool_t DWC_IN_BH(void);
12509 +#define dwc_in_bh DWC_IN_BH
12510 +
12511 +/** Returns "BH" if DWC_IN_BH is true. */
12512 +static inline char *dwc_bh(void) {
12513 +       return DWC_IN_BH() ? "BH" : "";
12514 +}
12515 +
12516 +/**
12517 + * A vprintf() clone.  Just call vprintf if you've got it.
12518 + */
12519 +extern void DWC_VPRINTF(char *format, va_list args);
12520 +#define dwc_vprintf DWC_VPRINTF
12521 +
12522 +/**
12523 + * A vsnprintf() clone.  Just call vprintf if you've got it.
12524 + */
12525 +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
12526 +#define dwc_vsnprintf DWC_VSNPRINTF
12527 +
12528 +/**
12529 + * printf() clone.  Just call printf if you've go it.
12530 + */
12531 +extern void DWC_PRINTF(char *format, ...)
12532 +/* This provides compiler level static checking of the parameters if you're
12533 + * using GCC. */
12534 +#ifdef __GNUC__
12535 +       __attribute__ ((format(printf, 1, 2)));
12536 +#else
12537 +       ;
12538 +#endif
12539 +#define dwc_printf DWC_PRINTF
12540 +
12541 +/**
12542 + * sprintf() clone.  Just call sprintf if you've got it.
12543 + */
12544 +extern int DWC_SPRINTF(char *string, char *format, ...)
12545 +#ifdef __GNUC__
12546 +       __attribute__ ((format(printf, 2, 3)));
12547 +#else
12548 +       ;
12549 +#endif
12550 +#define dwc_sprintf DWC_SPRINTF
12551 +
12552 +/**
12553 + * snprintf() clone.  Just call snprintf if you've got it.
12554 + */
12555 +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
12556 +#ifdef __GNUC__
12557 +       __attribute__ ((format(printf, 3, 4)));
12558 +#else
12559 +       ;
12560 +#endif
12561 +#define dwc_snprintf DWC_SNPRINTF
12562 +
12563 +/**
12564 + * Prints a WARNING message.  On systems that don't differentiate between
12565 + * warnings and regular log messages, just print it.  Indicates that something
12566 + * may be wrong with the driver.  Works like printf().
12567 + *
12568 + * Use the DWC_WARN macro to call this function.
12569 + */
12570 +extern void __DWC_WARN(char *format, ...)
12571 +#ifdef __GNUC__
12572 +       __attribute__ ((format(printf, 1, 2)));
12573 +#else
12574 +       ;
12575 +#endif
12576 +
12577 +/**
12578 + * Prints an error message.  On systems that don't differentiate between errors
12579 + * and regular log messages, just print it.  Indicates that something went wrong
12580 + * with the driver.  Works like printf().
12581 + *
12582 + * Use the DWC_ERROR macro to call this function.
12583 + */
12584 +extern void __DWC_ERROR(char *format, ...)
12585 +#ifdef __GNUC__
12586 +       __attribute__ ((format(printf, 1, 2)));
12587 +#else
12588 +       ;
12589 +#endif
12590 +
12591 +/**
12592 + * Prints an exception error message and takes some user-defined action such as
12593 + * print out a backtrace or trigger a breakpoint.  Indicates that something went
12594 + * abnormally wrong with the driver such as programmer error, or other
12595 + * exceptional condition.  It should not be ignored so even on systems without
12596 + * printing capability, some action should be taken to notify the developer of
12597 + * it.  Works like printf().
12598 + */
12599 +extern void DWC_EXCEPTION(char *format, ...)
12600 +#ifdef __GNUC__
12601 +       __attribute__ ((format(printf, 1, 2)));
12602 +#else
12603 +       ;
12604 +#endif
12605 +#define dwc_exception DWC_EXCEPTION
12606 +
12607 +#ifndef DWC_OTG_DEBUG_LEV
12608 +#define DWC_OTG_DEBUG_LEV 0
12609 +#endif
12610 +
12611 +#ifdef DEBUG
12612 +/**
12613 + * Prints out a debug message.  Used for logging/trace messages.
12614 + *
12615 + * Use the DWC_DEBUG macro to call this function
12616 + */
12617 +extern void __DWC_DEBUG(char *format, ...)
12618 +#ifdef __GNUC__
12619 +       __attribute__ ((format(printf, 1, 2)));
12620 +#else
12621 +       ;
12622 +#endif
12623 +#else
12624 +#define __DWC_DEBUG printk
12625 +#endif
12626 +
12627 +/**
12628 + * Prints out a Debug message.
12629 + */
12630 +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
12631 +                                                __func__, dwc_irq(), ## _args)
12632 +#define dwc_debug DWC_DEBUG
12633 +/**
12634 + * Prints out a Debug message if enabled at compile time.
12635 + */
12636 +#if DWC_OTG_DEBUG_LEV > 0
12637 +#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
12638 +#else
12639 +#define DWC_DEBUGC(_format, _args...)
12640 +#endif
12641 +#define dwc_debugc DWC_DEBUGC
12642 +/**
12643 + * Prints out an informative message.
12644 + */
12645 +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
12646 +                                              dwc_irq(), ## _args)
12647 +#define dwc_info DWC_INFO
12648 +/**
12649 + * Prints out an informative message if enabled at compile time.
12650 + */
12651 +#if DWC_OTG_DEBUG_LEV > 1
12652 +#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
12653 +#else
12654 +#define DWC_INFOC(_format, _args...)
12655 +#endif
12656 +#define dwc_infoc DWC_INFOC
12657 +/**
12658 + * Prints out a warning message.
12659 + */
12660 +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
12661 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12662 +#define dwc_warn DWC_WARN
12663 +/**
12664 + * Prints out an error message.
12665 + */
12666 +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
12667 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12668 +#define dwc_error DWC_ERROR
12669 +
12670 +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
12671 +                                               dwc_irq(), __func__, __LINE__, ## _args)
12672 +#define dwc_proto_error DWC_PROTO_ERROR
12673 +
12674 +#ifdef DEBUG
12675 +/** Prints out a exception error message if the _expr expression fails.  Disabled
12676 + * if DEBUG is not enabled. */
12677 +#define DWC_ASSERT(_expr, _format, _args...) do { \
12678 +       if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
12679 +                                     __FILE__, __LINE__, ## _args); } \
12680 +       } while (0)
12681 +#else
12682 +#define DWC_ASSERT(_x...)
12683 +#endif
12684 +#define dwc_assert DWC_ASSERT
12685 +
12686 +
12687 +/** @name Byte Ordering
12688 + * The following functions are for conversions between processor's byte ordering
12689 + * and specific ordering you want.
12690 + */
12691 +
12692 +/** Converts 32 bit data in CPU byte ordering to little endian. */
12693 +extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
12694 +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
12695 +
12696 +/** Converts 32 bit data in CPU byte orderint to big endian. */
12697 +extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
12698 +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
12699 +
12700 +/** Converts 32 bit little endian data to CPU byte ordering. */
12701 +extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
12702 +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
12703 +
12704 +/** Converts 32 bit big endian data to CPU byte ordering. */
12705 +extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
12706 +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
12707 +
12708 +/** Converts 16 bit data in CPU byte ordering to little endian. */
12709 +extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
12710 +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
12711 +
12712 +/** Converts 16 bit data in CPU byte orderint to big endian. */
12713 +extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
12714 +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
12715 +
12716 +/** Converts 16 bit little endian data to CPU byte ordering. */
12717 +extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
12718 +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
12719 +
12720 +/** Converts 16 bit bi endian data to CPU byte ordering. */
12721 +extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
12722 +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
12723 +
12724 +
12725 +/** @name Register Read/Write
12726 + *
12727 + * The following six functions should be implemented to read/write registers of
12728 + * 32-bit and 64-bit sizes.  All modules use this to read/write register values.
12729 + * The reg value is a pointer to the register calculated from the void *base
12730 + * variable passed into the driver when it is started.  */
12731 +
12732 +#ifdef DWC_LINUX
12733 +/* Linux doesn't need any extra parameters for register read/write, so we
12734 + * just throw away the IO context parameter.
12735 + */
12736 +/** Reads the content of a 32-bit register. */
12737 +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
12738 +#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
12739 +
12740 +/** Reads the content of a 64-bit register. */
12741 +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
12742 +#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
12743 +
12744 +/** Writes to a 32-bit register. */
12745 +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
12746 +#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
12747 +
12748 +/** Writes to a 64-bit register. */
12749 +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
12750 +#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
12751 +
12752 +/**
12753 + * Modify bit values in a register.  Using the
12754 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12755 + */
12756 +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12757 +#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
12758 +extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12759 +#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
12760 +
12761 +#endif /* DWC_LINUX */
12762 +
12763 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12764 +typedef struct dwc_ioctx {
12765 +       struct device *dev;
12766 +       bus_space_tag_t iot;
12767 +       bus_space_handle_t ioh;
12768 +} dwc_ioctx_t;
12769 +
12770 +/** BSD needs two extra parameters for register read/write, so we pass
12771 + * them in using the IO context parameter.
12772 + */
12773 +/** Reads the content of a 32-bit register. */
12774 +extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
12775 +#define dwc_read_reg32 DWC_READ_REG32
12776 +
12777 +/** Reads the content of a 64-bit register. */
12778 +extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
12779 +#define dwc_read_reg64 DWC_READ_REG64
12780 +
12781 +/** Writes to a 32-bit register. */
12782 +extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
12783 +#define dwc_write_reg32 DWC_WRITE_REG32
12784 +
12785 +/** Writes to a 64-bit register. */
12786 +extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
12787 +#define dwc_write_reg64 DWC_WRITE_REG64
12788 +
12789 +/**
12790 + * Modify bit values in a register.  Using the
12791 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12792 + */
12793 +extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12794 +#define dwc_modify_reg32 DWC_MODIFY_REG32
12795 +extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12796 +#define dwc_modify_reg64 DWC_MODIFY_REG64
12797 +
12798 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12799 +
12800 +/** @cond */
12801 +
12802 +/** @name Some convenience MACROS used internally.  Define DWC_DEBUG_REGS to log the
12803 + * register writes. */
12804 +
12805 +#ifdef DWC_LINUX
12806 +
12807 +# ifdef DWC_DEBUG_REGS
12808 +
12809 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12810 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12811 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12812 +} \
12813 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12814 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12815 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12816 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12817 +}
12818 +
12819 +#define dwc_define_read_write_reg(_reg,_container_type) \
12820 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12821 +       return DWC_READ_REG32(&container->regs->_reg); \
12822 +} \
12823 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12824 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12825 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12826 +}
12827 +
12828 +# else /* DWC_DEBUG_REGS */
12829 +
12830 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12831 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12832 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12833 +} \
12834 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12835 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12836 +}
12837 +
12838 +#define dwc_define_read_write_reg(_reg,_container_type) \
12839 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12840 +       return DWC_READ_REG32(&container->regs->_reg); \
12841 +} \
12842 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12843 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12844 +}
12845 +
12846 +# endif        /* DWC_DEBUG_REGS */
12847 +
12848 +#endif /* DWC_LINUX */
12849 +
12850 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12851 +
12852 +# ifdef DWC_DEBUG_REGS
12853 +
12854 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12855 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12856 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12857 +} \
12858 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12859 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12860 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12861 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12862 +}
12863 +
12864 +#define dwc_define_read_write_reg(_reg,_container_type) \
12865 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12866 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12867 +} \
12868 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12869 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12870 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12871 +}
12872 +
12873 +# else /* DWC_DEBUG_REGS */
12874 +
12875 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12876 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12877 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12878 +} \
12879 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12880 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12881 +}
12882 +
12883 +#define dwc_define_read_write_reg(_reg,_container_type) \
12884 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12885 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12886 +} \
12887 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12888 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12889 +}
12890 +
12891 +# endif        /* DWC_DEBUG_REGS */
12892 +
12893 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12894 +
12895 +/** @endcond */
12896 +
12897 +
12898 +#ifdef DWC_CRYPTOLIB
12899 +/** @name Crypto Functions
12900 + *
12901 + * These are the low-level cryptographic functions used by the driver. */
12902 +
12903 +/** Perform AES CBC */
12904 +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
12905 +#define dwc_aes_cbc DWC_AES_CBC
12906 +
12907 +/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */
12908 +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
12909 +#define dwc_random_bytes DWC_RANDOM_BYTES
12910 +
12911 +/** Perform the SHA-256 hash function */
12912 +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
12913 +#define dwc_sha256 DWC_SHA256
12914 +
12915 +/** Calculated the HMAC-SHA256 */
12916 +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
12917 +#define dwc_hmac_sha256 DWC_HMAC_SHA256
12918 +
12919 +#endif /* DWC_CRYPTOLIB */
12920 +
12921 +
12922 +/** @name Memory Allocation
12923 + *
12924 + * These function provide access to memory allocation.  There are only 2 DMA
12925 + * functions and 3 Regular memory functions that need to be implemented.  None
12926 + * of the memory debugging routines need to be implemented.  The allocation
12927 + * routines all ZERO the contents of the memory.
12928 + *
12929 + * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
12930 + * This checks for memory leaks, keeping track of alloc/free pairs.  It also
12931 + * keeps track of how much memory the driver is using at any given time. */
12932 +
12933 +#define DWC_PAGE_SIZE 4096
12934 +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
12935 +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
12936 +
12937 +#define DWC_INVALID_DMA_ADDR 0x0
12938 +
12939 +#ifdef DWC_LINUX
12940 +/** Type for a DMA address */
12941 +typedef dma_addr_t dwc_dma_t;
12942 +#endif
12943 +
12944 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12945 +typedef bus_addr_t dwc_dma_t;
12946 +#endif
12947 +
12948 +#ifdef DWC_FREEBSD
12949 +typedef struct dwc_dmactx {
12950 +       struct device *dev;
12951 +       bus_dma_tag_t dma_tag;
12952 +       bus_dmamap_t dma_map;
12953 +       bus_addr_t dma_paddr;
12954 +       void *dma_vaddr;
12955 +} dwc_dmactx_t;
12956 +#endif
12957 +
12958 +#ifdef DWC_NETBSD
12959 +typedef struct dwc_dmactx {
12960 +       struct device *dev;
12961 +       bus_dma_tag_t dma_tag;
12962 +       bus_dmamap_t dma_map;
12963 +       bus_dma_segment_t segs[1];
12964 +       int nsegs;
12965 +       bus_addr_t dma_paddr;
12966 +       void *dma_vaddr;
12967 +} dwc_dmactx_t;
12968 +#endif
12969 +
12970 +/* @todo these functions will be added in the future */
12971 +#if 0
12972 +/**
12973 + * Creates a DMA pool from which you can allocate DMA buffers.  Buffers
12974 + * allocated from this pool will be guaranteed to meet the size, alignment, and
12975 + * boundary requirements specified.
12976 + *
12977 + * @param[in] size Specifies the size of the buffers that will be allocated from
12978 + * this pool.
12979 + * @param[in] align Specifies the byte alignment requirements of the buffers
12980 + * allocated from this pool.  Must be a power of 2.
12981 + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
12982 + * this pool must not cross.
12983 + *
12984 + * @returns A pointer to an internal opaque structure which is not to be
12985 + * accessed outside of these library functions.  Use this handle to specify
12986 + * which pools to allocate/free DMA buffers from and also to destroy the pool,
12987 + * when you are done with it.
12988 + */
12989 +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
12990 +
12991 +/**
12992 + * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.
12993 + */
12994 +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
12995 +
12996 +/**
12997 + * Allocate a buffer from the specified DMA pool and zeros its contents.
12998 + */
12999 +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
13000 +
13001 +/**
13002 + * Free a previously allocated buffer from the DMA pool.
13003 + */
13004 +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
13005 +#endif
13006 +
13007 +/** Allocates a DMA capable buffer and zeroes its contents. */
13008 +extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
13009 +
13010 +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
13011 +extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
13012 +
13013 +/** Frees a previously allocated buffer. */
13014 +extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
13015 +
13016 +/** Allocates a block of memory and zeroes its contents. */
13017 +extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
13018 +
13019 +/** Allocates a block of memory and zeroes its contents, in an atomic manner
13020 + * which can be used inside interrupt context.  The size should be sufficiently
13021 + * small, a few KB at most, such that failures are not likely to occur.  Can just call
13022 + * __DWC_ALLOC if it is atomic. */
13023 +extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
13024 +
13025 +/** Frees a previously allocated buffer. */
13026 +extern void __DWC_FREE(void *mem_ctx, void *addr);
13027 +
13028 +#ifndef DWC_DEBUG_MEMORY
13029 +
13030 +#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
13031 +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
13032 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
13033 +
13034 +# ifdef DWC_LINUX
13035 +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)
13036 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)
13037 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)
13038 +# endif
13039 +
13040 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13041 +#define DWC_DMA_ALLOC __DWC_DMA_ALLOC
13042 +#define DWC_DMA_FREE __DWC_DMA_FREE
13043 +# endif
13044 +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
13045 +
13046 +#else  /* DWC_DEBUG_MEMORY */
13047 +
13048 +extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
13049 +extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
13050 +extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
13051 +extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
13052 +                                char const *func, int line);
13053 +extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
13054 +                               char const *func, int line);
13055 +extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
13056 +                              dwc_dma_t dma_addr, char const *func, int line);
13057 +
13058 +extern int dwc_memory_debug_start(void *mem_ctx);
13059 +extern void dwc_memory_debug_stop(void);
13060 +extern void dwc_memory_debug_report(void);
13061 +
13062 +#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
13063 +#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
13064 +                                                       __func__, __LINE__)
13065 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
13066 +
13067 +# ifdef DWC_LINUX
13068 +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \
13069 +                                               _dma_, __func__, __LINE__)
13070 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \
13071 +                                               _dma_, __func__, __LINE__)
13072 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \
13073 +                                               _virt_, _dma_, __func__, __LINE__)
13074 +# endif
13075 +
13076 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13077 +#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
13078 +                                               _dma_, __func__, __LINE__)
13079 +#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
13080 +                                                _virt_, _dma_, __func__, __LINE__)
13081 +# endif
13082 +
13083 +#endif /* DWC_DEBUG_MEMORY */
13084 +
13085 +#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
13086 +#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
13087 +#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
13088 +
13089 +#ifdef DWC_LINUX
13090 +/* Linux doesn't need any extra parameters for DMA buffer allocation, so we
13091 + * just throw away the DMA context parameter.
13092 + */
13093 +#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
13094 +#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
13095 +#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
13096 +#endif
13097 +
13098 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13099 +/** BSD needs several extra parameters for DMA buffer allocation, so we pass
13100 + * them in using the DMA context parameter.
13101 + */
13102 +#define dwc_dma_alloc DWC_DMA_ALLOC
13103 +#define dwc_dma_free DWC_DMA_FREE
13104 +#endif
13105 +
13106 +
13107 +/** @name Memory and String Processing */
13108 +
13109 +/** memset() clone */
13110 +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
13111 +#define dwc_memset DWC_MEMSET
13112 +
13113 +/** memcpy() clone */
13114 +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
13115 +#define dwc_memcpy DWC_MEMCPY
13116 +
13117 +/** memmove() clone */
13118 +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
13119 +#define dwc_memmove DWC_MEMMOVE
13120 +
13121 +/** memcmp() clone */
13122 +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
13123 +#define dwc_memcmp DWC_MEMCMP
13124 +
13125 +/** strcmp() clone */
13126 +extern int DWC_STRCMP(void *s1, void *s2);
13127 +#define dwc_strcmp DWC_STRCMP
13128 +
13129 +/** strncmp() clone */
13130 +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
13131 +#define dwc_strncmp DWC_STRNCMP
13132 +
13133 +/** strlen() clone, for NULL terminated ASCII strings */
13134 +extern int DWC_STRLEN(char const *str);
13135 +#define dwc_strlen DWC_STRLEN
13136 +
13137 +/** strcpy() clone, for NULL terminated ASCII strings */
13138 +extern char *DWC_STRCPY(char *to, const char *from);
13139 +#define dwc_strcpy DWC_STRCPY
13140 +
13141 +/** strdup() clone.  If you wish to use memory allocation debugging, this
13142 + * implementation of strdup should use the DWC_* memory routines instead of
13143 + * calling a predefined strdup.  Otherwise the memory allocated by this routine
13144 + * will not be seen by the debugging routines. */
13145 +extern char *DWC_STRDUP(char const *str);
13146 +#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
13147 +
13148 +/** NOT an atoi() clone.  Read the description carefully.  Returns an integer
13149 + * converted from the string str in base 10 unless the string begins with a "0x"
13150 + * in which case it is base 16.  String must be a NULL terminated sequence of
13151 + * ASCII characters and may optionally begin with whitespace, a + or -, and a
13152 + * "0x" prefix if base 16.  The remaining characters must be valid digits for
13153 + * the number and end with a NULL character.  If any invalid characters are
13154 + * encountered or it returns with a negative error code and the results of the
13155 + * conversion are undefined.  On sucess it returns 0.  Overflow conditions are
13156 + * undefined.  An example implementation using atoi() can be referenced from the
13157 + * Linux implementation. */
13158 +extern int DWC_ATOI(const char *str, int32_t *value);
13159 +#define dwc_atoi DWC_ATOI
13160 +
13161 +/** Same as above but for unsigned. */
13162 +extern int DWC_ATOUI(const char *str, uint32_t *value);
13163 +#define dwc_atoui DWC_ATOUI
13164 +
13165 +#ifdef DWC_UTFLIB
13166 +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
13167 +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
13168 +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
13169 +#endif
13170 +
13171 +
13172 +/** @name Wait queues
13173 + *
13174 + * Wait queues provide a means of synchronizing between threads or processes.  A
13175 + * process can block on a waitq if some condition is not true, waiting for it to
13176 + * become true.  When the waitq is triggered all waiting process will get
13177 + * unblocked and the condition will be check again.  Waitqs should be triggered
13178 + * every time a condition can potentially change.*/
13179 +struct dwc_waitq;
13180 +
13181 +/** Type for a waitq */
13182 +typedef struct dwc_waitq dwc_waitq_t;
13183 +
13184 +/** The type of waitq condition callback function.  This is called every time
13185 + * condition is evaluated. */
13186 +typedef int (*dwc_waitq_condition_t)(void *data);
13187 +
13188 +/** Allocate a waitq */
13189 +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
13190 +#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
13191 +
13192 +/** Free a waitq */
13193 +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
13194 +#define dwc_waitq_free DWC_WAITQ_FREE
13195 +
13196 +/** Check the condition and if it is false, block on the waitq.  When unblocked, check the
13197 + * condition again.  The function returns when the condition becomes true.  The return value
13198 + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
13199 +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
13200 +#define dwc_waitq_wait DWC_WAITQ_WAIT
13201 +
13202 +/** Check the condition and if it is false, block on the waitq.  When unblocked,
13203 + * check the condition again.  The function returns when the condition become
13204 + * true or the timeout has passed.  The return value is 0 on condition true or
13205 + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
13206 + * error. */
13207 +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
13208 +                                     void *data, int32_t msecs);
13209 +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
13210 +
13211 +/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition
13212 + * has potentially changed. */
13213 +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
13214 +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
13215 +
13216 +/** Unblock all processes waiting on the waitq with an ABORTED result. */
13217 +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
13218 +#define dwc_waitq_abort DWC_WAITQ_ABORT
13219 +
13220 +
13221 +/** @name Threads
13222 + *
13223 + * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP
13224 + * whenever it is woken up, and then return.  The DWC_THREAD_STOP function
13225 + * returns the value from the thread.
13226 + */
13227 +
13228 +struct dwc_thread;
13229 +
13230 +/** Type for a thread */
13231 +typedef struct dwc_thread dwc_thread_t;
13232 +
13233 +/** The thread function */
13234 +typedef int (*dwc_thread_function_t)(void *data);
13235 +
13236 +/** Create a thread and start it running the thread_function.  Returns a handle
13237 + * to the thread */
13238 +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
13239 +#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
13240 +
13241 +/** Stops a thread.  Return the value returned by the thread.  Or will return
13242 + * DWC_ABORT if the thread never started. */
13243 +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
13244 +#define dwc_thread_stop DWC_THREAD_STOP
13245 +
13246 +/** Signifies to the thread that it must stop. */
13247 +#ifdef DWC_LINUX
13248 +/* Linux doesn't need any parameters for kthread_should_stop() */
13249 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
13250 +#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
13251 +
13252 +/* No thread_exit function in Linux */
13253 +#define dwc_thread_exit(_thrd_)
13254 +#endif
13255 +
13256 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13257 +/** BSD needs the thread pointer for kthread_suspend_check() */
13258 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
13259 +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
13260 +
13261 +/** The thread must call this to exit. */
13262 +extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
13263 +#define dwc_thread_exit DWC_THREAD_EXIT
13264 +#endif
13265 +
13266 +
13267 +/** @name Work queues
13268 + *
13269 + * Workqs are used to queue a callback function to be called at some later time,
13270 + * in another thread. */
13271 +struct dwc_workq;
13272 +
13273 +/** Type for a workq */
13274 +typedef struct dwc_workq dwc_workq_t;
13275 +
13276 +/** The type of the callback function to be called. */
13277 +typedef void (*dwc_work_callback_t)(void *data);
13278 +
13279 +/** Allocate a workq */
13280 +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
13281 +#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
13282 +
13283 +/** Free a workq.  All work must be completed before being freed. */
13284 +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
13285 +#define dwc_workq_free DWC_WORKQ_FREE
13286 +
13287 +/** Schedule a callback on the workq, passing in data.  The function will be
13288 + * scheduled at some later time. */
13289 +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
13290 +                              void *data, char *format, ...)
13291 +#ifdef __GNUC__
13292 +       __attribute__ ((format(printf, 4, 5)));
13293 +#else
13294 +       ;
13295 +#endif
13296 +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
13297 +
13298 +/** Schedule a callback on the workq, that will be called until at least
13299 + * given number miliseconds have passed. */
13300 +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
13301 +                                      void *data, uint32_t time, char *format, ...)
13302 +#ifdef __GNUC__
13303 +       __attribute__ ((format(printf, 5, 6)));
13304 +#else
13305 +       ;
13306 +#endif
13307 +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
13308 +
13309 +/** The number of processes in the workq */
13310 +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
13311 +#define dwc_workq_pending DWC_WORKQ_PENDING
13312 +
13313 +/** Blocks until all the work in the workq is complete or timed out.  Returns <
13314 + * 0 on timeout. */
13315 +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
13316 +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
13317 +
13318 +
13319 +/** @name Tasklets
13320 + *
13321 + */
13322 +struct dwc_tasklet;
13323 +
13324 +/** Type for a tasklet */
13325 +typedef struct dwc_tasklet dwc_tasklet_t;
13326 +
13327 +/** The type of the callback function to be called */
13328 +typedef void (*dwc_tasklet_callback_t)(void *data);
13329 +
13330 +/** Allocates a tasklet */
13331 +extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
13332 +#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
13333 +
13334 +/** Frees a tasklet */
13335 +extern void DWC_TASK_FREE(dwc_tasklet_t *task);
13336 +#define dwc_task_free DWC_TASK_FREE
13337 +
13338 +/** Schedules a tasklet to run */
13339 +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
13340 +#define dwc_task_schedule DWC_TASK_SCHEDULE
13341 +
13342 +
13343 +/** @name Timer
13344 + *
13345 + * Callbacks must be small and atomic.
13346 + */
13347 +struct dwc_timer;
13348 +
13349 +/** Type for a timer */
13350 +typedef struct dwc_timer dwc_timer_t;
13351 +
13352 +/** The type of the callback function to be called */
13353 +typedef void (*dwc_timer_callback_t)(void *data);
13354 +
13355 +/** Allocates a timer */
13356 +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
13357 +#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
13358 +
13359 +/** Frees a timer */
13360 +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
13361 +#define dwc_timer_free DWC_TIMER_FREE
13362 +
13363 +/** Schedules the timer to run at time ms from now.  And will repeat at every
13364 + * repeat_interval msec therafter
13365 + *
13366 + * Modifies a timer that is still awaiting execution to a new expiration time.
13367 + * The mod_time is added to the old time.  */
13368 +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
13369 +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
13370 +
13371 +/** Disables the timer from execution. */
13372 +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
13373 +#define dwc_timer_cancel DWC_TIMER_CANCEL
13374 +
13375 +
13376 +/** @name Spinlocks
13377 + *
13378 + * These locks are used when the work between the lock/unlock is atomic and
13379 + * short.  Interrupts are also disabled during the lock/unlock and thus they are
13380 + * suitable to lock between interrupt/non-interrupt context.  They also lock
13381 + * between processes if you have multiple CPUs or Preemption.  If you don't have
13382 + * multiple CPUS or Preemption, then the you can simply implement the
13383 + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because
13384 + * the work between the lock/unlock is atomic, the process context will never
13385 + * change, and so you never have to lock between processes.  */
13386 +
13387 +struct dwc_spinlock;
13388 +
13389 +/** Type for a spinlock */
13390 +typedef struct dwc_spinlock dwc_spinlock_t;
13391 +
13392 +/** Type for the 'flags' argument to spinlock funtions */
13393 +typedef unsigned long dwc_irqflags_t;
13394 +
13395 +/** Returns an initialized lock variable.  This function should allocate and
13396 + * initialize the OS-specific data structure used for locking.  This data
13397 + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
13398 + * be freed by the DWC_FREE_LOCK when it is no longer used.
13399 + *
13400 + * For Linux Spinlock Debugging make it macro because the debugging routines use
13401 + * the symbol name to determine recursive locking. Using a wrapper function
13402 + * makes it falsely think recursive locking occurs. */
13403 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK)
13404 +#define DWC_SPINLOCK_ALLOC_LINUX_DEBUG(lock) ({ \
13405 +       lock = DWC_ALLOC(sizeof(spinlock_t)); \
13406 +       if (lock) { \
13407 +               spin_lock_init((spinlock_t *)lock); \
13408 +       } \
13409 +})
13410 +#else
13411 +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
13412 +#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
13413 +#endif
13414 +
13415 +/** Frees an initialized lock variable. */
13416 +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
13417 +#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
13418 +
13419 +/** Disables interrupts and blocks until it acquires the lock.
13420 + *
13421 + * @param lock Pointer to the spinlock.
13422 + * @param flags Unsigned long for irq flags storage.
13423 + */
13424 +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
13425 +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
13426 +
13427 +/** Re-enables the interrupt and releases the lock.
13428 + *
13429 + * @param lock Pointer to the spinlock.
13430 + * @param flags Unsigned long for irq flags storage.  Must be the same as was
13431 + * passed into DWC_LOCK.
13432 + */
13433 +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
13434 +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
13435 +
13436 +/** Blocks until it acquires the lock.
13437 + *
13438 + * @param lock Pointer to the spinlock.
13439 + */
13440 +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
13441 +#define dwc_spinlock DWC_SPINLOCK
13442 +
13443 +/** Releases the lock.
13444 + *
13445 + * @param lock Pointer to the spinlock.
13446 + */
13447 +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
13448 +#define dwc_spinunlock DWC_SPINUNLOCK
13449 +
13450 +
13451 +/** @name Mutexes
13452 + *
13453 + * Unlike spinlocks Mutexes lock only between processes and the work between the
13454 + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
13455 + */
13456 +
13457 +struct dwc_mutex;
13458 +
13459 +/** Type for a mutex */
13460 +typedef struct dwc_mutex dwc_mutex_t;
13461 +
13462 +/* For Linux Mutex Debugging make it inline because the debugging routines use
13463 + * the symbol to determine recursive locking.  This makes it falsely think
13464 + * recursive locking occurs. */
13465 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13466 +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
13467 +       __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
13468 +       mutex_init((struct mutex *)__mutexp); \
13469 +})
13470 +#endif
13471 +
13472 +/** Allocate a mutex */
13473 +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
13474 +#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
13475 +
13476 +/* For memory leak debugging when using Linux Mutex Debugging */
13477 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13478 +#define DWC_MUTEX_FREE(__mutexp) do { \
13479 +       mutex_destroy((struct mutex *)__mutexp); \
13480 +       DWC_FREE(__mutexp); \
13481 +} while(0)
13482 +#else
13483 +/** Free a mutex */
13484 +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
13485 +#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
13486 +#endif
13487 +
13488 +/** Lock a mutex */
13489 +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
13490 +#define dwc_mutex_lock DWC_MUTEX_LOCK
13491 +
13492 +/** Non-blocking lock returns 1 on successful lock. */
13493 +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
13494 +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
13495 +
13496 +/** Unlock a mutex */
13497 +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
13498 +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
13499 +
13500 +
13501 +/** @name Time */
13502 +
13503 +/** Microsecond delay.
13504 + *
13505 + * @param usecs  Microseconds to delay.
13506 + */
13507 +extern void DWC_UDELAY(uint32_t usecs);
13508 +#define dwc_udelay DWC_UDELAY
13509 +
13510 +/** Millisecond delay.
13511 + *
13512 + * @param msecs  Milliseconds to delay.
13513 + */
13514 +extern void DWC_MDELAY(uint32_t msecs);
13515 +#define dwc_mdelay DWC_MDELAY
13516 +
13517 +/** Non-busy waiting.
13518 + * Sleeps for specified number of milliseconds.
13519 + *
13520 + * @param msecs Milliseconds to sleep.
13521 + */
13522 +extern void DWC_MSLEEP(uint32_t msecs);
13523 +#define dwc_msleep DWC_MSLEEP
13524 +
13525 +/**
13526 + * Returns number of milliseconds since boot.
13527 + */
13528 +extern uint32_t DWC_TIME(void);
13529 +#define dwc_time DWC_TIME
13530 +
13531 +
13532 +
13533 +
13534 +/* @mainpage DWC Portability and Common Library
13535 + *
13536 + * This is the documentation for the DWC Portability and Common Library.
13537 + *
13538 + * @section intro Introduction
13539 + *
13540 + * The DWC Portability library consists of wrapper calls and data structures to
13541 + * all low-level functions which are typically provided by the OS.  The WUDEV
13542 + * driver uses only these functions.  In order to port the WUDEV driver, only
13543 + * the functions in this library need to be re-implemented, with the same
13544 + * behavior as documented here.
13545 + *
13546 + * The Common library consists of higher level functions, which rely only on
13547 + * calling the functions from the DWC Portability library.  These common
13548 + * routines are shared across modules.  Some of the common libraries need to be
13549 + * used directly by the driver programmer when porting WUDEV.  Such as the
13550 + * parameter and notification libraries.
13551 + *
13552 + * @section low Portability Library OS Wrapper Functions
13553 + *
13554 + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
13555 + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of
13556 + * these functions are included in the dwc_os.h file.
13557 + *
13558 + * There are many functions here covering a wide array of OS services.  Please
13559 + * see dwc_os.h for details, and implementation notes for each function.
13560 + *
13561 + * @section common Common Library Functions
13562 + *
13563 + * Any function starting with dwc and in all lowercase is a common library
13564 + * routine.  These functions have a portable implementation and do not need to
13565 + * be reimplemented when porting.  The common routines can be used by any
13566 + * driver, and some must be used by the end user to control the drivers.  For
13567 + * example, you must use the Parameter common library in order to set the
13568 + * parameters in the WUDEV module.
13569 + *
13570 + * The common libraries consist of the following:
13571 + *
13572 + * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h
13573 + * - Parameters - Used internally and can be used by end-user.  See dwc_params.h
13574 + * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h
13575 + * - Lists - Used internally and can be used by end-user.  See dwc_list.h
13576 + * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h
13577 + * - Modpow - Used internally only.  See dwc_modpow.h
13578 + * - DH - Used internally only.  See dwc_dh.h
13579 + * - Crypto - Used internally only.  See dwc_crypto.h
13580 + *
13581 + *
13582 + * @section prereq Prerequistes For dwc_os.h
13583 + * @subsection types Data Types
13584 + *
13585 + * The dwc_os.h file assumes that several low-level data types are pre defined for the
13586 + * compilation environment.  These data types are:
13587 + *
13588 + * - uint8_t - unsigned 8-bit data type
13589 + * - int8_t - signed 8-bit data type
13590 + * - uint16_t - unsigned 16-bit data type
13591 + * - int16_t - signed 16-bit data type
13592 + * - uint32_t - unsigned 32-bit data type
13593 + * - int32_t - signed 32-bit data type
13594 + * - uint64_t - unsigned 64-bit data type
13595 + * - int64_t - signed 64-bit data type
13596 + *
13597 + * Ensure that these are defined before using dwc_os.h.  The easiest way to do
13598 + * that is to modify the top of the file to include the appropriate header.
13599 + * This is already done for the Linux environment.  If the DWC_LINUX macro is
13600 + * defined, the correct header will be added.  A standard header <stdint.h> is
13601 + * also used for environments where standard C headers are available.
13602 + *
13603 + * @subsection stdarg Variable Arguments
13604 + *
13605 + * Variable arguments are provided by a standard C header <stdarg.h>.  it is
13606 + * available in Both the Linux and ANSI C enviornment.  An equivalent must be
13607 + * provided in your enviornment in order to use dwc_os.h with the debug and
13608 + * tracing message functionality.
13609 + *
13610 + * @subsection thread Threading
13611 + *
13612 + * WUDEV Core must be run on an operating system that provides for multiple
13613 + * threads/processes.  Threading can be implemented in many ways, even in
13614 + * embedded systems without an operating system.  At the bare minimum, the
13615 + * system should be able to start any number of processes at any time to handle
13616 + * special work.  It need not be a pre-emptive system.  Process context can
13617 + * change upon a call to a blocking function.  The hardware interrupt context
13618 + * that calls the module's ISR() function must be differentiable from process
13619 + * context, even if your processes are impemented via a hardware interrupt.
13620 + * Further locking mechanism between process must exist (or be implemented), and
13621 + * process context must have a way to disable interrupts for a period of time to
13622 + * lock them out.  If all of this exists, the functions in dwc_os.h related to
13623 + * threading should be able to be implemented with the defined behavior.
13624 + *
13625 + */
13626 +
13627 +#ifdef __cplusplus
13628 +}
13629 +#endif
13630 +
13631 +#endif /* _DWC_OS_H_ */
13632 diff --git a/drivers/usb/host/dwc_common_port/usb.h b/drivers/usb/host/dwc_common_port/usb.h
13633 new file mode 100644
13634 index 0000000..27bda82
13635 --- /dev/null
13636 +++ b/drivers/usb/host/dwc_common_port/usb.h
13637 @@ -0,0 +1,946 @@
13638 +/*
13639 + * Copyright (c) 1998 The NetBSD Foundation, Inc.
13640 + * All rights reserved.
13641 + *
13642 + * This code is derived from software contributed to The NetBSD Foundation
13643 + * by Lennart Augustsson (lennart@augustsson.net) at
13644 + * Carlstedt Research & Technology.
13645 + *
13646 + * Redistribution and use in source and binary forms, with or without
13647 + * modification, are permitted provided that the following conditions
13648 + * are met:
13649 + * 1. Redistributions of source code must retain the above copyright
13650 + *    notice, this list of conditions and the following disclaimer.
13651 + * 2. Redistributions in binary form must reproduce the above copyright
13652 + *    notice, this list of conditions and the following disclaimer in the
13653 + *    documentation and/or other materials provided with the distribution.
13654 + * 3. All advertising materials mentioning features or use of this software
13655 + *    must display the following acknowledgement:
13656 + *        This product includes software developed by the NetBSD
13657 + *        Foundation, Inc. and its contributors.
13658 + * 4. Neither the name of The NetBSD Foundation nor the names of its
13659 + *    contributors may be used to endorse or promote products derived
13660 + *    from this software without specific prior written permission.
13661 + *
13662 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
13663 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13664 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13665 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
13666 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13667 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13668 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13669 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13670 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13671 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13672 + * POSSIBILITY OF SUCH DAMAGE.
13673 + */
13674 +
13675 +/* Modified by Synopsys, Inc, 12/12/2007 */
13676 +
13677 +
13678 +#ifndef _USB_H_
13679 +#define _USB_H_
13680 +
13681 +#ifdef __cplusplus
13682 +extern "C" {
13683 +#endif
13684 +
13685 +/*
13686 + * The USB records contain some unaligned little-endian word
13687 + * components.  The U[SG]ETW macros take care of both the alignment
13688 + * and endian problem and should always be used to access non-byte
13689 + * values.
13690 + */
13691 +typedef u_int8_t uByte;
13692 +typedef u_int8_t uWord[2];
13693 +typedef u_int8_t uDWord[4];
13694 +
13695 +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
13696 +#define UCONSTW(x)     { (x) & 0xff, ((x) >> 8) & 0xff }
13697 +#define UCONSTDW(x)    { (x) & 0xff, ((x) >> 8) & 0xff, \
13698 +                         ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
13699 +
13700 +#if 1
13701 +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
13702 +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
13703 +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
13704 +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
13705 +                    (w)[1] = (u_int8_t)((v) >> 8), \
13706 +                    (w)[2] = (u_int8_t)((v) >> 16), \
13707 +                    (w)[3] = (u_int8_t)((v) >> 24))
13708 +#else
13709 +/*
13710 + * On little-endian machines that can handle unanliged accesses
13711 + * (e.g. i386) these macros can be replaced by the following.
13712 + */
13713 +#define UGETW(w) (*(u_int16_t *)(w))
13714 +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
13715 +#define UGETDW(w) (*(u_int32_t *)(w))
13716 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
13717 +#endif
13718 +
13719 +/*
13720 + * Macros for accessing UAS IU fields, which are big-endian
13721 + */
13722 +#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
13723 +#define IUCONSTW(x)    { ((x) >> 8) & 0xff, (x) & 0xff }
13724 +#define IUCONSTDW(x)   { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
13725 +                       ((x) >> 8) & 0xff, (x) & 0xff }
13726 +#define IUGETW(w) (((w)[0] << 8) | (w)[1])
13727 +#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
13728 +#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
13729 +#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
13730 +                     (w)[1] = (u_int8_t)((v) >> 16), \
13731 +                     (w)[2] = (u_int8_t)((v) >> 8), \
13732 +                     (w)[3] = (u_int8_t)(v))
13733 +
13734 +#define UPACKED __attribute__((__packed__))
13735 +
13736 +typedef struct {
13737 +       uByte           bmRequestType;
13738 +       uByte           bRequest;
13739 +       uWord           wValue;
13740 +       uWord           wIndex;
13741 +       uWord           wLength;
13742 +} UPACKED usb_device_request_t;
13743 +
13744 +#define UT_GET_DIR(a) ((a) & 0x80)
13745 +#define UT_WRITE               0x00
13746 +#define UT_READ                        0x80
13747 +
13748 +#define UT_GET_TYPE(a) ((a) & 0x60)
13749 +#define UT_STANDARD            0x00
13750 +#define UT_CLASS               0x20
13751 +#define UT_VENDOR              0x40
13752 +
13753 +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
13754 +#define UT_DEVICE              0x00
13755 +#define UT_INTERFACE           0x01
13756 +#define UT_ENDPOINT            0x02
13757 +#define UT_OTHER               0x03
13758 +
13759 +#define UT_READ_DEVICE         (UT_READ  | UT_STANDARD | UT_DEVICE)
13760 +#define UT_READ_INTERFACE      (UT_READ  | UT_STANDARD | UT_INTERFACE)
13761 +#define UT_READ_ENDPOINT       (UT_READ  | UT_STANDARD | UT_ENDPOINT)
13762 +#define UT_WRITE_DEVICE                (UT_WRITE | UT_STANDARD | UT_DEVICE)
13763 +#define UT_WRITE_INTERFACE     (UT_WRITE | UT_STANDARD | UT_INTERFACE)
13764 +#define UT_WRITE_ENDPOINT      (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
13765 +#define UT_READ_CLASS_DEVICE   (UT_READ  | UT_CLASS | UT_DEVICE)
13766 +#define UT_READ_CLASS_INTERFACE        (UT_READ  | UT_CLASS | UT_INTERFACE)
13767 +#define UT_READ_CLASS_OTHER    (UT_READ  | UT_CLASS | UT_OTHER)
13768 +#define UT_READ_CLASS_ENDPOINT (UT_READ  | UT_CLASS | UT_ENDPOINT)
13769 +#define UT_WRITE_CLASS_DEVICE  (UT_WRITE | UT_CLASS | UT_DEVICE)
13770 +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
13771 +#define UT_WRITE_CLASS_OTHER   (UT_WRITE | UT_CLASS | UT_OTHER)
13772 +#define UT_WRITE_CLASS_ENDPOINT        (UT_WRITE | UT_CLASS | UT_ENDPOINT)
13773 +#define UT_READ_VENDOR_DEVICE  (UT_READ  | UT_VENDOR | UT_DEVICE)
13774 +#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
13775 +#define UT_READ_VENDOR_OTHER   (UT_READ  | UT_VENDOR | UT_OTHER)
13776 +#define UT_READ_VENDOR_ENDPOINT        (UT_READ  | UT_VENDOR | UT_ENDPOINT)
13777 +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
13778 +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
13779 +#define UT_WRITE_VENDOR_OTHER  (UT_WRITE | UT_VENDOR | UT_OTHER)
13780 +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
13781 +
13782 +/* Requests */
13783 +#define UR_GET_STATUS          0x00
13784 +#define  USTAT_STANDARD_STATUS  0x00
13785 +#define  WUSTAT_WUSB_FEATURE    0x01
13786 +#define  WUSTAT_CHANNEL_INFO    0x02
13787 +#define  WUSTAT_RECEIVED_DATA   0x03
13788 +#define  WUSTAT_MAS_AVAILABILITY 0x04
13789 +#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05
13790 +#define UR_CLEAR_FEATURE       0x01
13791 +#define UR_SET_FEATURE         0x03
13792 +#define UR_SET_AND_TEST_FEATURE 0x0c
13793 +#define UR_SET_ADDRESS         0x05
13794 +#define UR_GET_DESCRIPTOR      0x06
13795 +#define  UDESC_DEVICE          0x01
13796 +#define  UDESC_CONFIG          0x02
13797 +#define  UDESC_STRING          0x03
13798 +#define  UDESC_INTERFACE       0x04
13799 +#define  UDESC_ENDPOINT                0x05
13800 +#define  UDESC_SS_USB_COMPANION        0x30
13801 +#define  UDESC_DEVICE_QUALIFIER        0x06
13802 +#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07
13803 +#define  UDESC_INTERFACE_POWER 0x08
13804 +#define  UDESC_OTG             0x09
13805 +#define  WUDESC_SECURITY       0x0c
13806 +#define  WUDESC_KEY            0x0d
13807 +#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
13808 +#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
13809 +#define    WUD_KEY_TYPE_ASSOC    0x01
13810 +#define    WUD_KEY_TYPE_GTK      0x02
13811 +#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
13812 +#define    WUD_KEY_ORIGIN_HOST   0x00
13813 +#define    WUD_KEY_ORIGIN_DEVICE 0x01
13814 +#define  WUDESC_ENCRYPTION_TYPE        0x0e
13815 +#define  WUDESC_BOS            0x0f
13816 +#define  WUDESC_DEVICE_CAPABILITY 0x10
13817 +#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
13818 +#define  UDESC_BOS             0x0f
13819 +#define  UDESC_DEVICE_CAPABILITY 0x10
13820 +#define  UDESC_CS_DEVICE       0x21    /* class specific */
13821 +#define  UDESC_CS_CONFIG       0x22
13822 +#define  UDESC_CS_STRING       0x23
13823 +#define  UDESC_CS_INTERFACE    0x24
13824 +#define  UDESC_CS_ENDPOINT     0x25
13825 +#define  UDESC_HUB             0x29
13826 +#define UR_SET_DESCRIPTOR      0x07
13827 +#define UR_GET_CONFIG          0x08
13828 +#define UR_SET_CONFIG          0x09
13829 +#define UR_GET_INTERFACE       0x0a
13830 +#define UR_SET_INTERFACE       0x0b
13831 +#define UR_SYNCH_FRAME         0x0c
13832 +#define WUR_SET_ENCRYPTION      0x0d
13833 +#define WUR_GET_ENCRYPTION     0x0e
13834 +#define WUR_SET_HANDSHAKE      0x0f
13835 +#define WUR_GET_HANDSHAKE      0x10
13836 +#define WUR_SET_CONNECTION     0x11
13837 +#define WUR_SET_SECURITY_DATA  0x12
13838 +#define WUR_GET_SECURITY_DATA  0x13
13839 +#define WUR_SET_WUSB_DATA      0x14
13840 +#define  WUDATA_DRPIE_INFO     0x01
13841 +#define  WUDATA_TRANSMIT_DATA  0x02
13842 +#define  WUDATA_TRANSMIT_PARAMS        0x03
13843 +#define  WUDATA_RECEIVE_PARAMS 0x04
13844 +#define  WUDATA_TRANSMIT_POWER 0x05
13845 +#define WUR_LOOPBACK_DATA_WRITE        0x15
13846 +#define WUR_LOOPBACK_DATA_READ 0x16
13847 +#define WUR_SET_INTERFACE_DS   0x17
13848 +
13849 +/* Feature numbers */
13850 +#define UF_ENDPOINT_HALT       0
13851 +#define UF_DEVICE_REMOTE_WAKEUP        1
13852 +#define UF_TEST_MODE           2
13853 +#define UF_DEVICE_B_HNP_ENABLE 3
13854 +#define UF_DEVICE_A_HNP_SUPPORT        4
13855 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
13856 +#define WUF_WUSB               3
13857 +#define  WUF_TX_DRPIE          0x0
13858 +#define  WUF_DEV_XMIT_PACKET   0x1
13859 +#define  WUF_COUNT_PACKETS     0x2
13860 +#define  WUF_CAPTURE_PACKETS   0x3
13861 +#define UF_FUNCTION_SUSPEND    0
13862 +#define UF_U1_ENABLE           48
13863 +#define UF_U2_ENABLE           49
13864 +#define UF_LTM_ENABLE          50
13865 +
13866 +/* Class requests from the USB 2.0 hub spec, table 11-15 */
13867 +#define UCR_CLEAR_HUB_FEATURE          (0x2000 | UR_CLEAR_FEATURE)
13868 +#define UCR_CLEAR_PORT_FEATURE         (0x2300 | UR_CLEAR_FEATURE)
13869 +#define UCR_GET_HUB_DESCRIPTOR         (0xa000 | UR_GET_DESCRIPTOR)
13870 +#define UCR_GET_HUB_STATUS             (0xa000 | UR_GET_STATUS)
13871 +#define UCR_GET_PORT_STATUS            (0xa300 | UR_GET_STATUS)
13872 +#define UCR_SET_HUB_FEATURE            (0x2000 | UR_SET_FEATURE)
13873 +#define UCR_SET_PORT_FEATURE           (0x2300 | UR_SET_FEATURE)
13874 +#define UCR_SET_AND_TEST_PORT_FEATURE  (0xa300 | UR_SET_AND_TEST_FEATURE)
13875 +
13876 +#ifdef _MSC_VER
13877 +#include <pshpack1.h>
13878 +#endif
13879 +
13880 +typedef struct {
13881 +       uByte           bLength;
13882 +       uByte           bDescriptorType;
13883 +       uByte           bDescriptorSubtype;
13884 +} UPACKED usb_descriptor_t;
13885 +
13886 +typedef struct {
13887 +       uByte           bLength;
13888 +       uByte           bDescriptorType;
13889 +} UPACKED usb_descriptor_header_t;
13890 +
13891 +typedef struct {
13892 +       uByte           bLength;
13893 +       uByte           bDescriptorType;
13894 +       uWord           bcdUSB;
13895 +#define UD_USB_2_0             0x0200
13896 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
13897 +       uByte           bDeviceClass;
13898 +       uByte           bDeviceSubClass;
13899 +       uByte           bDeviceProtocol;
13900 +       uByte           bMaxPacketSize;
13901 +       /* The fields below are not part of the initial descriptor. */
13902 +       uWord           idVendor;
13903 +       uWord           idProduct;
13904 +       uWord           bcdDevice;
13905 +       uByte           iManufacturer;
13906 +       uByte           iProduct;
13907 +       uByte           iSerialNumber;
13908 +       uByte           bNumConfigurations;
13909 +} UPACKED usb_device_descriptor_t;
13910 +#define USB_DEVICE_DESCRIPTOR_SIZE 18
13911 +
13912 +typedef struct {
13913 +       uByte           bLength;
13914 +       uByte           bDescriptorType;
13915 +       uWord           wTotalLength;
13916 +       uByte           bNumInterface;
13917 +       uByte           bConfigurationValue;
13918 +       uByte           iConfiguration;
13919 +#define UC_ATT_ONE             (1 << 7)        /* must be set */
13920 +#define UC_ATT_SELFPOWER       (1 << 6)        /* self powered */
13921 +#define UC_ATT_WAKEUP          (1 << 5)        /* can wakeup */
13922 +#define UC_ATT_BATTERY         (1 << 4)        /* battery powered */
13923 +       uByte           bmAttributes;
13924 +#define UC_BUS_POWERED         0x80
13925 +#define UC_SELF_POWERED                0x40
13926 +#define UC_REMOTE_WAKEUP       0x20
13927 +       uByte           bMaxPower; /* max current in 2 mA units */
13928 +#define UC_POWER_FACTOR 2
13929 +} UPACKED usb_config_descriptor_t;
13930 +#define USB_CONFIG_DESCRIPTOR_SIZE 9
13931 +
13932 +typedef struct {
13933 +       uByte           bLength;
13934 +       uByte           bDescriptorType;
13935 +       uByte           bInterfaceNumber;
13936 +       uByte           bAlternateSetting;
13937 +       uByte           bNumEndpoints;
13938 +       uByte           bInterfaceClass;
13939 +       uByte           bInterfaceSubClass;
13940 +       uByte           bInterfaceProtocol;
13941 +       uByte           iInterface;
13942 +} UPACKED usb_interface_descriptor_t;
13943 +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
13944 +
13945 +typedef struct {
13946 +       uByte           bLength;
13947 +       uByte           bDescriptorType;
13948 +       uByte           bEndpointAddress;
13949 +#define UE_GET_DIR(a)  ((a) & 0x80)
13950 +#define UE_SET_DIR(a,d)        ((a) | (((d)&1) << 7))
13951 +#define UE_DIR_IN      0x80
13952 +#define UE_DIR_OUT     0x00
13953 +#define UE_ADDR                0x0f
13954 +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
13955 +       uByte           bmAttributes;
13956 +#define UE_XFERTYPE    0x03
13957 +#define  UE_CONTROL    0x00
13958 +#define  UE_ISOCHRONOUS        0x01
13959 +#define  UE_BULK       0x02
13960 +#define  UE_INTERRUPT  0x03
13961 +#define UE_GET_XFERTYPE(a)     ((a) & UE_XFERTYPE)
13962 +#define UE_ISO_TYPE    0x0c
13963 +#define  UE_ISO_ASYNC  0x04
13964 +#define  UE_ISO_ADAPT  0x08
13965 +#define  UE_ISO_SYNC   0x0c
13966 +#define UE_GET_ISO_TYPE(a)     ((a) & UE_ISO_TYPE)
13967 +       uWord           wMaxPacketSize;
13968 +       uByte           bInterval;
13969 +} UPACKED usb_endpoint_descriptor_t;
13970 +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
13971 +
13972 +typedef struct ss_endpoint_companion_descriptor {
13973 +       uByte bLength;
13974 +       uByte bDescriptorType;
13975 +       uByte bMaxBurst;
13976 +#define USSE_GET_MAX_STREAMS(a)                ((a) & 0x1f)
13977 +#define USSE_SET_MAX_STREAMS(a, b)     ((a) | ((b) & 0x1f))
13978 +#define USSE_GET_MAX_PACKET_NUM(a)     ((a) & 0x03)
13979 +#define USSE_SET_MAX_PACKET_NUM(a, b)  ((a) | ((b) & 0x03))
13980 +       uByte bmAttributes;
13981 +       uWord wBytesPerInterval;
13982 +} UPACKED ss_endpoint_companion_descriptor_t;
13983 +#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
13984 +
13985 +typedef struct {
13986 +       uByte           bLength;
13987 +       uByte           bDescriptorType;
13988 +       uWord           bString[127];
13989 +} UPACKED usb_string_descriptor_t;
13990 +#define USB_MAX_STRING_LEN 128
13991 +#define USB_LANGUAGE_TABLE 0   /* # of the string language id table */
13992 +
13993 +/* Hub specific request */
13994 +#define UR_GET_BUS_STATE       0x02
13995 +#define UR_CLEAR_TT_BUFFER     0x08
13996 +#define UR_RESET_TT            0x09
13997 +#define UR_GET_TT_STATE                0x0a
13998 +#define UR_STOP_TT             0x0b
13999 +
14000 +/* Hub features */
14001 +#define UHF_C_HUB_LOCAL_POWER  0
14002 +#define UHF_C_HUB_OVER_CURRENT 1
14003 +#define UHF_PORT_CONNECTION    0
14004 +#define UHF_PORT_ENABLE                1
14005 +#define UHF_PORT_SUSPEND       2
14006 +#define UHF_PORT_OVER_CURRENT  3
14007 +#define UHF_PORT_RESET         4
14008 +#define UHF_PORT_L1            5
14009 +#define UHF_PORT_POWER         8
14010 +#define UHF_PORT_LOW_SPEED     9
14011 +#define UHF_PORT_HIGH_SPEED    10
14012 +#define UHF_C_PORT_CONNECTION  16
14013 +#define UHF_C_PORT_ENABLE      17
14014 +#define UHF_C_PORT_SUSPEND     18
14015 +#define UHF_C_PORT_OVER_CURRENT        19
14016 +#define UHF_C_PORT_RESET       20
14017 +#define UHF_C_PORT_L1          23
14018 +#define UHF_PORT_TEST          21
14019 +#define UHF_PORT_INDICATOR     22
14020 +
14021 +typedef struct {
14022 +       uByte           bDescLength;
14023 +       uByte           bDescriptorType;
14024 +       uByte           bNbrPorts;
14025 +       uWord           wHubCharacteristics;
14026 +#define UHD_PWR                        0x0003
14027 +#define  UHD_PWR_GANGED                0x0000
14028 +#define  UHD_PWR_INDIVIDUAL    0x0001
14029 +#define  UHD_PWR_NO_SWITCH     0x0002
14030 +#define UHD_COMPOUND           0x0004
14031 +#define UHD_OC                 0x0018
14032 +#define  UHD_OC_GLOBAL         0x0000
14033 +#define  UHD_OC_INDIVIDUAL     0x0008
14034 +#define  UHD_OC_NONE           0x0010
14035 +#define UHD_TT_THINK           0x0060
14036 +#define  UHD_TT_THINK_8                0x0000
14037 +#define  UHD_TT_THINK_16       0x0020
14038 +#define  UHD_TT_THINK_24       0x0040
14039 +#define  UHD_TT_THINK_32       0x0060
14040 +#define UHD_PORT_IND           0x0080
14041 +       uByte           bPwrOn2PwrGood; /* delay in 2 ms units */
14042 +#define UHD_PWRON_FACTOR 2
14043 +       uByte           bHubContrCurrent;
14044 +       uByte           DeviceRemovable[32]; /* max 255 ports */
14045 +#define UHD_NOT_REMOV(desc, i) \
14046 +    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
14047 +       /* deprecated */ uByte          PortPowerCtrlMask[1];
14048 +} UPACKED usb_hub_descriptor_t;
14049 +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
14050 +
14051 +typedef struct {
14052 +       uByte           bLength;
14053 +       uByte           bDescriptorType;
14054 +       uWord           bcdUSB;
14055 +       uByte           bDeviceClass;
14056 +       uByte           bDeviceSubClass;
14057 +       uByte           bDeviceProtocol;
14058 +       uByte           bMaxPacketSize0;
14059 +       uByte           bNumConfigurations;
14060 +       uByte           bReserved;
14061 +} UPACKED usb_device_qualifier_t;
14062 +#define USB_DEVICE_QUALIFIER_SIZE 10
14063 +
14064 +typedef struct {
14065 +       uByte           bLength;
14066 +       uByte           bDescriptorType;
14067 +       uByte           bmAttributes;
14068 +#define UOTG_SRP       0x01
14069 +#define UOTG_HNP       0x02
14070 +} UPACKED usb_otg_descriptor_t;
14071 +
14072 +/* OTG feature selectors */
14073 +#define UOTG_B_HNP_ENABLE      3
14074 +#define UOTG_A_HNP_SUPPORT     4
14075 +#define UOTG_A_ALT_HNP_SUPPORT 5
14076 +
14077 +typedef struct {
14078 +       uWord           wStatus;
14079 +/* Device status flags */
14080 +#define UDS_SELF_POWERED               0x0001
14081 +#define UDS_REMOTE_WAKEUP              0x0002
14082 +/* Endpoint status flags */
14083 +#define UES_HALT                       0x0001
14084 +} UPACKED usb_status_t;
14085 +
14086 +typedef struct {
14087 +       uWord           wHubStatus;
14088 +#define UHS_LOCAL_POWER                        0x0001
14089 +#define UHS_OVER_CURRENT               0x0002
14090 +       uWord           wHubChange;
14091 +} UPACKED usb_hub_status_t;
14092 +
14093 +typedef struct {
14094 +       uWord           wPortStatus;
14095 +#define UPS_CURRENT_CONNECT_STATUS     0x0001
14096 +#define UPS_PORT_ENABLED               0x0002
14097 +#define UPS_SUSPEND                    0x0004
14098 +#define UPS_OVERCURRENT_INDICATOR      0x0008
14099 +#define UPS_RESET                      0x0010
14100 +#define UPS_PORT_POWER                 0x0100
14101 +#define UPS_LOW_SPEED                  0x0200
14102 +#define UPS_HIGH_SPEED                 0x0400
14103 +#define UPS_PORT_TEST                  0x0800
14104 +#define UPS_PORT_INDICATOR             0x1000
14105 +       uWord           wPortChange;
14106 +#define UPS_C_CONNECT_STATUS           0x0001
14107 +#define UPS_C_PORT_ENABLED             0x0002
14108 +#define UPS_C_SUSPEND                  0x0004
14109 +#define UPS_C_OVERCURRENT_INDICATOR    0x0008
14110 +#define UPS_C_PORT_RESET               0x0010
14111 +} UPACKED usb_port_status_t;
14112 +
14113 +#ifdef _MSC_VER
14114 +#include <poppack.h>
14115 +#endif
14116 +
14117 +/* Device class codes */
14118 +#define UDCLASS_IN_INTERFACE   0x00
14119 +#define UDCLASS_COMM           0x02
14120 +#define UDCLASS_HUB            0x09
14121 +#define  UDSUBCLASS_HUB                0x00
14122 +#define  UDPROTO_FSHUB         0x00
14123 +#define  UDPROTO_HSHUBSTT      0x01
14124 +#define  UDPROTO_HSHUBMTT      0x02
14125 +#define UDCLASS_DIAGNOSTIC     0xdc
14126 +#define UDCLASS_WIRELESS       0xe0
14127 +#define  UDSUBCLASS_RF         0x01
14128 +#define   UDPROTO_BLUETOOTH    0x01
14129 +#define UDCLASS_VENDOR         0xff
14130 +
14131 +/* Interface class codes */
14132 +#define UICLASS_UNSPEC         0x00
14133 +
14134 +#define UICLASS_AUDIO          0x01
14135 +#define  UISUBCLASS_AUDIOCONTROL       1
14136 +#define  UISUBCLASS_AUDIOSTREAM                2
14137 +#define  UISUBCLASS_MIDISTREAM         3
14138 +
14139 +#define UICLASS_CDC            0x02 /* communication */
14140 +#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL  1
14141 +#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL     2
14142 +#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL    3
14143 +#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
14144 +#define  UISUBCLASS_CAPI_CONTROLMODEL          5
14145 +#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
14146 +#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
14147 +#define   UIPROTO_CDC_AT                       1
14148 +
14149 +#define UICLASS_HID            0x03
14150 +#define  UISUBCLASS_BOOT       1
14151 +#define  UIPROTO_BOOT_KEYBOARD 1
14152 +
14153 +#define UICLASS_PHYSICAL       0x05
14154 +
14155 +#define UICLASS_IMAGE          0x06
14156 +
14157 +#define UICLASS_PRINTER                0x07
14158 +#define  UISUBCLASS_PRINTER    1
14159 +#define  UIPROTO_PRINTER_UNI   1
14160 +#define  UIPROTO_PRINTER_BI    2
14161 +#define  UIPROTO_PRINTER_1284  3
14162 +
14163 +#define UICLASS_MASS           0x08
14164 +#define  UISUBCLASS_RBC                1
14165 +#define  UISUBCLASS_SFF8020I   2
14166 +#define  UISUBCLASS_QIC157     3
14167 +#define  UISUBCLASS_UFI                4
14168 +#define  UISUBCLASS_SFF8070I   5
14169 +#define  UISUBCLASS_SCSI       6
14170 +#define  UIPROTO_MASS_CBI_I    0
14171 +#define  UIPROTO_MASS_CBI      1
14172 +#define  UIPROTO_MASS_BBB_OLD  2       /* Not in the spec anymore */
14173 +#define  UIPROTO_MASS_BBB      80      /* 'P' for the Iomega Zip drive */
14174 +
14175 +#define UICLASS_HUB            0x09
14176 +#define  UISUBCLASS_HUB                0
14177 +#define  UIPROTO_FSHUB         0
14178 +#define  UIPROTO_HSHUBSTT      0 /* Yes, same as previous */
14179 +#define  UIPROTO_HSHUBMTT      1
14180 +
14181 +#define UICLASS_CDC_DATA       0x0a
14182 +#define  UISUBCLASS_DATA               0
14183 +#define   UIPROTO_DATA_ISDNBRI         0x30    /* Physical iface */
14184 +#define   UIPROTO_DATA_HDLC            0x31    /* HDLC */
14185 +#define   UIPROTO_DATA_TRANSPARENT     0x32    /* Transparent */
14186 +#define   UIPROTO_DATA_Q921M           0x50    /* Management for Q921 */
14187 +#define   UIPROTO_DATA_Q921            0x51    /* Data for Q921 */
14188 +#define   UIPROTO_DATA_Q921TM          0x52    /* TEI multiplexer for Q921 */
14189 +#define   UIPROTO_DATA_V42BIS          0x90    /* Data compression */
14190 +#define   UIPROTO_DATA_Q931            0x91    /* Euro-ISDN */
14191 +#define   UIPROTO_DATA_V120            0x92    /* V.24 rate adaption */
14192 +#define   UIPROTO_DATA_CAPI            0x93    /* CAPI 2.0 commands */
14193 +#define   UIPROTO_DATA_HOST_BASED      0xfd    /* Host based driver */
14194 +#define   UIPROTO_DATA_PUF             0xfe    /* see Prot. Unit Func. Desc.*/
14195 +#define   UIPROTO_DATA_VENDOR          0xff    /* Vendor specific */
14196 +
14197 +#define UICLASS_SMARTCARD      0x0b
14198 +
14199 +/*#define UICLASS_FIRM_UPD     0x0c*/
14200 +
14201 +#define UICLASS_SECURITY       0x0d
14202 +
14203 +#define UICLASS_DIAGNOSTIC     0xdc
14204 +
14205 +#define UICLASS_WIRELESS       0xe0
14206 +#define  UISUBCLASS_RF                 0x01
14207 +#define   UIPROTO_BLUETOOTH            0x01
14208 +
14209 +#define UICLASS_APPL_SPEC      0xfe
14210 +#define  UISUBCLASS_FIRMWARE_DOWNLOAD  1
14211 +#define  UISUBCLASS_IRDA               2
14212 +#define  UIPROTO_IRDA                  0
14213 +
14214 +#define UICLASS_VENDOR         0xff
14215 +
14216 +#define USB_HUB_MAX_DEPTH 5
14217 +
14218 +/*
14219 + * Minimum time a device needs to be powered down to go through
14220 + * a power cycle.  XXX Are these time in the spec?
14221 + */
14222 +#define USB_POWER_DOWN_TIME    200 /* ms */
14223 +#define USB_PORT_POWER_DOWN_TIME       100 /* ms */
14224 +
14225 +#if 0
14226 +/* These are the values from the spec. */
14227 +#define USB_PORT_RESET_DELAY   10  /* ms */
14228 +#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
14229 +#define USB_PORT_RESET_RECOVERY        10  /* ms */
14230 +#define USB_PORT_POWERUP_DELAY 100 /* ms */
14231 +#define USB_SET_ADDRESS_SETTLE 2   /* ms */
14232 +#define USB_RESUME_DELAY       (20*5)  /* ms */
14233 +#define USB_RESUME_WAIT                10  /* ms */
14234 +#define USB_RESUME_RECOVERY    10  /* ms */
14235 +#define USB_EXTRA_POWER_UP_TIME        0   /* ms */
14236 +#else
14237 +/* Allow for marginal (i.e. non-conforming) devices. */
14238 +#define USB_PORT_RESET_DELAY   50  /* ms */
14239 +#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
14240 +#define USB_PORT_RESET_RECOVERY        250  /* ms */
14241 +#define USB_PORT_POWERUP_DELAY 300 /* ms */
14242 +#define USB_SET_ADDRESS_SETTLE 10  /* ms */
14243 +#define USB_RESUME_DELAY       (50*5)  /* ms */
14244 +#define USB_RESUME_WAIT                50  /* ms */
14245 +#define USB_RESUME_RECOVERY    50  /* ms */
14246 +#define USB_EXTRA_POWER_UP_TIME        20  /* ms */
14247 +#endif
14248 +
14249 +#define USB_MIN_POWER          100 /* mA */
14250 +#define USB_MAX_POWER          500 /* mA */
14251 +
14252 +#define USB_BUS_RESET_DELAY    100 /* ms XXX?*/
14253 +
14254 +#define USB_UNCONFIG_NO 0
14255 +#define USB_UNCONFIG_INDEX (-1)
14256 +
14257 +/*** ioctl() related stuff ***/
14258 +
14259 +struct usb_ctl_request {
14260 +       int     ucr_addr;
14261 +       usb_device_request_t ucr_request;
14262 +       void    *ucr_data;
14263 +       int     ucr_flags;
14264 +#define USBD_SHORT_XFER_OK     0x04    /* allow short reads */
14265 +       int     ucr_actlen;             /* actual length transferred */
14266 +};
14267 +
14268 +struct usb_alt_interface {
14269 +       int     uai_config_index;
14270 +       int     uai_interface_index;
14271 +       int     uai_alt_no;
14272 +};
14273 +
14274 +#define USB_CURRENT_CONFIG_INDEX (-1)
14275 +#define USB_CURRENT_ALT_INDEX (-1)
14276 +
14277 +struct usb_config_desc {
14278 +       int     ucd_config_index;
14279 +       usb_config_descriptor_t ucd_desc;
14280 +};
14281 +
14282 +struct usb_interface_desc {
14283 +       int     uid_config_index;
14284 +       int     uid_interface_index;
14285 +       int     uid_alt_index;
14286 +       usb_interface_descriptor_t uid_desc;
14287 +};
14288 +
14289 +struct usb_endpoint_desc {
14290 +       int     ued_config_index;
14291 +       int     ued_interface_index;
14292 +       int     ued_alt_index;
14293 +       int     ued_endpoint_index;
14294 +       usb_endpoint_descriptor_t ued_desc;
14295 +};
14296 +
14297 +struct usb_full_desc {
14298 +       int     ufd_config_index;
14299 +       u_int   ufd_size;
14300 +       u_char  *ufd_data;
14301 +};
14302 +
14303 +struct usb_string_desc {
14304 +       int     usd_string_index;
14305 +       int     usd_language_id;
14306 +       usb_string_descriptor_t usd_desc;
14307 +};
14308 +
14309 +struct usb_ctl_report_desc {
14310 +       int     ucrd_size;
14311 +       u_char  ucrd_data[1024];        /* filled data size will vary */
14312 +};
14313 +
14314 +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
14315 +
14316 +#define USB_MAX_DEVNAMES 4
14317 +#define USB_MAX_DEVNAMELEN 16
14318 +struct usb_device_info {
14319 +       u_int8_t        udi_bus;
14320 +       u_int8_t        udi_addr;       /* device address */
14321 +       usb_event_cookie_t udi_cookie;
14322 +       char            udi_product[USB_MAX_STRING_LEN];
14323 +       char            udi_vendor[USB_MAX_STRING_LEN];
14324 +       char            udi_release[8];
14325 +       u_int16_t       udi_productNo;
14326 +       u_int16_t       udi_vendorNo;
14327 +       u_int16_t       udi_releaseNo;
14328 +       u_int8_t        udi_class;
14329 +       u_int8_t        udi_subclass;
14330 +       u_int8_t        udi_protocol;
14331 +       u_int8_t        udi_config;
14332 +       u_int8_t        udi_speed;
14333 +#define USB_SPEED_UNKNOWN      0
14334 +#define USB_SPEED_LOW          1
14335 +#define USB_SPEED_FULL         2
14336 +#define USB_SPEED_HIGH         3
14337 +#define USB_SPEED_VARIABLE     4
14338 +#define USB_SPEED_SUPER                5
14339 +       int             udi_power;      /* power consumption in mA, 0 if selfpowered */
14340 +       int             udi_nports;
14341 +       char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
14342 +       u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
14343 +#define USB_PORT_ENABLED 0xff
14344 +#define USB_PORT_SUSPENDED 0xfe
14345 +#define USB_PORT_POWERED 0xfd
14346 +#define USB_PORT_DISABLED 0xfc
14347 +};
14348 +
14349 +struct usb_ctl_report {
14350 +       int     ucr_report;
14351 +       u_char  ucr_data[1024]; /* filled data size will vary */
14352 +};
14353 +
14354 +struct usb_device_stats {
14355 +       u_long  uds_requests[4];        /* indexed by transfer type UE_* */
14356 +};
14357 +
14358 +#define WUSB_MIN_IE                    0x80
14359 +#define WUSB_WCTA_IE                   0x80
14360 +#define WUSB_WCONNECTACK_IE            0x81
14361 +#define WUSB_WHOSTINFO_IE              0x82
14362 +#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
14363 +#define   WUHI_CA_RECONN               0x00
14364 +#define   WUHI_CA_LIMITED              0x01
14365 +#define   WUHI_CA_ALL                  0x03
14366 +#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
14367 +#define WUSB_WCHCHANGEANNOUNCE_IE      0x83
14368 +#define WUSB_WDEV_DISCONNECT_IE                0x84
14369 +#define WUSB_WHOST_DISCONNECT_IE       0x85
14370 +#define WUSB_WRELEASE_CHANNEL_IE       0x86
14371 +#define WUSB_WWORK_IE                  0x87
14372 +#define WUSB_WCHANNEL_STOP_IE          0x88
14373 +#define WUSB_WDEV_KEEPALIVE_IE         0x89
14374 +#define WUSB_WISOCH_DISCARD_IE         0x8A
14375 +#define WUSB_WRESETDEVICE_IE           0x8B
14376 +#define WUSB_WXMIT_PACKET_ADJUST_IE    0x8C
14377 +#define WUSB_MAX_IE                    0x8C
14378 +
14379 +/* Device Notification Types */
14380 +
14381 +#define WUSB_DN_MIN                    0x01
14382 +#define WUSB_DN_CONNECT                        0x01
14383 +# define WUSB_DA_OLDCONN       0x00
14384 +# define WUSB_DA_NEWCONN       0x01
14385 +# define WUSB_DA_SELF_BEACON   0x02
14386 +# define WUSB_DA_DIR_BEACON    0x04
14387 +# define WUSB_DA_NO_BEACON     0x06
14388 +#define WUSB_DN_DISCONNECT             0x02
14389 +#define WUSB_DN_EPRDY                  0x03
14390 +#define WUSB_DN_MASAVAILCHANGED                0x04
14391 +#define WUSB_DN_REMOTEWAKEUP           0x05
14392 +#define WUSB_DN_SLEEP                  0x06
14393 +#define WUSB_DN_ALIVE                  0x07
14394 +#define WUSB_DN_MAX                    0x07
14395 +
14396 +#ifdef _MSC_VER
14397 +#include <pshpack1.h>
14398 +#endif
14399 +
14400 +/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
14401 +typedef struct wusb_hndshk_data {
14402 +       uByte bMessageNumber;
14403 +       uByte bStatus;
14404 +       uByte tTKID[3];
14405 +       uByte bReserved;
14406 +       uByte CDID[16];
14407 +       uByte Nonce[16];
14408 +       uByte MIC[8];
14409 +} UPACKED wusb_hndshk_data_t;
14410 +#define WUSB_HANDSHAKE_LEN_FOR_MIC     38
14411 +
14412 +/* WUSB Connection Context */
14413 +typedef struct wusb_conn_context {
14414 +       uByte CHID [16];
14415 +       uByte CDID [16];
14416 +       uByte CK [16];
14417 +} UPACKED wusb_conn_context_t;
14418 +
14419 +/* WUSB Security Descriptor */
14420 +typedef struct wusb_security_desc {
14421 +       uByte bLength;
14422 +       uByte bDescriptorType;
14423 +       uWord wTotalLength;
14424 +       uByte bNumEncryptionTypes;
14425 +} UPACKED wusb_security_desc_t;
14426 +
14427 +/* WUSB Encryption Type Descriptor */
14428 +typedef struct wusb_encrypt_type_desc {
14429 +       uByte bLength;
14430 +       uByte bDescriptorType;
14431 +
14432 +       uByte bEncryptionType;
14433 +#define WUETD_UNSECURE         0
14434 +#define WUETD_WIRED            1
14435 +#define WUETD_CCM_1            2
14436 +#define WUETD_RSA_1            3
14437 +
14438 +       uByte bEncryptionValue;
14439 +       uByte bAuthKeyIndex;
14440 +} UPACKED wusb_encrypt_type_desc_t;
14441 +
14442 +/* WUSB Key Descriptor */
14443 +typedef struct wusb_key_desc {
14444 +       uByte bLength;
14445 +       uByte bDescriptorType;
14446 +       uByte tTKID[3];
14447 +       uByte bReserved;
14448 +       uByte KeyData[1];       /* variable length */
14449 +} UPACKED wusb_key_desc_t;
14450 +
14451 +/* WUSB BOS Descriptor (Binary device Object Store) */
14452 +typedef struct wusb_bos_desc {
14453 +       uByte bLength;
14454 +       uByte bDescriptorType;
14455 +       uWord wTotalLength;
14456 +       uByte bNumDeviceCaps;
14457 +} UPACKED wusb_bos_desc_t;
14458 +
14459 +#define USB_DEVICE_CAPABILITY_20_EXTENSION     0x02
14460 +typedef struct usb_dev_cap_20_ext_desc {
14461 +       uByte bLength;
14462 +       uByte bDescriptorType;
14463 +       uByte bDevCapabilityType;
14464 +#define USB_20_EXT_LPM                         0x02
14465 +       uDWord bmAttributes;
14466 +} UPACKED usb_dev_cap_20_ext_desc_t;
14467 +
14468 +#define USB_DEVICE_CAPABILITY_SS_USB           0x03
14469 +typedef struct usb_dev_cap_ss_usb {
14470 +       uByte bLength;
14471 +       uByte bDescriptorType;
14472 +       uByte bDevCapabilityType;
14473 +#define USB_DC_SS_USB_LTM_CAPABLE              0x02
14474 +       uByte bmAttributes;
14475 +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW                0x01
14476 +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL       0x02
14477 +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH       0x04
14478 +#define USB_DC_SS_USB_SPEED_SUPPORT_SS         0x08
14479 +       uWord wSpeedsSupported;
14480 +       uByte bFunctionalitySupport;
14481 +       uByte bU1DevExitLat;
14482 +       uWord wU2DevExitLat;
14483 +} UPACKED usb_dev_cap_ss_usb_t;
14484 +
14485 +#define USB_DEVICE_CAPABILITY_CONTAINER_ID     0x04
14486 +typedef struct usb_dev_cap_container_id {
14487 +       uByte bLength;
14488 +       uByte bDescriptorType;
14489 +       uByte bDevCapabilityType;
14490 +       uByte bReserved;
14491 +       uByte containerID[16];
14492 +} UPACKED usb_dev_cap_container_id_t;
14493 +
14494 +/* Device Capability Type Codes */
14495 +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
14496 +
14497 +/* Device Capability Descriptor */
14498 +typedef struct wusb_dev_cap_desc {
14499 +       uByte bLength;
14500 +       uByte bDescriptorType;
14501 +       uByte bDevCapabilityType;
14502 +       uByte caps[1];  /* Variable length */
14503 +} UPACKED wusb_dev_cap_desc_t;
14504 +
14505 +/* Device Capability Descriptor */
14506 +typedef struct wusb_dev_cap_uwb_desc {
14507 +       uByte bLength;
14508 +       uByte bDescriptorType;
14509 +       uByte bDevCapabilityType;
14510 +       uByte bmAttributes;
14511 +       uWord wPHYRates;        /* Bitmap */
14512 +       uByte bmTFITXPowerInfo;
14513 +       uByte bmFFITXPowerInfo;
14514 +       uWord bmBandGroup;
14515 +       uByte bReserved;
14516 +} UPACKED wusb_dev_cap_uwb_desc_t;
14517 +
14518 +/* Wireless USB Endpoint Companion Descriptor */
14519 +typedef struct wusb_endpoint_companion_desc {
14520 +       uByte bLength;
14521 +       uByte bDescriptorType;
14522 +       uByte bMaxBurst;
14523 +       uByte bMaxSequence;
14524 +       uWord wMaxStreamDelay;
14525 +       uWord wOverTheAirPacketSize;
14526 +       uByte bOverTheAirInterval;
14527 +       uByte bmCompAttributes;
14528 +} UPACKED wusb_endpoint_companion_desc_t;
14529 +
14530 +/* Wireless USB Numeric Association M1 Data Structure */
14531 +typedef struct wusb_m1_data {
14532 +       uByte version;
14533 +       uWord langId;
14534 +       uByte deviceFriendlyNameLength;
14535 +       uByte sha_256_m3[32];
14536 +       uByte deviceFriendlyName[256];
14537 +} UPACKED wusb_m1_data_t;
14538 +
14539 +typedef struct wusb_m2_data {
14540 +       uByte version;
14541 +       uWord langId;
14542 +       uByte hostFriendlyNameLength;
14543 +       uByte pkh[384];
14544 +       uByte hostFriendlyName[256];
14545 +} UPACKED wusb_m2_data_t;
14546 +
14547 +typedef struct wusb_m3_data {
14548 +       uByte pkd[384];
14549 +       uByte nd;
14550 +} UPACKED wusb_m3_data_t;
14551 +
14552 +typedef struct wusb_m4_data {
14553 +       uDWord _attributeTypeIdAndLength_1;
14554 +       uWord  associationTypeId;
14555 +
14556 +       uDWord _attributeTypeIdAndLength_2;
14557 +       uWord  associationSubTypeId;
14558 +
14559 +       uDWord _attributeTypeIdAndLength_3;
14560 +       uDWord length;
14561 +
14562 +       uDWord _attributeTypeIdAndLength_4;
14563 +       uDWord associationStatus;
14564 +
14565 +       uDWord _attributeTypeIdAndLength_5;
14566 +       uByte  chid[16];
14567 +
14568 +       uDWord _attributeTypeIdAndLength_6;
14569 +       uByte  cdid[16];
14570 +
14571 +       uDWord _attributeTypeIdAndLength_7;
14572 +       uByte  bandGroups[2];
14573 +} UPACKED wusb_m4_data_t;
14574 +
14575 +#ifdef _MSC_VER
14576 +#include <poppack.h>
14577 +#endif
14578 +
14579 +#ifdef __cplusplus
14580 +}
14581 +#endif
14582 +
14583 +#endif /* _USB_H_ */
14584 diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile
14585 new file mode 100644
14586 index 0000000..236c47c
14587 --- /dev/null
14588 +++ b/drivers/usb/host/dwc_otg/Makefile
14589 @@ -0,0 +1,80 @@
14590 +#
14591 +# Makefile for DWC_otg Highspeed USB controller driver
14592 +#
14593 +
14594 +ifneq ($(KERNELRELEASE),)
14595 +
14596 +# Use the BUS_INTERFACE variable to compile the software for either
14597 +# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.
14598 +ifeq ($(BUS_INTERFACE),)
14599 +#      BUS_INTERFACE = -DPCI_INTERFACE
14600 +#      BUS_INTERFACE = -DLM_INTERFACE
14601 +        BUS_INTERFACE = -DPLATFORM_INTERFACE
14602 +endif
14603 +
14604 +#ccflags-y     += -DDEBUG
14605 +#ccflags-y     += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
14606 +
14607 +# Use one of the following flags to compile the software in host-only or
14608 +# device-only mode.
14609 +#ccflags-y        += -DDWC_HOST_ONLY
14610 +#ccflags-y        += -DDWC_DEVICE_ONLY
14611 +
14612 +ccflags-y      += -Dlinux -DDWC_HS_ELECT_TST
14613 +#ccflags-y     += -DDWC_EN_ISOC
14614 +ccflags-y      += -I$(obj)/../dwc_common_port
14615 +#ccflags-y     += -I$(PORTLIB)
14616 +ccflags-y      += -DDWC_LINUX
14617 +ccflags-y      += $(CFI)
14618 +ccflags-y      += $(BUS_INTERFACE)
14619 +#ccflags-y     += -DDWC_DEV_SRPCAP
14620 +
14621 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
14622 +
14623 +dwc_otg-objs   := dwc_otg_driver.o dwc_otg_attr.o
14624 +dwc_otg-objs   += dwc_otg_cil.o dwc_otg_cil_intr.o
14625 +dwc_otg-objs   += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
14626 +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
14627 +dwc_otg-objs   += dwc_otg_adp.o
14628 +ifneq ($(CFI),)
14629 +dwc_otg-objs   += dwc_otg_cfi.o
14630 +endif
14631 +
14632 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
14633 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
14634 +
14635 +ifneq ($(kernrel3),2.6.20)
14636 +ccflags-y += $(CPPFLAGS)
14637 +endif
14638 +
14639 +else
14640 +
14641 +PWD            := $(shell pwd)
14642 +PORTLIB                := $(PWD)/../dwc_common_port
14643 +
14644 +# Command paths
14645 +CTAGS          := $(CTAGS)
14646 +DOXYGEN                := $(DOXYGEN)
14647 +
14648 +default: portlib
14649 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14650 +
14651 +install: default
14652 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
14653 +       $(MAKE) -C$(KDIR) M=$(PWD) modules_install
14654 +
14655 +portlib:
14656 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14657 +       cp $(PORTLIB)/Module.symvers $(PWD)/
14658 +
14659 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
14660 +       $(DOXYGEN) doc/doxygen.cfg
14661 +
14662 +tags:  $(wildcard *.[hc])
14663 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
14664 +
14665 +
14666 +clean:
14667 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
14668 +
14669 +endif
14670 diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14671 new file mode 100644
14672 index 0000000..712b057
14673 --- /dev/null
14674 +++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14675 @@ -0,0 +1,224 @@
14676 +# Doxyfile 1.3.9.1
14677 +
14678 +#---------------------------------------------------------------------------
14679 +# Project related configuration options
14680 +#---------------------------------------------------------------------------
14681 +PROJECT_NAME           = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"
14682 +PROJECT_NUMBER         = v3.00a
14683 +OUTPUT_DIRECTORY       = ./doc/
14684 +CREATE_SUBDIRS         = NO
14685 +OUTPUT_LANGUAGE        = English
14686 +BRIEF_MEMBER_DESC      = YES
14687 +REPEAT_BRIEF           = YES
14688 +ABBREVIATE_BRIEF       = "The $name class" \
14689 +                         "The $name widget" \
14690 +                         "The $name file" \
14691 +                         is \
14692 +                         provides \
14693 +                         specifies \
14694 +                         contains \
14695 +                         represents \
14696 +                         a \
14697 +                         an \
14698 +                         the
14699 +ALWAYS_DETAILED_SEC    = NO
14700 +INLINE_INHERITED_MEMB  = NO
14701 +FULL_PATH_NAMES        = NO
14702 +STRIP_FROM_PATH        =
14703 +STRIP_FROM_INC_PATH    =
14704 +SHORT_NAMES            = NO
14705 +JAVADOC_AUTOBRIEF      = YES
14706 +MULTILINE_CPP_IS_BRIEF = NO
14707 +INHERIT_DOCS           = YES
14708 +DISTRIBUTE_GROUP_DOC   = NO
14709 +TAB_SIZE               = 8
14710 +ALIASES                =
14711 +OPTIMIZE_OUTPUT_FOR_C  = YES
14712 +OPTIMIZE_OUTPUT_JAVA   = NO
14713 +SUBGROUPING            = YES
14714 +#---------------------------------------------------------------------------
14715 +# Build related configuration options
14716 +#---------------------------------------------------------------------------
14717 +EXTRACT_ALL            = NO
14718 +EXTRACT_PRIVATE        = YES
14719 +EXTRACT_STATIC         = YES
14720 +EXTRACT_LOCAL_CLASSES  = YES
14721 +EXTRACT_LOCAL_METHODS  = NO
14722 +HIDE_UNDOC_MEMBERS     = NO
14723 +HIDE_UNDOC_CLASSES     = NO
14724 +HIDE_FRIEND_COMPOUNDS  = NO
14725 +HIDE_IN_BODY_DOCS      = NO
14726 +INTERNAL_DOCS          = NO
14727 +CASE_SENSE_NAMES       = NO
14728 +HIDE_SCOPE_NAMES       = NO
14729 +SHOW_INCLUDE_FILES     = YES
14730 +INLINE_INFO            = YES
14731 +SORT_MEMBER_DOCS       = NO
14732 +SORT_BRIEF_DOCS        = NO
14733 +SORT_BY_SCOPE_NAME     = NO
14734 +GENERATE_TODOLIST      = YES
14735 +GENERATE_TESTLIST      = YES
14736 +GENERATE_BUGLIST       = YES
14737 +GENERATE_DEPRECATEDLIST= YES
14738 +ENABLED_SECTIONS       =
14739 +MAX_INITIALIZER_LINES  = 30
14740 +SHOW_USED_FILES        = YES
14741 +SHOW_DIRECTORIES       = YES
14742 +#---------------------------------------------------------------------------
14743 +# configuration options related to warning and progress messages
14744 +#---------------------------------------------------------------------------
14745 +QUIET                  = YES
14746 +WARNINGS               = YES
14747 +WARN_IF_UNDOCUMENTED   = NO
14748 +WARN_IF_DOC_ERROR      = YES
14749 +WARN_FORMAT            = "$file:$line: $text"
14750 +WARN_LOGFILE           =
14751 +#---------------------------------------------------------------------------
14752 +# configuration options related to the input files
14753 +#---------------------------------------------------------------------------
14754 +INPUT                  = .
14755 +FILE_PATTERNS          = *.c \
14756 +                         *.h \
14757 +                         ./linux/*.c \
14758 +                         ./linux/*.h
14759 +RECURSIVE              = NO
14760 +EXCLUDE                = ./test/ \
14761 +                         ./dwc_otg/.AppleDouble/
14762 +EXCLUDE_SYMLINKS       = YES
14763 +EXCLUDE_PATTERNS       = *.mod.*
14764 +EXAMPLE_PATH           =
14765 +EXAMPLE_PATTERNS       = *
14766 +EXAMPLE_RECURSIVE      = NO
14767 +IMAGE_PATH             =
14768 +INPUT_FILTER           =
14769 +FILTER_PATTERNS        =
14770 +FILTER_SOURCE_FILES    = NO
14771 +#---------------------------------------------------------------------------
14772 +# configuration options related to source browsing
14773 +#---------------------------------------------------------------------------
14774 +SOURCE_BROWSER         = YES
14775 +INLINE_SOURCES         = NO
14776 +STRIP_CODE_COMMENTS    = YES
14777 +REFERENCED_BY_RELATION = NO
14778 +REFERENCES_RELATION    = NO
14779 +VERBATIM_HEADERS       = NO
14780 +#---------------------------------------------------------------------------
14781 +# configuration options related to the alphabetical class index
14782 +#---------------------------------------------------------------------------
14783 +ALPHABETICAL_INDEX     = NO
14784 +COLS_IN_ALPHA_INDEX    = 5
14785 +IGNORE_PREFIX          =
14786 +#---------------------------------------------------------------------------
14787 +# configuration options related to the HTML output
14788 +#---------------------------------------------------------------------------
14789 +GENERATE_HTML          = YES
14790 +HTML_OUTPUT            = html
14791 +HTML_FILE_EXTENSION    = .html
14792 +HTML_HEADER            =
14793 +HTML_FOOTER            =
14794 +HTML_STYLESHEET        =
14795 +HTML_ALIGN_MEMBERS     = YES
14796 +GENERATE_HTMLHELP      = NO
14797 +CHM_FILE               =
14798 +HHC_LOCATION           =
14799 +GENERATE_CHI           = NO
14800 +BINARY_TOC             = NO
14801 +TOC_EXPAND             = NO
14802 +DISABLE_INDEX          = NO
14803 +ENUM_VALUES_PER_LINE   = 4
14804 +GENERATE_TREEVIEW      = YES
14805 +TREEVIEW_WIDTH         = 250
14806 +#---------------------------------------------------------------------------
14807 +# configuration options related to the LaTeX output
14808 +#---------------------------------------------------------------------------
14809 +GENERATE_LATEX         = NO
14810 +LATEX_OUTPUT           = latex
14811 +LATEX_CMD_NAME         = latex
14812 +MAKEINDEX_CMD_NAME     = makeindex
14813 +COMPACT_LATEX          = NO
14814 +PAPER_TYPE             = a4wide
14815 +EXTRA_PACKAGES         =
14816 +LATEX_HEADER           =
14817 +PDF_HYPERLINKS         = NO
14818 +USE_PDFLATEX           = NO
14819 +LATEX_BATCHMODE        = NO
14820 +LATEX_HIDE_INDICES     = NO
14821 +#---------------------------------------------------------------------------
14822 +# configuration options related to the RTF output
14823 +#---------------------------------------------------------------------------
14824 +GENERATE_RTF           = NO
14825 +RTF_OUTPUT             = rtf
14826 +COMPACT_RTF            = NO
14827 +RTF_HYPERLINKS         = NO
14828 +RTF_STYLESHEET_FILE    =
14829 +RTF_EXTENSIONS_FILE    =
14830 +#---------------------------------------------------------------------------
14831 +# configuration options related to the man page output
14832 +#---------------------------------------------------------------------------
14833 +GENERATE_MAN           = NO
14834 +MAN_OUTPUT             = man
14835 +MAN_EXTENSION          = .3
14836 +MAN_LINKS              = NO
14837 +#---------------------------------------------------------------------------
14838 +# configuration options related to the XML output
14839 +#---------------------------------------------------------------------------
14840 +GENERATE_XML           = NO
14841 +XML_OUTPUT             = xml
14842 +XML_SCHEMA             =
14843 +XML_DTD                =
14844 +XML_PROGRAMLISTING     = YES
14845 +#---------------------------------------------------------------------------
14846 +# configuration options for the AutoGen Definitions output
14847 +#---------------------------------------------------------------------------
14848 +GENERATE_AUTOGEN_DEF   = NO
14849 +#---------------------------------------------------------------------------
14850 +# configuration options related to the Perl module output
14851 +#---------------------------------------------------------------------------
14852 +GENERATE_PERLMOD       = NO
14853 +PERLMOD_LATEX          = NO
14854 +PERLMOD_PRETTY         = YES
14855 +PERLMOD_MAKEVAR_PREFIX =
14856 +#---------------------------------------------------------------------------
14857 +# Configuration options related to the preprocessor
14858 +#---------------------------------------------------------------------------
14859 +ENABLE_PREPROCESSING   = YES
14860 +MACRO_EXPANSION        = YES
14861 +EXPAND_ONLY_PREDEF     = YES
14862 +SEARCH_INCLUDES        = YES
14863 +INCLUDE_PATH           =
14864 +INCLUDE_FILE_PATTERNS  =
14865 +PREDEFINED             = DEVICE_ATTR DWC_EN_ISOC
14866 +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
14867 +SKIP_FUNCTION_MACROS   = NO
14868 +#---------------------------------------------------------------------------
14869 +# Configuration::additions related to external references
14870 +#---------------------------------------------------------------------------
14871 +TAGFILES               =
14872 +GENERATE_TAGFILE       =
14873 +ALLEXTERNALS           = NO
14874 +EXTERNAL_GROUPS        = YES
14875 +PERL_PATH              = /usr/bin/perl
14876 +#---------------------------------------------------------------------------
14877 +# Configuration options related to the dot tool
14878 +#---------------------------------------------------------------------------
14879 +CLASS_DIAGRAMS         = YES
14880 +HIDE_UNDOC_RELATIONS   = YES
14881 +HAVE_DOT               = NO
14882 +CLASS_GRAPH            = YES
14883 +COLLABORATION_GRAPH    = YES
14884 +UML_LOOK               = NO
14885 +TEMPLATE_RELATIONS     = NO
14886 +INCLUDE_GRAPH          = YES
14887 +INCLUDED_BY_GRAPH      = YES
14888 +CALL_GRAPH             = NO
14889 +GRAPHICAL_HIERARCHY    = YES
14890 +DOT_IMAGE_FORMAT       = png
14891 +DOT_PATH               =
14892 +DOTFILE_DIRS           =
14893 +MAX_DOT_GRAPH_DEPTH    = 1000
14894 +GENERATE_LEGEND        = YES
14895 +DOT_CLEANUP            = YES
14896 +#---------------------------------------------------------------------------
14897 +# Configuration::additions related to the search engine
14898 +#---------------------------------------------------------------------------
14899 +SEARCHENGINE           = NO
14900 diff --git a/drivers/usb/host/dwc_otg/dummy_audio.c b/drivers/usb/host/dwc_otg/dummy_audio.c
14901 new file mode 100644
14902 index 0000000..225decf
14903 --- /dev/null
14904 +++ b/drivers/usb/host/dwc_otg/dummy_audio.c
14905 @@ -0,0 +1,1575 @@
14906 +/*
14907 + * zero.c -- Gadget Zero, for USB development
14908 + *
14909 + * Copyright (C) 2003-2004 David Brownell
14910 + * All rights reserved.
14911 + *
14912 + * Redistribution and use in source and binary forms, with or without
14913 + * modification, are permitted provided that the following conditions
14914 + * are met:
14915 + * 1. Redistributions of source code must retain the above copyright
14916 + *    notice, this list of conditions, and the following disclaimer,
14917 + *    without modification.
14918 + * 2. Redistributions in binary form must reproduce the above copyright
14919 + *    notice, this list of conditions and the following disclaimer in the
14920 + *    documentation and/or other materials provided with the distribution.
14921 + * 3. The names of the above-listed copyright holders may not be used
14922 + *    to endorse or promote products derived from this software without
14923 + *    specific prior written permission.
14924 + *
14925 + * ALTERNATIVELY, this software may be distributed under the terms of the
14926 + * GNU General Public License ("GPL") as published by the Free Software
14927 + * Foundation, either version 2 of that License or (at your option) any
14928 + * later version.
14929 + *
14930 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
14931 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14932 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14933 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14934 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14935 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14936 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14937 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14938 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14939 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14940 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14941 + */
14942 +
14943 +
14944 +/*
14945 + * Gadget Zero only needs two bulk endpoints, and is an example of how you
14946 + * can write a hardware-agnostic gadget driver running inside a USB device.
14947 + *
14948 + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
14949 + * affect most of the driver.
14950 + *
14951 + * Use it with the Linux host/master side "usbtest" driver to get a basic
14952 + * functional test of your device-side usb stack, or with "usb-skeleton".
14953 + *
14954 + * It supports two similar configurations.  One sinks whatever the usb host
14955 + * writes, and in return sources zeroes.  The other loops whatever the host
14956 + * writes back, so the host can read it.  Module options include:
14957 + *
14958 + *   buflen=N          default N=4096, buffer size used
14959 + *   qlen=N            default N=32, how many buffers in the loopback queue
14960 + *   loopdefault       default false, list loopback config first
14961 + *
14962 + * Many drivers will only have one configuration, letting them be much
14963 + * simpler if they also don't support high speed operation (like this
14964 + * driver does).
14965 + */
14966 +
14967 +#include <linux/config.h>
14968 +#include <linux/module.h>
14969 +#include <linux/kernel.h>
14970 +#include <linux/delay.h>
14971 +#include <linux/ioport.h>
14972 +#include <linux/sched.h>
14973 +#include <linux/slab.h>
14974 +#include <linux/smp_lock.h>
14975 +#include <linux/errno.h>
14976 +#include <linux/init.h>
14977 +#include <linux/timer.h>
14978 +#include <linux/list.h>
14979 +#include <linux/interrupt.h>
14980 +#include <linux/uts.h>
14981 +#include <linux/version.h>
14982 +#include <linux/device.h>
14983 +#include <linux/moduleparam.h>
14984 +#include <linux/proc_fs.h>
14985 +
14986 +#include <asm/byteorder.h>
14987 +#include <asm/io.h>
14988 +#include <asm/irq.h>
14989 +#include <asm/system.h>
14990 +#include <asm/unaligned.h>
14991 +
14992 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
14993 +# include <linux/usb/ch9.h>
14994 +#else
14995 +# include <linux/usb_ch9.h>
14996 +#endif
14997 +
14998 +#include <linux/usb_gadget.h>
14999 +
15000 +
15001 +/*-------------------------------------------------------------------------*/
15002 +/*-------------------------------------------------------------------------*/
15003 +
15004 +
15005 +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
15006 +{
15007 +       int     count = 0;
15008 +       u8      c;
15009 +       u16     uchar;
15010 +
15011 +       /* this insists on correct encodings, though not minimal ones.
15012 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
15013 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
15014 +        */
15015 +       while (len != 0 && (c = (u8) *s++) != 0) {
15016 +               if (unlikely(c & 0x80)) {
15017 +                       // 2-byte sequence:
15018 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
15019 +                       if ((c & 0xe0) == 0xc0) {
15020 +                               uchar = (c & 0x1f) << 6;
15021 +
15022 +                               c = (u8) *s++;
15023 +                               if ((c & 0xc0) != 0xc0)
15024 +                                       goto fail;
15025 +                               c &= 0x3f;
15026 +                               uchar |= c;
15027 +
15028 +                       // 3-byte sequence (most CJKV characters):
15029 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
15030 +                       } else if ((c & 0xf0) == 0xe0) {
15031 +                               uchar = (c & 0x0f) << 12;
15032 +
15033 +                               c = (u8) *s++;
15034 +                               if ((c & 0xc0) != 0xc0)
15035 +                                       goto fail;
15036 +                               c &= 0x3f;
15037 +                               uchar |= c << 6;
15038 +
15039 +                               c = (u8) *s++;
15040 +                               if ((c & 0xc0) != 0xc0)
15041 +                                       goto fail;
15042 +                               c &= 0x3f;
15043 +                               uchar |= c;
15044 +
15045 +                               /* no bogus surrogates */
15046 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
15047 +                                       goto fail;
15048 +
15049 +                       // 4-byte sequence (surrogate pairs, currently rare):
15050 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
15051 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
15052 +                       // (uuuuu = wwww + 1)
15053 +                       // FIXME accept the surrogate code points (only)
15054 +
15055 +                       } else
15056 +                               goto fail;
15057 +               } else
15058 +                       uchar = c;
15059 +               put_unaligned (cpu_to_le16 (uchar), cp++);
15060 +               count++;
15061 +               len--;
15062 +       }
15063 +       return count;
15064 +fail:
15065 +       return -1;
15066 +}
15067 +
15068 +
15069 +/**
15070 + * usb_gadget_get_string - fill out a string descriptor
15071 + * @table: of c strings encoded using UTF-8
15072 + * @id: string id, from low byte of wValue in get string descriptor
15073 + * @buf: at least 256 bytes
15074 + *
15075 + * Finds the UTF-8 string matching the ID, and converts it into a
15076 + * string descriptor in utf16-le.
15077 + * Returns length of descriptor (always even) or negative errno
15078 + *
15079 + * If your driver needs stings in multiple languages, you'll probably
15080 + * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
15081 + * using this routine after choosing which set of UTF-8 strings to use.
15082 + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
15083 + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
15084 + * characters (which are also widely used in C strings).
15085 + */
15086 +int
15087 +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
15088 +{
15089 +       struct usb_string       *s;
15090 +       int                     len;
15091 +
15092 +       /* descriptor 0 has the language id */
15093 +       if (id == 0) {
15094 +               buf [0] = 4;
15095 +               buf [1] = USB_DT_STRING;
15096 +               buf [2] = (u8) table->language;
15097 +               buf [3] = (u8) (table->language >> 8);
15098 +               return 4;
15099 +       }
15100 +       for (s = table->strings; s && s->s; s++)
15101 +               if (s->id == id)
15102 +                       break;
15103 +
15104 +       /* unrecognized: stall. */
15105 +       if (!s || !s->s)
15106 +               return -EINVAL;
15107 +
15108 +       /* string descriptors have length, tag, then UTF16-LE text */
15109 +       len = min ((size_t) 126, strlen (s->s));
15110 +       memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
15111 +       len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
15112 +       if (len < 0)
15113 +               return -EINVAL;
15114 +       buf [0] = (len + 1) * 2;
15115 +       buf [1] = USB_DT_STRING;
15116 +       return buf [0];
15117 +}
15118 +
15119 +
15120 +/*-------------------------------------------------------------------------*/
15121 +/*-------------------------------------------------------------------------*/
15122 +
15123 +
15124 +/**
15125 + * usb_descriptor_fillbuf - fill buffer with descriptors
15126 + * @buf: Buffer to be filled
15127 + * @buflen: Size of buf
15128 + * @src: Array of descriptor pointers, terminated by null pointer.
15129 + *
15130 + * Copies descriptors into the buffer, returning the length or a
15131 + * negative error code if they can't all be copied.  Useful when
15132 + * assembling descriptors for an associated set of interfaces used
15133 + * as part of configuring a composite device; or in other cases where
15134 + * sets of descriptors need to be marshaled.
15135 + */
15136 +int
15137 +usb_descriptor_fillbuf(void *buf, unsigned buflen,
15138 +               const struct usb_descriptor_header **src)
15139 +{
15140 +       u8      *dest = buf;
15141 +
15142 +       if (!src)
15143 +               return -EINVAL;
15144 +
15145 +       /* fill buffer from src[] until null descriptor ptr */
15146 +       for (; 0 != *src; src++) {
15147 +               unsigned                len = (*src)->bLength;
15148 +
15149 +               if (len > buflen)
15150 +                       return -EINVAL;
15151 +               memcpy(dest, *src, len);
15152 +               buflen -= len;
15153 +               dest += len;
15154 +       }
15155 +       return dest - (u8 *)buf;
15156 +}
15157 +
15158 +
15159 +/**
15160 + * usb_gadget_config_buf - builts a complete configuration descriptor
15161 + * @config: Header for the descriptor, including characteristics such
15162 + *     as power requirements and number of interfaces.
15163 + * @desc: Null-terminated vector of pointers to the descriptors (interface,
15164 + *     endpoint, etc) defining all functions in this device configuration.
15165 + * @buf: Buffer for the resulting configuration descriptor.
15166 + * @length: Length of buffer.  If this is not big enough to hold the
15167 + *     entire configuration descriptor, an error code will be returned.
15168 + *
15169 + * This copies descriptors into the response buffer, building a descriptor
15170 + * for that configuration.  It returns the buffer length or a negative
15171 + * status code.  The config.wTotalLength field is set to match the length
15172 + * of the result, but other descriptor fields (including power usage and
15173 + * interface count) must be set by the caller.
15174 + *
15175 + * Gadget drivers could use this when constructing a config descriptor
15176 + * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
15177 + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
15178 + */
15179 +int usb_gadget_config_buf(
15180 +       const struct usb_config_descriptor      *config,
15181 +       void                                    *buf,
15182 +       unsigned                                length,
15183 +       const struct usb_descriptor_header      **desc
15184 +)
15185 +{
15186 +       struct usb_config_descriptor            *cp = buf;
15187 +       int                                     len;
15188 +
15189 +       /* config descriptor first */
15190 +       if (length < USB_DT_CONFIG_SIZE || !desc)
15191 +               return -EINVAL;
15192 +       *cp = *config;
15193 +
15194 +       /* then interface/endpoint/class/vendor/... */
15195 +       len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
15196 +                       length - USB_DT_CONFIG_SIZE, desc);
15197 +       if (len < 0)
15198 +               return len;
15199 +       len += USB_DT_CONFIG_SIZE;
15200 +       if (len > 0xffff)
15201 +               return -EINVAL;
15202 +
15203 +       /* patch up the config descriptor */
15204 +       cp->bLength = USB_DT_CONFIG_SIZE;
15205 +       cp->bDescriptorType = USB_DT_CONFIG;
15206 +       cp->wTotalLength = cpu_to_le16(len);
15207 +       cp->bmAttributes |= USB_CONFIG_ATT_ONE;
15208 +       return len;
15209 +}
15210 +
15211 +/*-------------------------------------------------------------------------*/
15212 +/*-------------------------------------------------------------------------*/
15213 +
15214 +
15215 +#define RBUF_LEN (1024*1024)
15216 +static int rbuf_start;
15217 +static int rbuf_len;
15218 +static __u8 rbuf[RBUF_LEN];
15219 +
15220 +/*-------------------------------------------------------------------------*/
15221 +
15222 +#define DRIVER_VERSION         "St Patrick's Day 2004"
15223 +
15224 +static const char shortname [] = "zero";
15225 +static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";
15226 +
15227 +static const char source_sink [] = "source and sink data";
15228 +static const char loopback [] = "loop input to output";
15229 +
15230 +/*-------------------------------------------------------------------------*/
15231 +
15232 +/*
15233 + * driver assumes self-powered hardware, and
15234 + * has no way for users to trigger remote wakeup.
15235 + *
15236 + * this version autoconfigures as much as possible,
15237 + * which is reasonable for most "bulk-only" drivers.
15238 + */
15239 +static const char *EP_IN_NAME;         /* source */
15240 +static const char *EP_OUT_NAME;                /* sink */
15241 +
15242 +/*-------------------------------------------------------------------------*/
15243 +
15244 +/* big enough to hold our biggest descriptor */
15245 +#define USB_BUFSIZ     512
15246 +
15247 +struct zero_dev {
15248 +       spinlock_t              lock;
15249 +       struct usb_gadget       *gadget;
15250 +       struct usb_request      *req;           /* for control responses */
15251 +
15252 +       /* when configured, we have one of two configs:
15253 +        * - source data (in to host) and sink it (out from host)
15254 +        * - or loop it back (out from host back in to host)
15255 +        */
15256 +       u8                      config;
15257 +       struct usb_ep           *in_ep, *out_ep;
15258 +
15259 +       /* autoresume timer */
15260 +       struct timer_list       resume;
15261 +};
15262 +
15263 +#define xprintk(d,level,fmt,args...) \
15264 +       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
15265 +
15266 +#ifdef DEBUG
15267 +#define DBG(dev,fmt,args...) \
15268 +       xprintk(dev , KERN_DEBUG , fmt , ## args)
15269 +#else
15270 +#define DBG(dev,fmt,args...) \
15271 +       do { } while (0)
15272 +#endif /* DEBUG */
15273 +
15274 +#ifdef VERBOSE
15275 +#define VDBG   DBG
15276 +#else
15277 +#define VDBG(dev,fmt,args...) \
15278 +       do { } while (0)
15279 +#endif /* VERBOSE */
15280 +
15281 +#define ERROR(dev,fmt,args...) \
15282 +       xprintk(dev , KERN_ERR , fmt , ## args)
15283 +#define WARN(dev,fmt,args...) \
15284 +       xprintk(dev , KERN_WARNING , fmt , ## args)
15285 +#define INFO(dev,fmt,args...) \
15286 +       xprintk(dev , KERN_INFO , fmt , ## args)
15287 +
15288 +/*-------------------------------------------------------------------------*/
15289 +
15290 +static unsigned buflen = 4096;
15291 +static unsigned qlen = 32;
15292 +static unsigned pattern = 0;
15293 +
15294 +module_param (buflen, uint, S_IRUGO|S_IWUSR);
15295 +module_param (qlen, uint, S_IRUGO|S_IWUSR);
15296 +module_param (pattern, uint, S_IRUGO|S_IWUSR);
15297 +
15298 +/*
15299 + * if it's nonzero, autoresume says how many seconds to wait
15300 + * before trying to wake up the host after suspend.
15301 + */
15302 +static unsigned autoresume = 0;
15303 +module_param (autoresume, uint, 0);
15304 +
15305 +/*
15306 + * Normally the "loopback" configuration is second (index 1) so
15307 + * it's not the default.  Here's where to change that order, to
15308 + * work better with hosts where config changes are problematic.
15309 + * Or controllers (like superh) that only support one config.
15310 + */
15311 +static int loopdefault = 0;
15312 +
15313 +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
15314 +
15315 +/*-------------------------------------------------------------------------*/
15316 +
15317 +/* Thanks to NetChip Technologies for donating this product ID.
15318 + *
15319 + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
15320 + * Instead:  allocate your own, using normal USB-IF procedures.
15321 + */
15322 +#ifndef        CONFIG_USB_ZERO_HNPTEST
15323 +#define DRIVER_VENDOR_NUM      0x0525          /* NetChip */
15324 +#define DRIVER_PRODUCT_NUM     0xa4a0          /* Linux-USB "Gadget Zero" */
15325 +#else
15326 +#define DRIVER_VENDOR_NUM      0x1a0a          /* OTG test device IDs */
15327 +#define DRIVER_PRODUCT_NUM     0xbadd
15328 +#endif
15329 +
15330 +/*-------------------------------------------------------------------------*/
15331 +
15332 +/*
15333 + * DESCRIPTORS ... most are static, but strings and (full)
15334 + * configuration descriptors are built on demand.
15335 + */
15336 +
15337 +/*
15338 +#define STRING_MANUFACTURER            25
15339 +#define STRING_PRODUCT                 42
15340 +#define STRING_SERIAL                  101
15341 +*/
15342 +#define STRING_MANUFACTURER            1
15343 +#define STRING_PRODUCT                 2
15344 +#define STRING_SERIAL                  3
15345 +
15346 +#define STRING_SOURCE_SINK             250
15347 +#define STRING_LOOPBACK                        251
15348 +
15349 +/*
15350 + * This device advertises two configurations; these numbers work
15351 + * on a pxa250 as well as more flexible hardware.
15352 + */
15353 +#define        CONFIG_SOURCE_SINK      3
15354 +#define        CONFIG_LOOPBACK         2
15355 +
15356 +/*
15357 +static struct usb_device_descriptor
15358 +device_desc = {
15359 +       .bLength =              sizeof device_desc,
15360 +       .bDescriptorType =      USB_DT_DEVICE,
15361 +
15362 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15363 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15364 +
15365 +       .idVendor =             __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
15366 +       .idProduct =            __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
15367 +       .iManufacturer =        STRING_MANUFACTURER,
15368 +       .iProduct =             STRING_PRODUCT,
15369 +       .iSerialNumber =        STRING_SERIAL,
15370 +       .bNumConfigurations =   2,
15371 +};
15372 +*/
15373 +static struct usb_device_descriptor
15374 +device_desc = {
15375 +       .bLength =              sizeof device_desc,
15376 +       .bDescriptorType =      USB_DT_DEVICE,
15377 +       .bcdUSB =               __constant_cpu_to_le16 (0x0100),
15378 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
15379 +       .bDeviceSubClass =      0,
15380 +       .bDeviceProtocol =      0,
15381 +       .bMaxPacketSize0 =      64,
15382 +       .bcdDevice =            __constant_cpu_to_le16 (0x0100),
15383 +       .idVendor =             __constant_cpu_to_le16 (0x0499),
15384 +       .idProduct =            __constant_cpu_to_le16 (0x3002),
15385 +       .iManufacturer =        STRING_MANUFACTURER,
15386 +       .iProduct =             STRING_PRODUCT,
15387 +       .iSerialNumber =        STRING_SERIAL,
15388 +       .bNumConfigurations =   1,
15389 +};
15390 +
15391 +static struct usb_config_descriptor
15392 +z_config = {
15393 +       .bLength =              sizeof z_config,
15394 +       .bDescriptorType =      USB_DT_CONFIG,
15395 +
15396 +       /* compute wTotalLength on the fly */
15397 +       .bNumInterfaces =       2,
15398 +       .bConfigurationValue =  1,
15399 +       .iConfiguration =       0,
15400 +       .bmAttributes =         0x40,
15401 +       .bMaxPower =            0,      /* self-powered */
15402 +};
15403 +
15404 +
15405 +static struct usb_otg_descriptor
15406 +otg_descriptor = {
15407 +       .bLength =              sizeof otg_descriptor,
15408 +       .bDescriptorType =      USB_DT_OTG,
15409 +
15410 +       .bmAttributes =         USB_OTG_SRP,
15411 +};
15412 +
15413 +/* one interface in each configuration */
15414 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15415 +
15416 +/*
15417 + * usb 2.0 devices need to expose both high speed and full speed
15418 + * descriptors, unless they only run at full speed.
15419 + *
15420 + * that means alternate endpoint descriptors (bigger packets)
15421 + * and a "device qualifier" ... plus more construction options
15422 + * for the config descriptor.
15423 + */
15424 +
15425 +static struct usb_qualifier_descriptor
15426 +dev_qualifier = {
15427 +       .bLength =              sizeof dev_qualifier,
15428 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
15429 +
15430 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15431 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15432 +
15433 +       .bNumConfigurations =   2,
15434 +};
15435 +
15436 +
15437 +struct usb_cs_as_general_descriptor {
15438 +       __u8  bLength;
15439 +       __u8  bDescriptorType;
15440 +
15441 +       __u8  bDescriptorSubType;
15442 +       __u8  bTerminalLink;
15443 +       __u8  bDelay;
15444 +       __u16  wFormatTag;
15445 +} __attribute__ ((packed));
15446 +
15447 +struct usb_cs_as_format_descriptor {
15448 +       __u8  bLength;
15449 +       __u8  bDescriptorType;
15450 +
15451 +       __u8  bDescriptorSubType;
15452 +       __u8  bFormatType;
15453 +       __u8  bNrChannels;
15454 +       __u8  bSubframeSize;
15455 +       __u8  bBitResolution;
15456 +       __u8  bSamfreqType;
15457 +       __u8  tLowerSamFreq[3];
15458 +       __u8  tUpperSamFreq[3];
15459 +} __attribute__ ((packed));
15460 +
15461 +static const struct usb_interface_descriptor
15462 +z_audio_control_if_desc = {
15463 +       .bLength =              sizeof z_audio_control_if_desc,
15464 +       .bDescriptorType =      USB_DT_INTERFACE,
15465 +       .bInterfaceNumber = 0,
15466 +       .bAlternateSetting = 0,
15467 +       .bNumEndpoints = 0,
15468 +       .bInterfaceClass = USB_CLASS_AUDIO,
15469 +       .bInterfaceSubClass = 0x1,
15470 +       .bInterfaceProtocol = 0,
15471 +       .iInterface = 0,
15472 +};
15473 +
15474 +static const struct usb_interface_descriptor
15475 +z_audio_if_desc = {
15476 +       .bLength =              sizeof z_audio_if_desc,
15477 +       .bDescriptorType =      USB_DT_INTERFACE,
15478 +       .bInterfaceNumber = 1,
15479 +       .bAlternateSetting = 0,
15480 +       .bNumEndpoints = 0,
15481 +       .bInterfaceClass = USB_CLASS_AUDIO,
15482 +       .bInterfaceSubClass = 0x2,
15483 +       .bInterfaceProtocol = 0,
15484 +       .iInterface = 0,
15485 +};
15486 +
15487 +static const struct usb_interface_descriptor
15488 +z_audio_if_desc2 = {
15489 +       .bLength =              sizeof z_audio_if_desc,
15490 +       .bDescriptorType =      USB_DT_INTERFACE,
15491 +       .bInterfaceNumber = 1,
15492 +       .bAlternateSetting = 1,
15493 +       .bNumEndpoints = 1,
15494 +       .bInterfaceClass = USB_CLASS_AUDIO,
15495 +       .bInterfaceSubClass = 0x2,
15496 +       .bInterfaceProtocol = 0,
15497 +       .iInterface = 0,
15498 +};
15499 +
15500 +static const struct usb_cs_as_general_descriptor
15501 +z_audio_cs_as_if_desc = {
15502 +       .bLength = 7,
15503 +       .bDescriptorType = 0x24,
15504 +
15505 +       .bDescriptorSubType = 0x01,
15506 +       .bTerminalLink = 0x01,
15507 +       .bDelay = 0x0,
15508 +       .wFormatTag = __constant_cpu_to_le16 (0x0001)
15509 +};
15510 +
15511 +
15512 +static const struct usb_cs_as_format_descriptor
15513 +z_audio_cs_as_format_desc = {
15514 +       .bLength = 0xe,
15515 +       .bDescriptorType = 0x24,
15516 +
15517 +       .bDescriptorSubType = 2,
15518 +       .bFormatType = 1,
15519 +       .bNrChannels = 1,
15520 +       .bSubframeSize = 1,
15521 +       .bBitResolution = 8,
15522 +       .bSamfreqType = 0,
15523 +       .tLowerSamFreq = {0x7e, 0x13, 0x00},
15524 +       .tUpperSamFreq = {0xe2, 0xd6, 0x00},
15525 +};
15526 +
15527 +static const struct usb_endpoint_descriptor
15528 +z_iso_ep = {
15529 +       .bLength = 0x09,
15530 +       .bDescriptorType = 0x05,
15531 +       .bEndpointAddress = 0x04,
15532 +       .bmAttributes = 0x09,
15533 +       .wMaxPacketSize = 0x0038,
15534 +       .bInterval = 0x01,
15535 +       .bRefresh = 0x00,
15536 +       .bSynchAddress = 0x00,
15537 +};
15538 +
15539 +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15540 +
15541 +// 9 bytes
15542 +static char z_ac_interface_header_desc[] =
15543 +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
15544 +
15545 +// 12 bytes
15546 +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
15547 +                    0x03, 0x00, 0x00, 0x00};
15548 +// 13 bytes
15549 +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00,
15550 +                    0x02, 0x00, 0x02, 0x00, 0x00};
15551 +// 9 bytes
15552 +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02,
15553 +                    0x00};
15554 +
15555 +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,
15556 +                     0x00};
15557 +
15558 +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15559 +
15560 +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00,
15561 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15562 +
15563 +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15564 +                     0x00};
15565 +
15566 +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15567 +
15568 +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
15569 +                     0x00};
15570 +
15571 +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15572 +
15573 +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
15574 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15575 +
15576 +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15577 +                     0x00};
15578 +
15579 +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15580 +
15581 +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
15582 +                      0x00};
15583 +
15584 +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15585 +
15586 +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
15587 +                      0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15588 +
15589 +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
15590 +                      0x00};
15591 +
15592 +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15593 +
15594 +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00,
15595 +                      0x00};
15596 +
15597 +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15598 +
15599 +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00,
15600 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15601 +
15602 +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
15603 +                      0x00};
15604 +
15605 +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15606 +
15607 +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
15608 +                      0x00};
15609 +
15610 +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15611 +
15612 +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00,
15613 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15614 +
15615 +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
15616 +                      0x00};
15617 +
15618 +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15619 +
15620 +
15621 +
15622 +static const struct usb_descriptor_header *z_function [] = {
15623 +       (struct usb_descriptor_header *) &z_audio_control_if_desc,
15624 +       (struct usb_descriptor_header *) &z_ac_interface_header_desc,
15625 +       (struct usb_descriptor_header *) &z_0,
15626 +       (struct usb_descriptor_header *) &z_1,
15627 +       (struct usb_descriptor_header *) &z_2,
15628 +       (struct usb_descriptor_header *) &z_audio_if_desc,
15629 +       (struct usb_descriptor_header *) &z_audio_if_desc2,
15630 +       (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
15631 +       (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
15632 +       (struct usb_descriptor_header *) &z_iso_ep,
15633 +       (struct usb_descriptor_header *) &z_iso_ep2,
15634 +       (struct usb_descriptor_header *) &za_0,
15635 +       (struct usb_descriptor_header *) &za_1,
15636 +       (struct usb_descriptor_header *) &za_2,
15637 +       (struct usb_descriptor_header *) &za_3,
15638 +       (struct usb_descriptor_header *) &za_4,
15639 +       (struct usb_descriptor_header *) &za_5,
15640 +       (struct usb_descriptor_header *) &za_6,
15641 +       (struct usb_descriptor_header *) &za_7,
15642 +       (struct usb_descriptor_header *) &za_8,
15643 +       (struct usb_descriptor_header *) &za_9,
15644 +       (struct usb_descriptor_header *) &za_10,
15645 +       (struct usb_descriptor_header *) &za_11,
15646 +       (struct usb_descriptor_header *) &za_12,
15647 +       (struct usb_descriptor_header *) &za_13,
15648 +       (struct usb_descriptor_header *) &za_14,
15649 +       (struct usb_descriptor_header *) &za_15,
15650 +       (struct usb_descriptor_header *) &za_16,
15651 +       (struct usb_descriptor_header *) &za_17,
15652 +       (struct usb_descriptor_header *) &za_18,
15653 +       (struct usb_descriptor_header *) &za_19,
15654 +       (struct usb_descriptor_header *) &za_20,
15655 +       (struct usb_descriptor_header *) &za_21,
15656 +       (struct usb_descriptor_header *) &za_22,
15657 +       (struct usb_descriptor_header *) &za_23,
15658 +       (struct usb_descriptor_header *) &za_24,
15659 +       NULL,
15660 +};
15661 +
15662 +/* maxpacket and other transfer characteristics vary by speed. */
15663 +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
15664 +
15665 +#else
15666 +
15667 +/* if there's no high speed support, maxpacket doesn't change. */
15668 +#define ep_desc(g,hs,fs) fs
15669 +
15670 +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
15671 +
15672 +static char                            manufacturer [40];
15673 +//static char                          serial [40];
15674 +static char                            serial [] = "Ser 00 em";
15675 +
15676 +/* static strings, in UTF-8 */
15677 +static struct usb_string               strings [] = {
15678 +       { STRING_MANUFACTURER, manufacturer, },
15679 +       { STRING_PRODUCT, longname, },
15680 +       { STRING_SERIAL, serial, },
15681 +       { STRING_LOOPBACK, loopback, },
15682 +       { STRING_SOURCE_SINK, source_sink, },
15683 +       {  }                    /* end of list */
15684 +};
15685 +
15686 +static struct usb_gadget_strings       stringtab = {
15687 +       .language       = 0x0409,       /* en-us */
15688 +       .strings        = strings,
15689 +};
15690 +
15691 +/*
15692 + * config descriptors are also handcrafted.  these must agree with code
15693 + * that sets configurations, and with code managing interfaces and their
15694 + * altsettings.  other complexity may come from:
15695 + *
15696 + *  - high speed support, including "other speed config" rules
15697 + *  - multiple configurations
15698 + *  - interfaces with alternate settings
15699 + *  - embedded class or vendor-specific descriptors
15700 + *
15701 + * this handles high speed, and has a second config that could as easily
15702 + * have been an alternate interface setting (on most hardware).
15703 + *
15704 + * NOTE:  to demonstrate (and test) more USB capabilities, this driver
15705 + * should include an altsetting to test interrupt transfers, including
15706 + * high bandwidth modes at high speed.  (Maybe work like Intel's test
15707 + * device?)
15708 + */
15709 +static int
15710 +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
15711 +{
15712 +       int len;
15713 +       const struct usb_descriptor_header **function;
15714 +
15715 +       function = z_function;
15716 +       len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
15717 +       if (len < 0)
15718 +               return len;
15719 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
15720 +       return len;
15721 +}
15722 +
15723 +/*-------------------------------------------------------------------------*/
15724 +
15725 +static struct usb_request *
15726 +alloc_ep_req (struct usb_ep *ep, unsigned length)
15727 +{
15728 +       struct usb_request      *req;
15729 +
15730 +       req = usb_ep_alloc_request (ep, GFP_ATOMIC);
15731 +       if (req) {
15732 +               req->length = length;
15733 +               req->buf = usb_ep_alloc_buffer (ep, length,
15734 +                               &req->dma, GFP_ATOMIC);
15735 +               if (!req->buf) {
15736 +                       usb_ep_free_request (ep, req);
15737 +                       req = NULL;
15738 +               }
15739 +       }
15740 +       return req;
15741 +}
15742 +
15743 +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
15744 +{
15745 +       if (req->buf)
15746 +               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
15747 +       usb_ep_free_request (ep, req);
15748 +}
15749 +
15750 +/*-------------------------------------------------------------------------*/
15751 +
15752 +/* optionally require specific source/sink data patterns  */
15753 +
15754 +static int
15755 +check_read_data (
15756 +       struct zero_dev         *dev,
15757 +       struct usb_ep           *ep,
15758 +       struct usb_request      *req
15759 +)
15760 +{
15761 +       unsigned        i;
15762 +       u8              *buf = req->buf;
15763 +
15764 +       for (i = 0; i < req->actual; i++, buf++) {
15765 +               switch (pattern) {
15766 +               /* all-zeroes has no synchronization issues */
15767 +               case 0:
15768 +                       if (*buf == 0)
15769 +                               continue;
15770 +                       break;
15771 +               /* mod63 stays in sync with short-terminated transfers,
15772 +                * or otherwise when host and gadget agree on how large
15773 +                * each usb transfer request should be.  resync is done
15774 +                * with set_interface or set_config.
15775 +                */
15776 +               case 1:
15777 +                       if (*buf == (u8)(i % 63))
15778 +                               continue;
15779 +                       break;
15780 +               }
15781 +               ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
15782 +               usb_ep_set_halt (ep);
15783 +               return -EINVAL;
15784 +       }
15785 +       return 0;
15786 +}
15787 +
15788 +/*-------------------------------------------------------------------------*/
15789 +
15790 +static void zero_reset_config (struct zero_dev *dev)
15791 +{
15792 +       if (dev->config == 0)
15793 +               return;
15794 +
15795 +       DBG (dev, "reset config\n");
15796 +
15797 +       /* just disable endpoints, forcing completion of pending i/o.
15798 +        * all our completion handlers free their requests in this case.
15799 +        */
15800 +       if (dev->in_ep) {
15801 +               usb_ep_disable (dev->in_ep);
15802 +               dev->in_ep = NULL;
15803 +       }
15804 +       if (dev->out_ep) {
15805 +               usb_ep_disable (dev->out_ep);
15806 +               dev->out_ep = NULL;
15807 +       }
15808 +       dev->config = 0;
15809 +       del_timer (&dev->resume);
15810 +}
15811 +
15812 +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
15813 +
15814 +static void
15815 +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
15816 +{
15817 +       struct zero_dev *dev = ep->driver_data;
15818 +       int             status = req->status;
15819 +       int i, j;
15820 +
15821 +       switch (status) {
15822 +
15823 +       case 0:                         /* normal completion? */
15824 +               //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
15825 +               for (i=0, j=rbuf_start; i<req->actual; i++) {
15826 +                       //printk ("%02x ", ((__u8*)req->buf)[i]);
15827 +                       rbuf[j] = ((__u8*)req->buf)[i];
15828 +                       j++;
15829 +                       if (j >= RBUF_LEN) j=0;
15830 +               }
15831 +               rbuf_start = j;
15832 +               //printk ("\n\n");
15833 +
15834 +               if (rbuf_len < RBUF_LEN) {
15835 +                       rbuf_len += req->actual;
15836 +                       if (rbuf_len > RBUF_LEN) {
15837 +                               rbuf_len = RBUF_LEN;
15838 +                       }
15839 +               }
15840 +
15841 +               break;
15842 +
15843 +       /* this endpoint is normally active while we're configured */
15844 +       case -ECONNABORTED:             /* hardware forced ep reset */
15845 +       case -ECONNRESET:               /* request dequeued */
15846 +       case -ESHUTDOWN:                /* disconnect from host */
15847 +               VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
15848 +                               req->actual, req->length);
15849 +               if (ep == dev->out_ep)
15850 +                       check_read_data (dev, ep, req);
15851 +               free_ep_req (ep, req);
15852 +               return;
15853 +
15854 +       case -EOVERFLOW:                /* buffer overrun on read means that
15855 +                                        * we didn't provide a big enough
15856 +                                        * buffer.
15857 +                                        */
15858 +       default:
15859 +#if 1
15860 +               DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
15861 +                               status, req->actual, req->length);
15862 +#endif
15863 +       case -EREMOTEIO:                /* short read */
15864 +               break;
15865 +       }
15866 +
15867 +       status = usb_ep_queue (ep, req, GFP_ATOMIC);
15868 +       if (status) {
15869 +               ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
15870 +                               ep->name, req->length, status);
15871 +               usb_ep_set_halt (ep);
15872 +               /* FIXME recover later ... somehow */
15873 +       }
15874 +}
15875 +
15876 +static struct usb_request *
15877 +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
15878 +{
15879 +       struct usb_request      *req;
15880 +       int                     status;
15881 +
15882 +       req = alloc_ep_req (ep, 512);
15883 +       if (!req)
15884 +               return NULL;
15885 +
15886 +       req->complete = zero_isoc_complete;
15887 +
15888 +       status = usb_ep_queue (ep, req, gfp_flags);
15889 +       if (status) {
15890 +               struct zero_dev *dev = ep->driver_data;
15891 +
15892 +               ERROR (dev, "start %s --> %d\n", ep->name, status);
15893 +               free_ep_req (ep, req);
15894 +               req = NULL;
15895 +       }
15896 +
15897 +       return req;
15898 +}
15899 +
15900 +/* change our operational config.  this code must agree with the code
15901 + * that returns config descriptors, and altsetting code.
15902 + *
15903 + * it's also responsible for power management interactions. some
15904 + * configurations might not work with our current power sources.
15905 + *
15906 + * note that some device controller hardware will constrain what this
15907 + * code can do, perhaps by disallowing more than one configuration or
15908 + * by limiting configuration choices (like the pxa2xx).
15909 + */
15910 +static int
15911 +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
15912 +{
15913 +       int                     result = 0;
15914 +       struct usb_gadget       *gadget = dev->gadget;
15915 +       const struct usb_endpoint_descriptor    *d;
15916 +       struct usb_ep           *ep;
15917 +
15918 +       if (number == dev->config)
15919 +               return 0;
15920 +
15921 +       zero_reset_config (dev);
15922 +
15923 +       gadget_for_each_ep (ep, gadget) {
15924 +
15925 +               if (strcmp (ep->name, "ep4") == 0) {
15926 +
15927 +                       d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
15928 +                       result = usb_ep_enable (ep, d);
15929 +
15930 +                       if (result == 0) {
15931 +                               ep->driver_data = dev;
15932 +                               dev->in_ep = ep;
15933 +
15934 +                               if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
15935 +
15936 +                                       dev->in_ep = ep;
15937 +                                       continue;
15938 +                               }
15939 +
15940 +                               usb_ep_disable (ep);
15941 +                               result = -EIO;
15942 +                       }
15943 +               }
15944 +
15945 +       }
15946 +
15947 +       dev->config = number;
15948 +       return result;
15949 +}
15950 +
15951 +/*-------------------------------------------------------------------------*/
15952 +
15953 +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
15954 +{
15955 +       if (req->status || req->actual != req->length)
15956 +               DBG ((struct zero_dev *) ep->driver_data,
15957 +                               "setup complete --> %d, %d/%d\n",
15958 +                               req->status, req->actual, req->length);
15959 +}
15960 +
15961 +/*
15962 + * The setup() callback implements all the ep0 functionality that's
15963 + * not handled lower down, in hardware or the hardware driver (like
15964 + * device and endpoint feature flags, and their status).  It's all
15965 + * housekeeping for the gadget function we're implementing.  Most of
15966 + * the work is in config-specific setup.
15967 + */
15968 +static int
15969 +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
15970 +{
15971 +       struct zero_dev         *dev = get_gadget_data (gadget);
15972 +       struct usb_request      *req = dev->req;
15973 +       int                     value = -EOPNOTSUPP;
15974 +
15975 +       /* usually this stores reply data in the pre-allocated ep0 buffer,
15976 +        * but config change events will reconfigure hardware.
15977 +        */
15978 +       req->zero = 0;
15979 +       switch (ctrl->bRequest) {
15980 +
15981 +       case USB_REQ_GET_DESCRIPTOR:
15982 +
15983 +               switch (ctrl->wValue >> 8) {
15984 +
15985 +               case USB_DT_DEVICE:
15986 +                       value = min (ctrl->wLength, (u16) sizeof device_desc);
15987 +                       memcpy (req->buf, &device_desc, value);
15988 +                       break;
15989 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15990 +               case USB_DT_DEVICE_QUALIFIER:
15991 +                       if (!gadget->is_dualspeed)
15992 +                               break;
15993 +                       value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
15994 +                       memcpy (req->buf, &dev_qualifier, value);
15995 +                       break;
15996 +
15997 +               case USB_DT_OTHER_SPEED_CONFIG:
15998 +                       if (!gadget->is_dualspeed)
15999 +                               break;
16000 +                       // FALLTHROUGH
16001 +#endif /* CONFIG_USB_GADGET_DUALSPEED */
16002 +               case USB_DT_CONFIG:
16003 +                       value = config_buf (gadget, req->buf,
16004 +                                       ctrl->wValue >> 8,
16005 +                                       ctrl->wValue & 0xff);
16006 +                       if (value >= 0)
16007 +                               value = min (ctrl->wLength, (u16) value);
16008 +                       break;
16009 +
16010 +               case USB_DT_STRING:
16011 +                       /* wIndex == language code.
16012 +                        * this driver only handles one language, you can
16013 +                        * add string tables for other languages, using
16014 +                        * any UTF-8 characters
16015 +                        */
16016 +                       value = usb_gadget_get_string (&stringtab,
16017 +                                       ctrl->wValue & 0xff, req->buf);
16018 +                       if (value >= 0) {
16019 +                               value = min (ctrl->wLength, (u16) value);
16020 +                       }
16021 +                       break;
16022 +               }
16023 +               break;
16024 +
16025 +       /* currently two configs, two speeds */
16026 +       case USB_REQ_SET_CONFIGURATION:
16027 +               if (ctrl->bRequestType != 0)
16028 +                       goto unknown;
16029 +
16030 +               spin_lock (&dev->lock);
16031 +               value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
16032 +               spin_unlock (&dev->lock);
16033 +               break;
16034 +       case USB_REQ_GET_CONFIGURATION:
16035 +               if (ctrl->bRequestType != USB_DIR_IN)
16036 +                       goto unknown;
16037 +               *(u8 *)req->buf = dev->config;
16038 +               value = min (ctrl->wLength, (u16) 1);
16039 +               break;
16040 +
16041 +       /* until we add altsetting support, or other interfaces,
16042 +        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
16043 +        * and already killed pending endpoint I/O.
16044 +        */
16045 +       case USB_REQ_SET_INTERFACE:
16046 +
16047 +               if (ctrl->bRequestType != USB_RECIP_INTERFACE)
16048 +                       goto unknown;
16049 +               spin_lock (&dev->lock);
16050 +               if (dev->config) {
16051 +                       u8              config = dev->config;
16052 +
16053 +                       /* resets interface configuration, forgets about
16054 +                        * previous transaction state (queued bufs, etc)
16055 +                        * and re-inits endpoint state (toggle etc)
16056 +                        * no response queued, just zero status == success.
16057 +                        * if we had more than one interface we couldn't
16058 +                        * use this "reset the config" shortcut.
16059 +                        */
16060 +                       zero_reset_config (dev);
16061 +                       zero_set_config (dev, config, GFP_ATOMIC);
16062 +                       value = 0;
16063 +               }
16064 +               spin_unlock (&dev->lock);
16065 +               break;
16066 +       case USB_REQ_GET_INTERFACE:
16067 +               if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
16068 +                       value = ctrl->wLength;
16069 +                       break;
16070 +               }
16071 +               else {
16072 +                       if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
16073 +                               goto unknown;
16074 +                       if (!dev->config)
16075 +                               break;
16076 +                       if (ctrl->wIndex != 0) {
16077 +                               value = -EDOM;
16078 +                               break;
16079 +                       }
16080 +                       *(u8 *)req->buf = 0;
16081 +                       value = min (ctrl->wLength, (u16) 1);
16082 +               }
16083 +               break;
16084 +
16085 +       /*
16086 +        * These are the same vendor-specific requests supported by
16087 +        * Intel's USB 2.0 compliance test devices.  We exceed that
16088 +        * device spec by allowing multiple-packet requests.
16089 +        */
16090 +       case 0x5b:      /* control WRITE test -- fill the buffer */
16091 +               if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
16092 +                       goto unknown;
16093 +               if (ctrl->wValue || ctrl->wIndex)
16094 +                       break;
16095 +               /* just read that many bytes into the buffer */
16096 +               if (ctrl->wLength > USB_BUFSIZ)
16097 +                       break;
16098 +               value = ctrl->wLength;
16099 +               break;
16100 +       case 0x5c:      /* control READ test -- return the buffer */
16101 +               if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
16102 +                       goto unknown;
16103 +               if (ctrl->wValue || ctrl->wIndex)
16104 +                       break;
16105 +               /* expect those bytes are still in the buffer; send back */
16106 +               if (ctrl->wLength > USB_BUFSIZ
16107 +                               || ctrl->wLength != req->length)
16108 +                       break;
16109 +               value = ctrl->wLength;
16110 +               break;
16111 +
16112 +       case 0x01: // SET_CUR
16113 +       case 0x02:
16114 +       case 0x03:
16115 +       case 0x04:
16116 +       case 0x05:
16117 +               value = ctrl->wLength;
16118 +               break;
16119 +       case 0x81:
16120 +               switch (ctrl->wValue) {
16121 +               case 0x0201:
16122 +               case 0x0202:
16123 +                       ((u8*)req->buf)[0] = 0x00;
16124 +                       ((u8*)req->buf)[1] = 0xe3;
16125 +                       break;
16126 +               case 0x0300:
16127 +               case 0x0500:
16128 +                       ((u8*)req->buf)[0] = 0x00;
16129 +                       break;
16130 +               }
16131 +               //((u8*)req->buf)[0] = 0x81;
16132 +               //((u8*)req->buf)[1] = 0x81;
16133 +               value = ctrl->wLength;
16134 +               break;
16135 +       case 0x82:
16136 +               switch (ctrl->wValue) {
16137 +               case 0x0201:
16138 +               case 0x0202:
16139 +                       ((u8*)req->buf)[0] = 0x00;
16140 +                       ((u8*)req->buf)[1] = 0xc3;
16141 +                       break;
16142 +               case 0x0300:
16143 +               case 0x0500:
16144 +                       ((u8*)req->buf)[0] = 0x00;
16145 +                       break;
16146 +               }
16147 +               //((u8*)req->buf)[0] = 0x82;
16148 +               //((u8*)req->buf)[1] = 0x82;
16149 +               value = ctrl->wLength;
16150 +               break;
16151 +       case 0x83:
16152 +               switch (ctrl->wValue) {
16153 +               case 0x0201:
16154 +               case 0x0202:
16155 +                       ((u8*)req->buf)[0] = 0x00;
16156 +                       ((u8*)req->buf)[1] = 0x00;
16157 +                       break;
16158 +               case 0x0300:
16159 +                       ((u8*)req->buf)[0] = 0x60;
16160 +                       break;
16161 +               case 0x0500:
16162 +                       ((u8*)req->buf)[0] = 0x18;
16163 +                       break;
16164 +               }
16165 +               //((u8*)req->buf)[0] = 0x83;
16166 +               //((u8*)req->buf)[1] = 0x83;
16167 +               value = ctrl->wLength;
16168 +               break;
16169 +       case 0x84:
16170 +               switch (ctrl->wValue) {
16171 +               case 0x0201:
16172 +               case 0x0202:
16173 +                       ((u8*)req->buf)[0] = 0x00;
16174 +                       ((u8*)req->buf)[1] = 0x01;
16175 +                       break;
16176 +               case 0x0300:
16177 +               case 0x0500:
16178 +                       ((u8*)req->buf)[0] = 0x08;
16179 +                       break;
16180 +               }
16181 +               //((u8*)req->buf)[0] = 0x84;
16182 +               //((u8*)req->buf)[1] = 0x84;
16183 +               value = ctrl->wLength;
16184 +               break;
16185 +       case 0x85:
16186 +               ((u8*)req->buf)[0] = 0x85;
16187 +               ((u8*)req->buf)[1] = 0x85;
16188 +               value = ctrl->wLength;
16189 +               break;
16190 +
16191 +
16192 +       default:
16193 +unknown:
16194 +               printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
16195 +                       ctrl->bRequestType, ctrl->bRequest,
16196 +                       ctrl->wValue, ctrl->wIndex, ctrl->wLength);
16197 +       }
16198 +
16199 +       /* respond with data transfer before status phase? */
16200 +       if (value >= 0) {
16201 +               req->length = value;
16202 +               req->zero = value < ctrl->wLength
16203 +                               && (value % gadget->ep0->maxpacket) == 0;
16204 +               value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
16205 +               if (value < 0) {
16206 +                       DBG (dev, "ep_queue < 0 --> %d\n", value);
16207 +                       req->status = 0;
16208 +                       zero_setup_complete (gadget->ep0, req);
16209 +               }
16210 +       }
16211 +
16212 +       /* device either stalls (value < 0) or reports success */
16213 +       return value;
16214 +}
16215 +
16216 +static void
16217 +zero_disconnect (struct usb_gadget *gadget)
16218 +{
16219 +       struct zero_dev         *dev = get_gadget_data (gadget);
16220 +       unsigned long           flags;
16221 +
16222 +       spin_lock_irqsave (&dev->lock, flags);
16223 +       zero_reset_config (dev);
16224 +
16225 +       /* a more significant application might have some non-usb
16226 +        * activities to quiesce here, saving resources like power
16227 +        * or pushing the notification up a network stack.
16228 +        */
16229 +       spin_unlock_irqrestore (&dev->lock, flags);
16230 +
16231 +       /* next we may get setup() calls to enumerate new connections;
16232 +        * or an unbind() during shutdown (including removing module).
16233 +        */
16234 +}
16235 +
16236 +static void
16237 +zero_autoresume (unsigned long _dev)
16238 +{
16239 +       struct zero_dev *dev = (struct zero_dev *) _dev;
16240 +       int             status;
16241 +
16242 +       /* normally the host would be woken up for something
16243 +        * more significant than just a timer firing...
16244 +        */
16245 +       if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
16246 +               status = usb_gadget_wakeup (dev->gadget);
16247 +               DBG (dev, "wakeup --> %d\n", status);
16248 +       }
16249 +}
16250 +
16251 +/*-------------------------------------------------------------------------*/
16252 +
16253 +static void
16254 +zero_unbind (struct usb_gadget *gadget)
16255 +{
16256 +       struct zero_dev         *dev = get_gadget_data (gadget);
16257 +
16258 +       DBG (dev, "unbind\n");
16259 +
16260 +       /* we've already been disconnected ... no i/o is active */
16261 +       if (dev->req)
16262 +               free_ep_req (gadget->ep0, dev->req);
16263 +       del_timer_sync (&dev->resume);
16264 +       kfree (dev);
16265 +       set_gadget_data (gadget, NULL);
16266 +}
16267 +
16268 +static int
16269 +zero_bind (struct usb_gadget *gadget)
16270 +{
16271 +       struct zero_dev         *dev;
16272 +       //struct usb_ep         *ep;
16273 +
16274 +       printk("binding\n");
16275 +       /*
16276 +        * DRIVER POLICY CHOICE:  you may want to do this differently.
16277 +        * One thing to avoid is reusing a bcdDevice revision code
16278 +        * with different host-visible configurations or behavior
16279 +        * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
16280 +        */
16281 +       //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
16282 +
16283 +
16284 +       /* ok, we made sense of the hardware ... */
16285 +       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
16286 +       if (!dev)
16287 +               return -ENOMEM;
16288 +       memset (dev, 0, sizeof *dev);
16289 +       spin_lock_init (&dev->lock);
16290 +       dev->gadget = gadget;
16291 +       set_gadget_data (gadget, dev);
16292 +
16293 +       /* preallocate control response and buffer */
16294 +       dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
16295 +       if (!dev->req)
16296 +               goto enomem;
16297 +       dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
16298 +                               &dev->req->dma, GFP_KERNEL);
16299 +       if (!dev->req->buf)
16300 +               goto enomem;
16301 +
16302 +       dev->req->complete = zero_setup_complete;
16303 +
16304 +       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
16305 +
16306 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16307 +       /* assume ep0 uses the same value for both speeds ... */
16308 +       dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
16309 +
16310 +       /* and that all endpoints are dual-speed */
16311 +       //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
16312 +       //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
16313 +#endif
16314 +
16315 +       usb_gadget_set_selfpowered (gadget);
16316 +
16317 +       init_timer (&dev->resume);
16318 +       dev->resume.function = zero_autoresume;
16319 +       dev->resume.data = (unsigned long) dev;
16320 +
16321 +       gadget->ep0->driver_data = dev;
16322 +
16323 +       INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
16324 +       INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
16325 +               EP_OUT_NAME, EP_IN_NAME);
16326 +
16327 +       snprintf (manufacturer, sizeof manufacturer,
16328 +               UTS_SYSNAME " " UTS_RELEASE " with %s",
16329 +               gadget->name);
16330 +
16331 +       return 0;
16332 +
16333 +enomem:
16334 +       zero_unbind (gadget);
16335 +       return -ENOMEM;
16336 +}
16337 +
16338 +/*-------------------------------------------------------------------------*/
16339 +
16340 +static void
16341 +zero_suspend (struct usb_gadget *gadget)
16342 +{
16343 +       struct zero_dev         *dev = get_gadget_data (gadget);
16344 +
16345 +       if (gadget->speed == USB_SPEED_UNKNOWN)
16346 +               return;
16347 +
16348 +       if (autoresume) {
16349 +               mod_timer (&dev->resume, jiffies + (HZ * autoresume));
16350 +               DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
16351 +       } else
16352 +               DBG (dev, "suspend\n");
16353 +}
16354 +
16355 +static void
16356 +zero_resume (struct usb_gadget *gadget)
16357 +{
16358 +       struct zero_dev         *dev = get_gadget_data (gadget);
16359 +
16360 +       DBG (dev, "resume\n");
16361 +       del_timer (&dev->resume);
16362 +}
16363 +
16364 +
16365 +/*-------------------------------------------------------------------------*/
16366 +
16367 +static struct usb_gadget_driver zero_driver = {
16368 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16369 +       .speed          = USB_SPEED_HIGH,
16370 +#else
16371 +       .speed          = USB_SPEED_FULL,
16372 +#endif
16373 +       .function       = (char *) longname,
16374 +       .bind           = zero_bind,
16375 +       .unbind         = zero_unbind,
16376 +
16377 +       .setup          = zero_setup,
16378 +       .disconnect     = zero_disconnect,
16379 +
16380 +       .suspend        = zero_suspend,
16381 +       .resume         = zero_resume,
16382 +
16383 +       .driver         = {
16384 +               .name           = (char *) shortname,
16385 +               // .shutdown = ...
16386 +               // .suspend = ...
16387 +               // .resume = ...
16388 +       },
16389 +};
16390 +
16391 +MODULE_AUTHOR ("David Brownell");
16392 +MODULE_LICENSE ("Dual BSD/GPL");
16393 +
16394 +static struct proc_dir_entry *pdir, *pfile;
16395 +
16396 +static int isoc_read_data (char *page, char **start,
16397 +                          off_t off, int count,
16398 +                          int *eof, void *data)
16399 +{
16400 +       int i;
16401 +       static int c = 0;
16402 +       static int done = 0;
16403 +       static int s = 0;
16404 +
16405 +/*
16406 +       printk ("\ncount: %d\n", count);
16407 +       printk ("rbuf_start: %d\n", rbuf_start);
16408 +       printk ("rbuf_len: %d\n", rbuf_len);
16409 +       printk ("off: %d\n", off);
16410 +       printk ("start: %p\n\n", *start);
16411 +*/
16412 +       if (done) {
16413 +               c = 0;
16414 +               done = 0;
16415 +               *eof = 1;
16416 +               return 0;
16417 +       }
16418 +
16419 +       if (c == 0) {
16420 +               if (rbuf_len == RBUF_LEN)
16421 +                       s = rbuf_start;
16422 +               else s = 0;
16423 +       }
16424 +
16425 +       for (i=0; i<count && c<rbuf_len; i++, c++) {
16426 +               page[i] = rbuf[(c+s) % RBUF_LEN];
16427 +       }
16428 +       *start = page;
16429 +
16430 +       if (c >= rbuf_len) {
16431 +               *eof = 1;
16432 +               done = 1;
16433 +       }
16434 +
16435 +
16436 +       return i;
16437 +}
16438 +
16439 +static int __init init (void)
16440 +{
16441 +
16442 +       int retval = 0;
16443 +
16444 +       pdir = proc_mkdir("isoc_test", NULL);
16445 +       if(pdir == NULL) {
16446 +               retval = -ENOMEM;
16447 +               printk("Error creating dir\n");
16448 +               goto done;
16449 +       }
16450 +       pdir->owner = THIS_MODULE;
16451 +
16452 +       pfile = create_proc_read_entry("isoc_data",
16453 +                                      0444, pdir,
16454 +                                      isoc_read_data,
16455 +                                      NULL);
16456 +       if (pfile == NULL) {
16457 +               retval = -ENOMEM;
16458 +               printk("Error creating file\n");
16459 +               goto no_file;
16460 +       }
16461 +       pfile->owner = THIS_MODULE;
16462 +
16463 +       return usb_gadget_register_driver (&zero_driver);
16464 +
16465 + no_file:
16466 +       remove_proc_entry("isoc_data", NULL);
16467 + done:
16468 +       return retval;
16469 +}
16470 +module_init (init);
16471 +
16472 +static void __exit cleanup (void)
16473 +{
16474 +
16475 +       usb_gadget_unregister_driver (&zero_driver);
16476 +
16477 +       remove_proc_entry("isoc_data", pdir);
16478 +       remove_proc_entry("isoc_test", NULL);
16479 +}
16480 +module_exit (cleanup);
16481 diff --git a/drivers/usb/host/dwc_otg/dwc_cfi_common.h b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16482 new file mode 100644
16483 index 0000000..7770e20
16484 --- /dev/null
16485 +++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16486 @@ -0,0 +1,142 @@
16487 +/* ==========================================================================
16488 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16489 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16490 + * otherwise expressly agreed to in writing between Synopsys and you.
16491 + *
16492 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16493 + * any End User Software License Agreement or Agreement for Licensed Product
16494 + * with Synopsys or any supplement thereto. You are permitted to use and
16495 + * redistribute this Software in source and binary forms, with or without
16496 + * modification, provided that redistributions of source code must retain this
16497 + * notice. You may not view, use, disclose, copy or distribute this file or
16498 + * any information contained herein except pursuant to this license grant from
16499 + * Synopsys. If you do not agree with this notice, including the disclaimer
16500 + * below, then you are not authorized to use the Software.
16501 + *
16502 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16503 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16504 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16505 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16506 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16507 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16508 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16509 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16510 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16511 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16512 + * DAMAGE.
16513 + * ========================================================================== */
16514 +
16515 +#if !defined(__DWC_CFI_COMMON_H__)
16516 +#define __DWC_CFI_COMMON_H__
16517 +
16518 +//#include <linux/types.h>
16519 +
16520 +/**
16521 + * @file
16522 + *
16523 + * This file contains the CFI specific common constants, interfaces
16524 + * (functions and macros) and structures for Linux. No PCD specific
16525 + * data structure or definition is to be included in this file.
16526 + *
16527 + */
16528 +
16529 +/** This is a request for all Core Features */
16530 +#define VEN_CORE_GET_FEATURES          0xB1
16531 +
16532 +/** This is a request to get the value of a specific Core Feature */
16533 +#define VEN_CORE_GET_FEATURE           0xB2
16534 +
16535 +/** This command allows the host to set the value of a specific Core Feature */
16536 +#define VEN_CORE_SET_FEATURE           0xB3
16537 +
16538 +/** This command allows the host to set the default values of
16539 + * either all or any specific Core Feature
16540 + */
16541 +#define VEN_CORE_RESET_FEATURES                0xB4
16542 +
16543 +/** This command forces the PCD to write the deferred values of a Core Features */
16544 +#define VEN_CORE_ACTIVATE_FEATURES     0xB5
16545 +
16546 +/** This request reads a DWORD value from a register at the specified offset */
16547 +#define VEN_CORE_READ_REGISTER         0xB6
16548 +
16549 +/** This request writes a DWORD value into a register at the specified offset */
16550 +#define VEN_CORE_WRITE_REGISTER                0xB7
16551 +
16552 +/** This structure is the header of the Core Features dataset returned to
16553 + *  the Host
16554 + */
16555 +struct cfi_all_features_header {
16556 +/** The features header structure length is */
16557 +#define CFI_ALL_FEATURES_HDR_LEN               8
16558 +       /**
16559 +        * The total length of the features dataset returned to the Host
16560 +        */
16561 +       uint16_t wTotalLen;
16562 +
16563 +       /**
16564 +        * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
16565 +        * This field identifies the version of the CFI Specification with which
16566 +        * the device is compliant.
16567 +        */
16568 +       uint16_t wVersion;
16569 +
16570 +       /** The ID of the Core */
16571 +       uint16_t wCoreID;
16572 +#define CFI_CORE_ID_UDC                1
16573 +#define CFI_CORE_ID_OTG                2
16574 +#define CFI_CORE_ID_WUDEV      3
16575 +
16576 +       /** Number of features returned by VEN_CORE_GET_FEATURES request */
16577 +       uint16_t wNumFeatures;
16578 +} UPACKED;
16579 +
16580 +typedef struct cfi_all_features_header cfi_all_features_header_t;
16581 +
16582 +/** This structure is a header of the Core Feature descriptor dataset returned to
16583 + *  the Host after the VEN_CORE_GET_FEATURES request
16584 + */
16585 +struct cfi_feature_desc_header {
16586 +#define CFI_FEATURE_DESC_HDR_LEN       8
16587 +
16588 +       /** The feature ID */
16589 +       uint16_t wFeatureID;
16590 +
16591 +       /** Length of this feature descriptor in bytes - including the
16592 +        * length of the feature name string
16593 +        */
16594 +       uint16_t wLength;
16595 +
16596 +       /** The data length of this feature in bytes */
16597 +       uint16_t wDataLength;
16598 +
16599 +       /**
16600 +        * Attributes of this features
16601 +        * D0: Access rights
16602 +        * 0 - Read/Write
16603 +        * 1 - Read only
16604 +        */
16605 +       uint8_t bmAttributes;
16606 +#define CFI_FEATURE_ATTR_RO            1
16607 +#define CFI_FEATURE_ATTR_RW            0
16608 +
16609 +       /** Length of the feature name in bytes */
16610 +       uint8_t bNameLen;
16611 +
16612 +       /** The feature name buffer */
16613 +       //uint8_t *name;
16614 +} UPACKED;
16615 +
16616 +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
16617 +
16618 +/**
16619 + * This structure describes a NULL terminated string referenced by its id field.
16620 + * It is very similar to usb_string structure but has the id field type set to 16-bit.
16621 + */
16622 +struct cfi_string {
16623 +       uint16_t id;
16624 +       const uint8_t *s;
16625 +};
16626 +typedef struct cfi_string cfi_string_t;
16627 +
16628 +#endif
16629 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.c b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16630 new file mode 100644
16631 index 0000000..ce0618d
16632 --- /dev/null
16633 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16634 @@ -0,0 +1,854 @@
16635 +/* ==========================================================================
16636 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
16637 + * $Revision: #12 $
16638 + * $Date: 2011/10/26 $
16639 + * $Change: 1873028 $
16640 + *
16641 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16642 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16643 + * otherwise expressly agreed to in writing between Synopsys and you.
16644 + *
16645 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16646 + * any End User Software License Agreement or Agreement for Licensed Product
16647 + * with Synopsys or any supplement thereto. You are permitted to use and
16648 + * redistribute this Software in source and binary forms, with or without
16649 + * modification, provided that redistributions of source code must retain this
16650 + * notice. You may not view, use, disclose, copy or distribute this file or
16651 + * any information contained herein except pursuant to this license grant from
16652 + * Synopsys. If you do not agree with this notice, including the disclaimer
16653 + * below, then you are not authorized to use the Software.
16654 + *
16655 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16656 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16657 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16658 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16659 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16660 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16661 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16662 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16663 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16664 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16665 + * DAMAGE.
16666 + * ========================================================================== */
16667 +
16668 +#include "dwc_os.h"
16669 +#include "dwc_otg_regs.h"
16670 +#include "dwc_otg_cil.h"
16671 +#include "dwc_otg_adp.h"
16672 +
16673 +/** @file
16674 + *
16675 + * This file contains the most of the Attach Detect Protocol implementation for
16676 + * the driver to support OTG Rev2.0.
16677 + *
16678 + */
16679 +
16680 +void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
16681 +{
16682 +       adpctl_data_t adpctl;
16683 +
16684 +       adpctl.d32 = value;
16685 +       adpctl.b.ar = 0x2;
16686 +
16687 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16688 +
16689 +       while (adpctl.b.ar) {
16690 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16691 +       }
16692 +
16693 +}
16694 +
16695 +/**
16696 + * Function is called to read ADP registers
16697 + */
16698 +uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
16699 +{
16700 +       adpctl_data_t adpctl;
16701 +
16702 +       adpctl.d32 = 0;
16703 +       adpctl.b.ar = 0x1;
16704 +
16705 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16706 +
16707 +       while (adpctl.b.ar) {
16708 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16709 +       }
16710 +
16711 +       return adpctl.d32;
16712 +}
16713 +
16714 +/**
16715 + * Function is called to read ADPCTL register and filter Write-clear bits
16716 + */
16717 +uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
16718 +{
16719 +       adpctl_data_t adpctl;
16720 +
16721 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16722 +       adpctl.b.adp_tmout_int = 0;
16723 +       adpctl.b.adp_prb_int = 0;
16724 +       adpctl.b.adp_tmout_int = 0;
16725 +
16726 +       return adpctl.d32;
16727 +}
16728 +
16729 +/**
16730 + * Function is called to write ADP registers
16731 + */
16732 +void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
16733 +                           uint32_t set)
16734 +{
16735 +       dwc_otg_adp_write_reg(core_if,
16736 +                             (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
16737 +}
16738 +
16739 +static void adp_sense_timeout(void *ptr)
16740 +{
16741 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16742 +       core_if->adp.sense_timer_started = 0;
16743 +       DWC_PRINTF("ADP SENSE TIMEOUT\n");
16744 +       if (core_if->adp_enable) {
16745 +               dwc_otg_adp_sense_stop(core_if);
16746 +               dwc_otg_adp_probe_start(core_if);
16747 +       }
16748 +}
16749 +
16750 +/**
16751 + * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
16752 + */
16753 +static void adp_vbuson_timeout(void *ptr)
16754 +{
16755 +       gpwrdn_data_t gpwrdn;
16756 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16757 +       hprt0_data_t hprt0 = {.d32 = 0 };
16758 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
16759 +       DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
16760 +       if (core_if) {
16761 +               core_if->adp.vbuson_timer_started = 0;
16762 +               /* Turn off vbus */
16763 +               hprt0.b.prtpwr = 1;
16764 +               DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
16765 +               gpwrdn.d32 = 0;
16766 +
16767 +               /* Power off the core */
16768 +               if (core_if->power_down == 2) {
16769 +                       /* Enable Wakeup Logic */
16770 +//                      gpwrdn.b.wkupactiv = 1;
16771 +                       gpwrdn.b.pmuactv = 0;
16772 +                       gpwrdn.b.pwrdnrstn = 1;
16773 +                       gpwrdn.b.pwrdnclmp = 1;
16774 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16775 +                                        gpwrdn.d32);
16776 +
16777 +                       /* Suspend the Phy Clock */
16778 +                       pcgcctl.b.stoppclk = 1;
16779 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
16780 +
16781 +                       /* Switch on VDD */
16782 +//                      gpwrdn.b.wkupactiv = 1;
16783 +                       gpwrdn.b.pmuactv = 1;
16784 +                       gpwrdn.b.pwrdnrstn = 1;
16785 +                       gpwrdn.b.pwrdnclmp = 1;
16786 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16787 +                                        gpwrdn.d32);
16788 +               } else {
16789 +                       /* Enable Power Down Logic */
16790 +                       gpwrdn.b.pmuintsel = 1;
16791 +                       gpwrdn.b.pmuactv = 1;
16792 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16793 +               }
16794 +
16795 +               /* Power off the core */
16796 +               if (core_if->power_down == 2) {
16797 +                       gpwrdn.d32 = 0;
16798 +                       gpwrdn.b.pwrdnswtch = 1;
16799 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
16800 +                                        gpwrdn.d32, 0);
16801 +               }
16802 +
16803 +               /* Unmask SRP detected interrupt from Power Down Logic */
16804 +               gpwrdn.d32 = 0;
16805 +               gpwrdn.b.srp_det_msk = 1;
16806 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16807 +
16808 +               dwc_otg_adp_probe_start(core_if);
16809 +               dwc_otg_dump_global_registers(core_if);
16810 +               dwc_otg_dump_host_registers(core_if);
16811 +       }
16812 +
16813 +}
16814 +
16815 +/**
16816 + * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
16817 + * not asserted within 1.1 seconds.
16818 + *
16819 + * @param core_if the pointer to core_if strucure.
16820 + */
16821 +void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
16822 +{
16823 +       core_if->adp.vbuson_timer_started = 1;
16824 +       if (core_if->adp.vbuson_timer)
16825 +       {
16826 +               DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
16827 +               /* 1.1 secs + 60ms necessary for cil_hcd_start*/
16828 +               DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
16829 +       } else {
16830 +               DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
16831 +       }
16832 +}
16833 +
16834 +#if 0
16835 +/**
16836 + * Masks all DWC OTG core interrupts
16837 + *
16838 + */
16839 +static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
16840 +{
16841 +       int i;
16842 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
16843 +
16844 +       /* Mask Host Interrupts */
16845 +
16846 +       /* Clear and disable HCINTs */
16847 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
16848 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
16849 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
16850 +
16851 +       }
16852 +
16853 +       /* Clear and disable HAINT */
16854 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
16855 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
16856 +
16857 +       /* Mask Device Interrupts */
16858 +       if (!core_if->multiproc_int_enable) {
16859 +               /* Clear and disable IN Endpoint interrupts */
16860 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
16861 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16862 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16863 +                                       diepint, 0xFFFFFFFF);
16864 +               }
16865 +
16866 +               /* Clear and disable OUT Endpoint interrupts */
16867 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
16868 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16869 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16870 +                                       doepint, 0xFFFFFFFF);
16871 +               }
16872 +
16873 +               /* Clear and disable DAINT */
16874 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
16875 +                               0xFFFFFFFF);
16876 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
16877 +       } else {
16878 +               for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
16879 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16880 +                                       diepeachintmsk[i], 0);
16881 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16882 +                                       diepint, 0xFFFFFFFF);
16883 +               }
16884 +
16885 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
16886 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16887 +                                       doepeachintmsk[i], 0);
16888 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16889 +                                       doepint, 0xFFFFFFFF);
16890 +               }
16891 +
16892 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
16893 +                               0);
16894 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
16895 +                               0xFFFFFFFF);
16896 +
16897 +       }
16898 +
16899 +       /* Disable interrupts */
16900 +       ahbcfg.b.glblintrmsk = 1;
16901 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
16902 +
16903 +       /* Disable all interrupts. */
16904 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
16905 +
16906 +       /* Clear any pending interrupts */
16907 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16908 +
16909 +       /* Clear any pending OTG Interrupts */
16910 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
16911 +}
16912 +
16913 +/**
16914 + * Unmask Port Connection Detected interrupt
16915 + *
16916 + */
16917 +static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
16918 +{
16919 +       gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
16920 +
16921 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
16922 +}
16923 +#endif
16924 +
16925 +/**
16926 + * Starts the ADP Probing
16927 + *
16928 + * @param core_if the pointer to core_if structure.
16929 + */
16930 +uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
16931 +{
16932 +
16933 +       adpctl_data_t adpctl = {.d32 = 0};
16934 +       gpwrdn_data_t gpwrdn;
16935 +#if 0
16936 +       adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
16937 +                                                               .b.adp_sns_int = 1, b.adp_tmout_int};
16938 +#endif
16939 +       dwc_otg_disable_global_interrupts(core_if);
16940 +       DWC_PRINTF("ADP Probe Start\n");
16941 +       core_if->adp.probe_enabled = 1;
16942 +
16943 +       adpctl.b.adpres = 1;
16944 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16945 +
16946 +       while (adpctl.b.adpres) {
16947 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16948 +       }
16949 +
16950 +       adpctl.d32 = 0;
16951 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16952 +
16953 +       /* In Host mode unmask SRP detected interrupt */
16954 +       gpwrdn.d32 = 0;
16955 +       gpwrdn.b.sts_chngint_msk = 1;
16956 +       if (!gpwrdn.b.idsts) {
16957 +               gpwrdn.b.srp_det_msk = 1;
16958 +       }
16959 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16960 +
16961 +       adpctl.b.adp_tmout_int_msk = 1;
16962 +       adpctl.b.adp_prb_int_msk = 1;
16963 +       adpctl.b.prb_dschg = 1;
16964 +       adpctl.b.prb_delta = 1;
16965 +       adpctl.b.prb_per = 1;
16966 +       adpctl.b.adpen = 1;
16967 +       adpctl.b.enaprb = 1;
16968 +
16969 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16970 +       DWC_PRINTF("ADP Probe Finish\n");
16971 +       return 0;
16972 +}
16973 +
16974 +/**
16975 + * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
16976 + * within 3 seconds.
16977 + *
16978 + * @param core_if the pointer to core_if strucure.
16979 + */
16980 +void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
16981 +{
16982 +       core_if->adp.sense_timer_started = 1;
16983 +       DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
16984 +}
16985 +
16986 +/**
16987 + * Starts the ADP Sense
16988 + *
16989 + * @param core_if the pointer to core_if strucure.
16990 + */
16991 +uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
16992 +{
16993 +       adpctl_data_t adpctl;
16994 +
16995 +       DWC_PRINTF("ADP Sense Start\n");
16996 +
16997 +       /* Unmask ADP sense interrupt and mask all other from the core */
16998 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16999 +       adpctl.b.adp_sns_int_msk = 1;
17000 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17001 +       dwc_otg_disable_global_interrupts(core_if); // vahrama
17002 +
17003 +       /* Set ADP reset bit*/
17004 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
17005 +       adpctl.b.adpres = 1;
17006 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17007 +
17008 +       while (adpctl.b.adpres) {
17009 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17010 +       }
17011 +
17012 +       adpctl.b.adpres = 0;
17013 +       adpctl.b.adpen = 1;
17014 +       adpctl.b.enasns = 1;
17015 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17016 +
17017 +       dwc_otg_adp_sense_timer_start(core_if);
17018 +
17019 +       return 0;
17020 +}
17021 +
17022 +/**
17023 + * Stops the ADP Probing
17024 + *
17025 + * @param core_if the pointer to core_if strucure.
17026 + */
17027 +uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
17028 +{
17029 +
17030 +       adpctl_data_t adpctl;
17031 +       DWC_PRINTF("Stop ADP probe\n");
17032 +       core_if->adp.probe_enabled = 0;
17033 +       core_if->adp.probe_counter = 0;
17034 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17035 +
17036 +       adpctl.b.adpen = 0;
17037 +       adpctl.b.adp_prb_int = 1;
17038 +       adpctl.b.adp_tmout_int = 1;
17039 +       adpctl.b.adp_sns_int = 1;
17040 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17041 +
17042 +       return 0;
17043 +}
17044 +
17045 +/**
17046 + * Stops the ADP Sensing
17047 + *
17048 + * @param core_if the pointer to core_if strucure.
17049 + */
17050 +uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
17051 +{
17052 +       adpctl_data_t adpctl;
17053 +
17054 +       core_if->adp.sense_enabled = 0;
17055 +
17056 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
17057 +       adpctl.b.enasns = 0;
17058 +       adpctl.b.adp_sns_int = 1;
17059 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17060 +
17061 +       return 0;
17062 +}
17063 +
17064 +/**
17065 + * Called to turn on the VBUS after initial ADP probe in host mode.
17066 + * If port power was already enabled in cil_hcd_start function then
17067 + * only schedule a timer.
17068 + *
17069 + * @param core_if the pointer to core_if structure.
17070 + */
17071 +void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
17072 +{
17073 +       hprt0_data_t hprt0 = {.d32 = 0 };
17074 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
17075 +       DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
17076 +
17077 +       if (hprt0.b.prtpwr == 0) {
17078 +               hprt0.b.prtpwr = 1;
17079 +               //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17080 +       }
17081 +
17082 +       dwc_otg_adp_vbuson_timer_start(core_if);
17083 +}
17084 +
17085 +/**
17086 + * Called right after driver is loaded
17087 + * to perform initial actions for ADP
17088 + *
17089 + * @param core_if the pointer to core_if structure.
17090 + * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
17091 + */
17092 +void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
17093 +{
17094 +       gpwrdn_data_t gpwrdn;
17095 +
17096 +       DWC_PRINTF("ADP Initial Start\n");
17097 +       core_if->adp.adp_started = 1;
17098 +
17099 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17100 +       dwc_otg_disable_global_interrupts(core_if);
17101 +       if (is_host) {
17102 +               DWC_PRINTF("HOST MODE\n");
17103 +               /* Enable Power Down Logic Interrupt*/
17104 +               gpwrdn.d32 = 0;
17105 +               gpwrdn.b.pmuintsel = 1;
17106 +               gpwrdn.b.pmuactv = 1;
17107 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17108 +               /* Initialize first ADP probe to obtain Ramp Time value */
17109 +               core_if->adp.initial_probe = 1;
17110 +               dwc_otg_adp_probe_start(core_if);
17111 +       } else {
17112 +               gotgctl_data_t gotgctl;
17113 +               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17114 +               DWC_PRINTF("DEVICE MODE\n");
17115 +               if (gotgctl.b.bsesvld == 0) {
17116 +                       /* Enable Power Down Logic Interrupt*/
17117 +                       gpwrdn.d32 = 0;
17118 +                       DWC_PRINTF("VBUS is not valid - start ADP probe\n");
17119 +                       gpwrdn.b.pmuintsel = 1;
17120 +                       gpwrdn.b.pmuactv = 1;
17121 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17122 +                       core_if->adp.initial_probe = 1;
17123 +                       dwc_otg_adp_probe_start(core_if);
17124 +               } else {
17125 +                       DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
17126 +                       core_if->op_state = B_PERIPHERAL;
17127 +                       dwc_otg_core_init(core_if);
17128 +                       dwc_otg_enable_global_interrupts(core_if);
17129 +                       cil_pcd_start(core_if);
17130 +                       dwc_otg_dump_global_registers(core_if);
17131 +                       dwc_otg_dump_dev_registers(core_if);
17132 +               }
17133 +       }
17134 +}
17135 +
17136 +void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
17137 +{
17138 +       core_if->adp.adp_started = 0;
17139 +       core_if->adp.initial_probe = 0;
17140 +       core_if->adp.probe_timer_values[0] = -1;
17141 +       core_if->adp.probe_timer_values[1] = -1;
17142 +       core_if->adp.probe_enabled = 0;
17143 +       core_if->adp.sense_enabled = 0;
17144 +       core_if->adp.sense_timer_started = 0;
17145 +       core_if->adp.vbuson_timer_started = 0;
17146 +       core_if->adp.probe_counter = 0;
17147 +       core_if->adp.gpwrdn = 0;
17148 +       core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
17149 +       /* Initialize timers */
17150 +       core_if->adp.sense_timer =
17151 +           DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
17152 +       core_if->adp.vbuson_timer =
17153 +           DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
17154 +       if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
17155 +       {
17156 +               DWC_ERROR("Could not allocate memory for ADP timers\n");
17157 +       }
17158 +}
17159 +
17160 +void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
17161 +{
17162 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
17163 +       gpwrdn.b.pmuintsel = 1;
17164 +       gpwrdn.b.pmuactv = 1;
17165 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17166 +
17167 +       if (core_if->adp.probe_enabled)
17168 +               dwc_otg_adp_probe_stop(core_if);
17169 +       if (core_if->adp.sense_enabled)
17170 +               dwc_otg_adp_sense_stop(core_if);
17171 +       if (core_if->adp.sense_timer_started)
17172 +               DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17173 +       if (core_if->adp.vbuson_timer_started)
17174 +               DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
17175 +       DWC_TIMER_FREE(core_if->adp.sense_timer);
17176 +       DWC_TIMER_FREE(core_if->adp.vbuson_timer);
17177 +}
17178 +
17179 +/////////////////////////////////////////////////////////////////////
17180 +////////////// ADP Interrupt Handlers ///////////////////////////////
17181 +/////////////////////////////////////////////////////////////////////
17182 +/**
17183 + * This function sets Ramp Timer values
17184 + */
17185 +static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
17186 +{
17187 +       if (core_if->adp.probe_timer_values[0] == -1) {
17188 +               core_if->adp.probe_timer_values[0] = val;
17189 +               core_if->adp.probe_timer_values[1] = -1;
17190 +               return 1;
17191 +       } else {
17192 +               core_if->adp.probe_timer_values[1] =
17193 +                   core_if->adp.probe_timer_values[0];
17194 +               core_if->adp.probe_timer_values[0] = val;
17195 +               return 0;
17196 +       }
17197 +}
17198 +
17199 +/**
17200 + * This function compares Ramp Timer values
17201 + */
17202 +static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
17203 +{
17204 +       uint32_t diff;
17205 +       if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
17206 +                       diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
17207 +       else
17208 +                       diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];
17209 +       if(diff < 2) {
17210 +               return 0;
17211 +       } else {
17212 +               return 1;
17213 +       }
17214 +}
17215 +
17216 +/**
17217 + * This function handles ADP Probe Interrupts
17218 + */
17219 +static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
17220 +                                                uint32_t val)
17221 +{
17222 +       adpctl_data_t adpctl = {.d32 = 0 };
17223 +       gpwrdn_data_t gpwrdn, temp;
17224 +       adpctl.d32 = val;
17225 +
17226 +       temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17227 +       core_if->adp.probe_counter++;
17228 +       core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17229 +       if (adpctl.b.rtim == 0 && !temp.b.idsts){
17230 +               DWC_PRINTF("RTIM value is 0\n");
17231 +               goto exit;
17232 +       }
17233 +       if (set_timer_value(core_if, adpctl.b.rtim) &&
17234 +           core_if->adp.initial_probe) {
17235 +               core_if->adp.initial_probe = 0;
17236 +               dwc_otg_adp_probe_stop(core_if);
17237 +               gpwrdn.d32 = 0;
17238 +               gpwrdn.b.pmuactv = 1;
17239 +               gpwrdn.b.pmuintsel = 1;
17240 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17241 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17242 +
17243 +               /* check which value is for device mode and which for Host mode */
17244 +               if (!temp.b.idsts) {    /* considered host mode value is 0 */
17245 +                       /*
17246 +                        * Turn on VBUS after initial ADP probe.
17247 +                        */
17248 +                       core_if->op_state = A_HOST;
17249 +                       dwc_otg_enable_global_interrupts(core_if);
17250 +                       DWC_SPINUNLOCK(core_if->lock);
17251 +                       cil_hcd_start(core_if);
17252 +                       dwc_otg_adp_turnon_vbus(core_if);
17253 +                       DWC_SPINLOCK(core_if->lock);
17254 +               } else {
17255 +                       /*
17256 +                        * Initiate SRP after initial ADP probe.
17257 +                        */
17258 +                       dwc_otg_enable_global_interrupts(core_if);
17259 +                       dwc_otg_initiate_srp(core_if);
17260 +               }
17261 +       } else if (core_if->adp.probe_counter > 2){
17262 +               gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17263 +               if (compare_timer_values(core_if)) {
17264 +                       DWC_PRINTF("Difference in timer values !!! \n");
17265 +//                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
17266 +                       dwc_otg_adp_probe_stop(core_if);
17267 +
17268 +                       /* Power on the core */
17269 +                       if (core_if->power_down == 2) {
17270 +                               gpwrdn.b.pwrdnswtch = 1;
17271 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17272 +                                                gpwrdn, 0, gpwrdn.d32);
17273 +                       }
17274 +
17275 +                       /* check which value is for device mode and which for Host mode */
17276 +                       if (!temp.b.idsts) {    /* considered host mode value is 0 */
17277 +                               /* Disable Interrupt from Power Down Logic */
17278 +                               gpwrdn.d32 = 0;
17279 +                               gpwrdn.b.pmuintsel = 1;
17280 +                               gpwrdn.b.pmuactv = 1;
17281 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17282 +                                                gpwrdn, gpwrdn.d32, 0);
17283 +
17284 +                               /*
17285 +                                * Initialize the Core for Host mode.
17286 +                                */
17287 +                               core_if->op_state = A_HOST;
17288 +                               dwc_otg_core_init(core_if);
17289 +                               dwc_otg_enable_global_interrupts(core_if);
17290 +                               cil_hcd_start(core_if);
17291 +                       } else {
17292 +                               gotgctl_data_t gotgctl;
17293 +                               /* Mask SRP detected interrupt from Power Down Logic */
17294 +                               gpwrdn.d32 = 0;
17295 +                               gpwrdn.b.srp_det_msk = 1;
17296 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17297 +                                                gpwrdn, gpwrdn.d32, 0);
17298 +
17299 +                               /* Disable Power Down Logic */
17300 +                               gpwrdn.d32 = 0;
17301 +                               gpwrdn.b.pmuintsel = 1;
17302 +                               gpwrdn.b.pmuactv = 1;
17303 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17304 +                                                gpwrdn, gpwrdn.d32, 0);
17305 +
17306 +                               /*
17307 +                                * Initialize the Core for Device mode.
17308 +                                */
17309 +                               core_if->op_state = B_PERIPHERAL;
17310 +                               dwc_otg_core_init(core_if);
17311 +                               dwc_otg_enable_global_interrupts(core_if);
17312 +                               cil_pcd_start(core_if);
17313 +
17314 +                               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17315 +                               if (!gotgctl.b.bsesvld) {
17316 +                                       dwc_otg_initiate_srp(core_if);
17317 +                               }
17318 +                       }
17319 +               }
17320 +               if (core_if->power_down == 2) {
17321 +                       if (gpwrdn.b.bsessvld) {
17322 +                               /* Mask SRP detected interrupt from Power Down Logic */
17323 +                               gpwrdn.d32 = 0;
17324 +                               gpwrdn.b.srp_det_msk = 1;
17325 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17326 +
17327 +                               /* Disable Power Down Logic */
17328 +                               gpwrdn.d32 = 0;
17329 +                               gpwrdn.b.pmuactv = 1;
17330 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17331 +
17332 +                               /*
17333 +                                * Initialize the Core for Device mode.
17334 +                                */
17335 +                               core_if->op_state = B_PERIPHERAL;
17336 +                               dwc_otg_core_init(core_if);
17337 +                               dwc_otg_enable_global_interrupts(core_if);
17338 +                               cil_pcd_start(core_if);
17339 +                       }
17340 +               }
17341 +       }
17342 +exit:
17343 +       /* Clear interrupt */
17344 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17345 +       adpctl.b.adp_prb_int = 1;
17346 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17347 +
17348 +       return 0;
17349 +}
17350 +
17351 +/**
17352 + * This function hadles ADP Sense Interrupt
17353 + */
17354 +static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
17355 +{
17356 +       adpctl_data_t adpctl;
17357 +       /* Stop ADP Sense timer */
17358 +       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17359 +
17360 +       /* Restart ADP Sense timer */
17361 +       dwc_otg_adp_sense_timer_start(core_if);
17362 +
17363 +       /* Clear interrupt */
17364 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17365 +       adpctl.b.adp_sns_int = 1;
17366 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17367 +
17368 +       return 0;
17369 +}
17370 +
17371 +/**
17372 + * This function handles ADP Probe Interrupts
17373 + */
17374 +static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
17375 +                                                uint32_t val)
17376 +{
17377 +       adpctl_data_t adpctl = {.d32 = 0 };
17378 +       adpctl.d32 = val;
17379 +       set_timer_value(core_if, adpctl.b.rtim);
17380 +
17381 +       /* Clear interrupt */
17382 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17383 +       adpctl.b.adp_tmout_int = 1;
17384 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17385 +
17386 +       return 0;
17387 +}
17388 +
17389 +/**
17390 + * ADP Interrupt handler.
17391 + *
17392 + */
17393 +int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
17394 +{
17395 +       int retval = 0;
17396 +       adpctl_data_t adpctl = {.d32 = 0};
17397 +
17398 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17399 +       DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
17400 +
17401 +       if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
17402 +               DWC_PRINTF("ADP Sense interrupt\n");
17403 +               retval |= dwc_otg_adp_handle_sns_intr(core_if);
17404 +       }
17405 +       if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
17406 +               DWC_PRINTF("ADP timeout interrupt\n");
17407 +               retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
17408 +       }
17409 +       if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
17410 +               DWC_PRINTF("ADP Probe interrupt\n");
17411 +               adpctl.b.adp_prb_int = 1;
17412 +               retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
17413 +       }
17414 +
17415 +//     dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
17416 +       //dwc_otg_adp_write_reg(core_if, adpctl.d32);
17417 +       DWC_PRINTF("RETURN FROM ADP ISR\n");
17418 +
17419 +       return retval;
17420 +}
17421 +
17422 +/**
17423 + *
17424 + * @param core_if Programming view of DWC_otg controller.
17425 + */
17426 +int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
17427 +{
17428 +
17429 +#ifndef DWC_HOST_ONLY
17430 +       hprt0_data_t hprt0;
17431 +       gpwrdn_data_t gpwrdn;
17432 +       DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
17433 +
17434 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17435 +       /* check which value is for device mode and which for Host mode */
17436 +       if (!gpwrdn.b.idsts) {  /* considered host mode value is 0 */
17437 +               DWC_PRINTF("SRP: Host mode\n");
17438 +
17439 +               if (core_if->adp_enable) {
17440 +                       dwc_otg_adp_probe_stop(core_if);
17441 +
17442 +                       /* Power on the core */
17443 +                       if (core_if->power_down == 2) {
17444 +                               gpwrdn.b.pwrdnswtch = 1;
17445 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17446 +                                                gpwrdn, 0, gpwrdn.d32);
17447 +                       }
17448 +
17449 +                       core_if->op_state = A_HOST;
17450 +                       dwc_otg_core_init(core_if);
17451 +                       dwc_otg_enable_global_interrupts(core_if);
17452 +                       cil_hcd_start(core_if);
17453 +               }
17454 +
17455 +               /* Turn on the port power bit. */
17456 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
17457 +               hprt0.b.prtpwr = 1;
17458 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17459 +
17460 +               /* Start the Connection timer. So a message can be displayed
17461 +                * if connect does not occur within 10 seconds. */
17462 +               cil_hcd_session_start(core_if);
17463 +       } else {
17464 +               DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
17465 +               if (core_if->adp_enable) {
17466 +                       dwc_otg_adp_probe_stop(core_if);
17467 +
17468 +                       /* Power on the core */
17469 +                       if (core_if->power_down == 2) {
17470 +                               gpwrdn.b.pwrdnswtch = 1;
17471 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17472 +                                                gpwrdn, 0, gpwrdn.d32);
17473 +                       }
17474 +
17475 +                       gpwrdn.d32 = 0;
17476 +                       gpwrdn.b.pmuactv = 0;
17477 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
17478 +                                        gpwrdn.d32);
17479 +
17480 +                       core_if->op_state = B_PERIPHERAL;
17481 +                       dwc_otg_core_init(core_if);
17482 +                       dwc_otg_enable_global_interrupts(core_if);
17483 +                       cil_pcd_start(core_if);
17484 +               }
17485 +       }
17486 +#endif
17487 +       return 1;
17488 +}
17489 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.h b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17490 new file mode 100644
17491 index 0000000..4110b25
17492 --- /dev/null
17493 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17494 @@ -0,0 +1,80 @@
17495 +/* ==========================================================================
17496 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
17497 + * $Revision: #7 $
17498 + * $Date: 2011/10/24 $
17499 + * $Change: 1871159 $
17500 + *
17501 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17502 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17503 + * otherwise expressly agreed to in writing between Synopsys and you.
17504 + *
17505 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17506 + * any End User Software License Agreement or Agreement for Licensed Product
17507 + * with Synopsys or any supplement thereto. You are permitted to use and
17508 + * redistribute this Software in source and binary forms, with or without
17509 + * modification, provided that redistributions of source code must retain this
17510 + * notice. You may not view, use, disclose, copy or distribute this file or
17511 + * any information contained herein except pursuant to this license grant from
17512 + * Synopsys. If you do not agree with this notice, including the disclaimer
17513 + * below, then you are not authorized to use the Software.
17514 + *
17515 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17516 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17517 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17518 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17519 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17520 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17521 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17522 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17523 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17524 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17525 + * DAMAGE.
17526 + * ========================================================================== */
17527 +
17528 +#ifndef __DWC_OTG_ADP_H__
17529 +#define __DWC_OTG_ADP_H__
17530 +
17531 +/**
17532 + * @file
17533 + *
17534 + * This file contains the Attach Detect Protocol interfaces and defines
17535 + * (functions) and structures for Linux.
17536 + *
17537 + */
17538 +
17539 +#define DWC_OTG_ADP_UNATTACHED 0
17540 +#define DWC_OTG_ADP_ATTACHED   1
17541 +#define DWC_OTG_ADP_UNKOWN     2
17542 +
17543 +typedef struct dwc_otg_adp {
17544 +       uint32_t adp_started;
17545 +       uint32_t initial_probe;
17546 +       int32_t probe_timer_values[2];
17547 +       uint32_t probe_enabled;
17548 +       uint32_t sense_enabled;
17549 +       dwc_timer_t *sense_timer;
17550 +       uint32_t sense_timer_started;
17551 +       dwc_timer_t *vbuson_timer;
17552 +       uint32_t vbuson_timer_started;
17553 +       uint32_t attached;
17554 +       uint32_t probe_counter;
17555 +       uint32_t gpwrdn;
17556 +} dwc_otg_adp_t;
17557 +
17558 +/**
17559 + * Attach Detect Protocol functions
17560 + */
17561 +
17562 +extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);
17563 +extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);
17564 +extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);
17565 +extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
17566 +extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
17567 +extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
17568 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
17569 +extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
17570 +extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
17571 +extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
17572 +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
17573 +
17574 +#endif //__DWC_OTG_ADP_H__
17575 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17576 new file mode 100644
17577 index 0000000..fab2961
17578 --- /dev/null
17579 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17580 @@ -0,0 +1,1210 @@
17581 +/* ==========================================================================
17582 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
17583 + * $Revision: #44 $
17584 + * $Date: 2010/11/29 $
17585 + * $Change: 1636033 $
17586 + *
17587 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17588 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17589 + * otherwise expressly agreed to in writing between Synopsys and you.
17590 + *
17591 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17592 + * any End User Software License Agreement or Agreement for Licensed Product
17593 + * with Synopsys or any supplement thereto. You are permitted to use and
17594 + * redistribute this Software in source and binary forms, with or without
17595 + * modification, provided that redistributions of source code must retain this
17596 + * notice. You may not view, use, disclose, copy or distribute this file or
17597 + * any information contained herein except pursuant to this license grant from
17598 + * Synopsys. If you do not agree with this notice, including the disclaimer
17599 + * below, then you are not authorized to use the Software.
17600 + *
17601 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17602 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17603 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17604 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17605 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17606 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17607 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17608 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17609 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17610 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17611 + * DAMAGE.
17612 + * ========================================================================== */
17613 +
17614 +/** @file
17615 + *
17616 + * The diagnostic interface will provide access to the controller for
17617 + * bringing up the hardware and testing.  The Linux driver attributes
17618 + * feature will be used to provide the Linux Diagnostic
17619 + * Interface. These attributes are accessed through sysfs.
17620 + */
17621 +
17622 +/** @page "Linux Module Attributes"
17623 + *
17624 + * The Linux module attributes feature is used to provide the Linux
17625 + * Diagnostic Interface.  These attributes are accessed through sysfs.
17626 + * The diagnostic interface will provide access to the controller for
17627 + * bringing up the hardware and testing.
17628 +
17629 + The following table shows the attributes.
17630 + <table>
17631 + <tr>
17632 + <td><b> Name</b></td>
17633 + <td><b> Description</b></td>
17634 + <td><b> Access</b></td>
17635 + </tr>
17636 +
17637 + <tr>
17638 + <td> mode </td>
17639 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
17640 + <td> Read</td>
17641 + </tr>
17642 +
17643 + <tr>
17644 + <td> hnpcapable </td>
17645 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
17646 + Read returns the current value.</td>
17647 + <td> Read/Write</td>
17648 + </tr>
17649 +
17650 + <tr>
17651 + <td> srpcapable </td>
17652 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
17653 + Read returns the current value.</td>
17654 + <td> Read/Write</td>
17655 + </tr>
17656 +
17657 + <tr>
17658 + <td> hsic_connect </td>
17659 + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
17660 + Read returns the current value.</td>
17661 + <td> Read/Write</td>
17662 + </tr>
17663 +
17664 + <tr>
17665 + <td> inv_sel_hsic </td>
17666 + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
17667 + Read returns the current value.</td>
17668 + <td> Read/Write</td>
17669 + </tr>
17670 +
17671 + <tr>
17672 + <td> hnp </td>
17673 + <td> Initiates the Host Negotiation Protocol.  Read returns the status.</td>
17674 + <td> Read/Write</td>
17675 + </tr>
17676 +
17677 + <tr>
17678 + <td> srp </td>
17679 + <td> Initiates the Session Request Protocol.  Read returns the status.</td>
17680 + <td> Read/Write</td>
17681 + </tr>
17682 +
17683 + <tr>
17684 + <td> buspower </td>
17685 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
17686 + <td> Read/Write</td>
17687 + </tr>
17688 +
17689 + <tr>
17690 + <td> bussuspend </td>
17691 + <td> Suspends the USB bus.</td>
17692 + <td> Read/Write</td>
17693 + </tr>
17694 +
17695 + <tr>
17696 + <td> busconnected </td>
17697 + <td> Gets the connection status of the bus</td>
17698 + <td> Read</td>
17699 + </tr>
17700 +
17701 + <tr>
17702 + <td> gotgctl </td>
17703 + <td> Gets or sets the Core Control Status Register.</td>
17704 + <td> Read/Write</td>
17705 + </tr>
17706 +
17707 + <tr>
17708 + <td> gusbcfg </td>
17709 + <td> Gets or sets the Core USB Configuration Register</td>
17710 + <td> Read/Write</td>
17711 + </tr>
17712 +
17713 + <tr>
17714 + <td> grxfsiz </td>
17715 + <td> Gets or sets the Receive FIFO Size Register</td>
17716 + <td> Read/Write</td>
17717 + </tr>
17718 +
17719 + <tr>
17720 + <td> gnptxfsiz </td>
17721 + <td> Gets or sets the non-periodic Transmit Size Register</td>
17722 + <td> Read/Write</td>
17723 + </tr>
17724 +
17725 + <tr>
17726 + <td> gpvndctl </td>
17727 + <td> Gets or sets the PHY Vendor Control Register</td>
17728 + <td> Read/Write</td>
17729 + </tr>
17730 +
17731 + <tr>
17732 + <td> ggpio </td>
17733 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
17734 + or sets the upper 16 bits.</td>
17735 + <td> Read/Write</td>
17736 + </tr>
17737 +
17738 + <tr>
17739 + <td> guid </td>
17740 + <td> Gets or sets the value of the User ID Register</td>
17741 + <td> Read/Write</td>
17742 + </tr>
17743 +
17744 + <tr>
17745 + <td> gsnpsid </td>
17746 + <td> Gets the value of the Synopsys ID Regester</td>
17747 + <td> Read</td>
17748 + </tr>
17749 +
17750 + <tr>
17751 + <td> devspeed </td>
17752 + <td> Gets or sets the device speed setting in the DCFG register</td>
17753 + <td> Read/Write</td>
17754 + </tr>
17755 +
17756 + <tr>
17757 + <td> enumspeed </td>
17758 + <td> Gets the device enumeration Speed.</td>
17759 + <td> Read</td>
17760 + </tr>
17761 +
17762 + <tr>
17763 + <td> hptxfsiz </td>
17764 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
17765 + <td> Read</td>
17766 + </tr>
17767 +
17768 + <tr>
17769 + <td> hprt0 </td>
17770 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
17771 + <td> Read/Write</td>
17772 + </tr>
17773 +
17774 + <tr>
17775 + <td> regoffset </td>
17776 + <td> Sets the register offset for the next Register Access</td>
17777 + <td> Read/Write</td>
17778 + </tr>
17779 +
17780 + <tr>
17781 + <td> regvalue </td>
17782 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
17783 + <td> Read/Write</td>
17784 + </tr>
17785 +
17786 + <tr>
17787 + <td> remote_wakeup </td>
17788 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
17789 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
17790 + Wakeup signalling bit in the Device Control Register is set for 1
17791 + milli-second.</td>
17792 + <td> Read/Write</td>
17793 + </tr>
17794 +
17795 + <tr>
17796 + <td> rem_wakeup_pwrdn </td>
17797 + <td> On read, shows the status core - hibernated or not. On write, initiates
17798 + a remote wakeup of the device from Hibernation. </td>
17799 + <td> Read/Write</td>
17800 + </tr>
17801 +
17802 + <tr>
17803 + <td> mode_ch_tim_en </td>
17804 + <td> This bit is used to enable or disable the host core to wait for 200 PHY
17805 + clock cycles at the end of Resume to change the opmode signal to the PHY to 00
17806 + after Suspend or LPM. </td>
17807 + <td> Read/Write</td>
17808 + </tr>
17809 +
17810 + <tr>
17811 + <td> fr_interval </td>
17812 + <td> On read, shows the value of HFIR Frame Interval. On write, dynamically
17813 + reload HFIR register during runtime. The application can write a value to this
17814 + register only after the Port Enable bit of the Host Port Control and Status
17815 + register (HPRT.PrtEnaPort) has been set </td>
17816 + <td> Read/Write</td>
17817 + </tr>
17818 +
17819 + <tr>
17820 + <td> disconnect_us </td>
17821 + <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
17822 + which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>
17823 + <td> Read/Write</td>
17824 + </tr>
17825 +
17826 + <tr>
17827 + <td> regdump </td>
17828 + <td> Dumps the contents of core registers.</td>
17829 + <td> Read</td>
17830 + </tr>
17831 +
17832 + <tr>
17833 + <td> spramdump </td>
17834 + <td> Dumps the contents of core registers.</td>
17835 + <td> Read</td>
17836 + </tr>
17837 +
17838 + <tr>
17839 + <td> hcddump </td>
17840 + <td> Dumps the current HCD state.</td>
17841 + <td> Read</td>
17842 + </tr>
17843 +
17844 + <tr>
17845 + <td> hcd_frrem </td>
17846 + <td> Shows the average value of the Frame Remaining
17847 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
17848 + occurs. This can be used to determine the average interrupt latency. Also
17849 + shows the average Frame Remaining value for start_transfer and the "a" and
17850 + "b" sample points. The "a" and "b" sample points may be used during debugging
17851 + bto determine how long it takes to execute a section of the HCD code.</td>
17852 + <td> Read</td>
17853 + </tr>
17854 +
17855 + <tr>
17856 + <td> rd_reg_test </td>
17857 + <td> Displays the time required to read the GNPTXFSIZ register many times
17858 + (the output shows the number of times the register is read).
17859 + <td> Read</td>
17860 + </tr>
17861 +
17862 + <tr>
17863 + <td> wr_reg_test </td>
17864 + <td> Displays the time required to write the GNPTXFSIZ register many times
17865 + (the output shows the number of times the register is written).
17866 + <td> Read</td>
17867 + </tr>
17868 +
17869 + <tr>
17870 + <td> lpm_response </td>
17871 + <td> Gets or sets lpm_response mode. Applicable only in device mode.
17872 + <td> Write</td>
17873 + </tr>
17874 +
17875 + <tr>
17876 + <td> sleep_status </td>
17877 + <td> Shows sleep status of device.
17878 + <td> Read</td>
17879 + </tr>
17880 +
17881 + </table>
17882 +
17883 + Example usage:
17884 + To get the current mode:
17885 + cat /sys/devices/lm0/mode
17886 +
17887 + To power down the USB:
17888 + echo 0 > /sys/devices/lm0/buspower
17889 + */
17890 +
17891 +#include "dwc_otg_os_dep.h"
17892 +#include "dwc_os.h"
17893 +#include "dwc_otg_driver.h"
17894 +#include "dwc_otg_attr.h"
17895 +#include "dwc_otg_core_if.h"
17896 +#include "dwc_otg_pcd_if.h"
17897 +#include "dwc_otg_hcd_if.h"
17898 +
17899 +/*
17900 + * MACROs for defining sysfs attribute
17901 + */
17902 +#ifdef LM_INTERFACE
17903 +
17904 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17905 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17906 +{ \
17907 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17908 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);             \
17909 +       uint32_t val; \
17910 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17911 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17912 +}
17913 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17914 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17915 +                                       const char *buf, size_t count) \
17916 +{ \
17917 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17918 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17919 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17920 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17921 +       return count; \
17922 +}
17923 +
17924 +#elif defined(PCI_INTERFACE)
17925 +
17926 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17927 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17928 +{ \
17929 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);      \
17930 +       uint32_t val; \
17931 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17932 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17933 +}
17934 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17935 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17936 +                                       const char *buf, size_t count) \
17937 +{ \
17938 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17939 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17940 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17941 +       return count; \
17942 +}
17943 +
17944 +#elif defined(PLATFORM_INTERFACE)
17945 +
17946 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17947 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17948 +{ \
17949 +        struct platform_device *platform_dev = \
17950 +                container_of(_dev, struct platform_device, dev); \
17951 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);  \
17952 +       uint32_t val; \
17953 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17954 +                    __func__, _dev, platform_dev, otg_dev); \
17955 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17956 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17957 +}
17958 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17959 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17960 +                                       const char *buf, size_t count) \
17961 +{ \
17962 +        struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17963 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17964 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17965 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17966 +       return count; \
17967 +}
17968 +#endif
17969 +
17970 +/*
17971 + * MACROs for defining sysfs attribute for 32-bit registers
17972 + */
17973 +#ifdef LM_INTERFACE
17974 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17975 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17976 +{ \
17977 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17978 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17979 +       uint32_t val; \
17980 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17981 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17982 +}
17983 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17984 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17985 +                                       const char *buf, size_t count) \
17986 +{ \
17987 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17988 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17989 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
17990 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17991 +       return count; \
17992 +}
17993 +#elif defined(PCI_INTERFACE)
17994 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17995 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17996 +{ \
17997 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17998 +       uint32_t val; \
17999 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
18000 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
18001 +}
18002 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18003 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
18004 +                                       const char *buf, size_t count) \
18005 +{ \
18006 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
18007 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
18008 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
18009 +       return count; \
18010 +}
18011 +
18012 +#elif defined(PLATFORM_INTERFACE)
18013 +#include "dwc_otg_dbg.h"
18014 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18015 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
18016 +{ \
18017 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
18018 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
18019 +       uint32_t val; \
18020 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
18021 +                    __func__, _dev, platform_dev, otg_dev); \
18022 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
18023 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
18024 +}
18025 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18026 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
18027 +                                       const char *buf, size_t count) \
18028 +{ \
18029 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
18030 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
18031 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
18032 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
18033 +       return count; \
18034 +}
18035 +
18036 +#endif
18037 +
18038 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
18039 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
18040 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
18041 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
18042 +
18043 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
18044 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
18045 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
18046 +
18047 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
18048 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18049 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
18050 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
18051 +
18052 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
18053 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
18054 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
18055 +
18056 +/** @name Functions for Show/Store of Attributes */
18057 +/**@{*/
18058 +
18059 +/**
18060 + * Helper function returning the otg_device structure of the given device
18061 + */
18062 +static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
18063 +{
18064 +        dwc_otg_device_t *otg_dev;
18065 +        DWC_OTG_GETDRVDEV(otg_dev, _dev);
18066 +        return otg_dev;
18067 +}
18068 +
18069 +/**
18070 + * Show the register offset of the Register Access.
18071 + */
18072 +static ssize_t regoffset_show(struct device *_dev,
18073 +                             struct device_attribute *attr, char *buf)
18074 +{
18075 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18076 +       return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
18077 +                       otg_dev->os_dep.reg_offset);
18078 +}
18079 +
18080 +/**
18081 + * Set the register offset for the next Register Access        Read/Write
18082 + */
18083 +static ssize_t regoffset_store(struct device *_dev,
18084 +                              struct device_attribute *attr,
18085 +                              const char *buf, size_t count)
18086 +{
18087 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18088 +       uint32_t offset = simple_strtoul(buf, NULL, 16);
18089 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
18090 +       if (offset < SZ_256K) {
18091 +#elif  defined(PCI_INTERFACE)
18092 +       if (offset < 0x00040000) {
18093 +#endif
18094 +               otg_dev->os_dep.reg_offset = offset;
18095 +       } else {
18096 +               dev_err(_dev, "invalid offset\n");
18097 +       }
18098 +
18099 +       return count;
18100 +}
18101 +
18102 +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
18103 +
18104 +/**
18105 + * Show the value of the register at the offset in the reg_offset
18106 + * attribute.
18107 + */
18108 +static ssize_t regvalue_show(struct device *_dev,
18109 +                            struct device_attribute *attr, char *buf)
18110 +{
18111 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18112 +       uint32_t val;
18113 +       volatile uint32_t *addr;
18114 +
18115 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18116 +               /* Calculate the address */
18117 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18118 +                                    (uint8_t *) otg_dev->os_dep.base);
18119 +               val = DWC_READ_REG32(addr);
18120 +               return snprintf(buf,
18121 +                               sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
18122 +                               "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,
18123 +                               val);
18124 +       } else {
18125 +               dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);
18126 +               return sprintf(buf, "invalid offset\n");
18127 +       }
18128 +}
18129 +
18130 +/**
18131 + * Store the value in the register at the offset in the reg_offset
18132 + * attribute.
18133 + *
18134 + */
18135 +static ssize_t regvalue_store(struct device *_dev,
18136 +                             struct device_attribute *attr,
18137 +                             const char *buf, size_t count)
18138 +{
18139 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18140 +       volatile uint32_t *addr;
18141 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18142 +       //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
18143 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18144 +               /* Calculate the address */
18145 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18146 +                                    (uint8_t *) otg_dev->os_dep.base);
18147 +               DWC_WRITE_REG32(addr, val);
18148 +       } else {
18149 +               dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
18150 +                       otg_dev->os_dep.reg_offset);
18151 +       }
18152 +       return count;
18153 +}
18154 +
18155 +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
18156 +
18157 +/*
18158 + * Attributes
18159 + */
18160 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
18161 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
18162 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");
18163 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
18164 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
18165 +
18166 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18167 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18168 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
18169 +
18170 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
18171 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
18172 +                            &(otg_dev->core_if->core_global_regs->gusbcfg),
18173 +                            "GUSBCFG");
18174 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
18175 +                            &(otg_dev->core_if->core_global_regs->grxfsiz),
18176 +                            "GRXFSIZ");
18177 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
18178 +                            &(otg_dev->core_if->core_global_regs->gnptxfsiz),
18179 +                            "GNPTXFSIZ");
18180 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
18181 +                            &(otg_dev->core_if->core_global_regs->gpvndctl),
18182 +                            "GPVNDCTL");
18183 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
18184 +                            &(otg_dev->core_if->core_global_regs->ggpio),
18185 +                            "GGPIO");
18186 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
18187 +                            "GUID");
18188 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
18189 +                            &(otg_dev->core_if->core_global_regs->gsnpsid),
18190 +                            "GSNPSID");
18191 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
18192 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
18193 +
18194 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
18195 +                            &(otg_dev->core_if->core_global_regs->hptxfsiz),
18196 +                            "HPTXFSIZ");
18197 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
18198 +
18199 +/**
18200 + * @todo Add code to initiate the HNP.
18201 + */
18202 +/**
18203 + * Show the HNP status bit
18204 + */
18205 +static ssize_t hnp_show(struct device *_dev,
18206 +                       struct device_attribute *attr, char *buf)
18207 +{
18208 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18209 +       return sprintf(buf, "HstNegScs = 0x%x\n",
18210 +                      dwc_otg_get_hnpstatus(otg_dev->core_if));
18211 +}
18212 +
18213 +/**
18214 + * Set the HNP Request bit
18215 + */
18216 +static ssize_t hnp_store(struct device *_dev,
18217 +                        struct device_attribute *attr,
18218 +                        const char *buf, size_t count)
18219 +{
18220 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18221 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18222 +       dwc_otg_set_hnpreq(otg_dev->core_if, in);
18223 +       return count;
18224 +}
18225 +
18226 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
18227 +
18228 +/**
18229 + * @todo Add code to initiate the SRP.
18230 + */
18231 +/**
18232 + * Show the SRP status bit
18233 + */
18234 +static ssize_t srp_show(struct device *_dev,
18235 +                       struct device_attribute *attr, char *buf)
18236 +{
18237 +#ifndef DWC_HOST_ONLY
18238 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18239 +       return sprintf(buf, "SesReqScs = 0x%x\n",
18240 +                      dwc_otg_get_srpstatus(otg_dev->core_if));
18241 +#else
18242 +       return sprintf(buf, "Host Only Mode!\n");
18243 +#endif
18244 +}
18245 +
18246 +/**
18247 + * Set the SRP Request bit
18248 + */
18249 +static ssize_t srp_store(struct device *_dev,
18250 +                        struct device_attribute *attr,
18251 +                        const char *buf, size_t count)
18252 +{
18253 +#ifndef DWC_HOST_ONLY
18254 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18255 +       dwc_otg_pcd_initiate_srp(otg_dev->pcd);
18256 +#endif
18257 +       return count;
18258 +}
18259 +
18260 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
18261 +
18262 +/**
18263 + * @todo Need to do more for power on/off?
18264 + */
18265 +/**
18266 + * Show the Bus Power status
18267 + */
18268 +static ssize_t buspower_show(struct device *_dev,
18269 +                            struct device_attribute *attr, char *buf)
18270 +{
18271 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18272 +       return sprintf(buf, "Bus Power = 0x%x\n",
18273 +                      dwc_otg_get_prtpower(otg_dev->core_if));
18274 +}
18275 +
18276 +/**
18277 + * Set the Bus Power status
18278 + */
18279 +static ssize_t buspower_store(struct device *_dev,
18280 +                             struct device_attribute *attr,
18281 +                             const char *buf, size_t count)
18282 +{
18283 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18284 +       uint32_t on = simple_strtoul(buf, NULL, 16);
18285 +       dwc_otg_set_prtpower(otg_dev->core_if, on);
18286 +       return count;
18287 +}
18288 +
18289 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
18290 +
18291 +/**
18292 + * @todo Need to do more for suspend?
18293 + */
18294 +/**
18295 + * Show the Bus Suspend status
18296 + */
18297 +static ssize_t bussuspend_show(struct device *_dev,
18298 +                              struct device_attribute *attr, char *buf)
18299 +{
18300 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18301 +       return sprintf(buf, "Bus Suspend = 0x%x\n",
18302 +                      dwc_otg_get_prtsuspend(otg_dev->core_if));
18303 +}
18304 +
18305 +/**
18306 + * Set the Bus Suspend status
18307 + */
18308 +static ssize_t bussuspend_store(struct device *_dev,
18309 +                               struct device_attribute *attr,
18310 +                               const char *buf, size_t count)
18311 +{
18312 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18313 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18314 +       dwc_otg_set_prtsuspend(otg_dev->core_if, in);
18315 +       return count;
18316 +}
18317 +
18318 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
18319 +
18320 +/**
18321 + * Show the Mode Change Ready Timer status
18322 + */
18323 +static ssize_t mode_ch_tim_en_show(struct device *_dev,
18324 +                                  struct device_attribute *attr, char *buf)
18325 +{
18326 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18327 +       return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
18328 +                      dwc_otg_get_mode_ch_tim(otg_dev->core_if));
18329 +}
18330 +
18331 +/**
18332 + * Set the Mode Change Ready Timer status
18333 + */
18334 +static ssize_t mode_ch_tim_en_store(struct device *_dev,
18335 +                                   struct device_attribute *attr,
18336 +                                   const char *buf, size_t count)
18337 +{
18338 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18339 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18340 +       dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);
18341 +       return count;
18342 +}
18343 +
18344 +DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);
18345 +
18346 +/**
18347 + * Show the value of HFIR Frame Interval bitfield
18348 + */
18349 +static ssize_t fr_interval_show(struct device *_dev,
18350 +                               struct device_attribute *attr, char *buf)
18351 +{
18352 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18353 +       return sprintf(buf, "Frame Interval = 0x%x\n",
18354 +                      dwc_otg_get_fr_interval(otg_dev->core_if));
18355 +}
18356 +
18357 +/**
18358 + * Set the HFIR Frame Interval value
18359 + */
18360 +static ssize_t fr_interval_store(struct device *_dev,
18361 +                                struct device_attribute *attr,
18362 +                                const char *buf, size_t count)
18363 +{
18364 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18365 +       uint32_t in = simple_strtoul(buf, NULL, 10);
18366 +       dwc_otg_set_fr_interval(otg_dev->core_if, in);
18367 +       return count;
18368 +}
18369 +
18370 +DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);
18371 +
18372 +/**
18373 + * Show the status of Remote Wakeup.
18374 + */
18375 +static ssize_t remote_wakeup_show(struct device *_dev,
18376 +                                 struct device_attribute *attr, char *buf)
18377 +{
18378 +#ifndef DWC_HOST_ONLY
18379 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18380 +
18381 +       return sprintf(buf,
18382 +                      "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
18383 +                      dwc_otg_get_remotewakesig(otg_dev->core_if),
18384 +                      dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
18385 +                      dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
18386 +#else
18387 +       return sprintf(buf, "Host Only Mode!\n");
18388 +#endif /* DWC_HOST_ONLY */
18389 +}
18390 +
18391 +/**
18392 + * Initiate a remote wakeup of the host.  The Device control register
18393 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
18394 + * flag is set.
18395 + *
18396 + */
18397 +static ssize_t remote_wakeup_store(struct device *_dev,
18398 +                                  struct device_attribute *attr,
18399 +                                  const char *buf, size_t count)
18400 +{
18401 +#ifndef DWC_HOST_ONLY
18402 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18403 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18404 +
18405 +       if (val & 1) {
18406 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
18407 +       } else {
18408 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
18409 +       }
18410 +#endif /* DWC_HOST_ONLY */
18411 +       return count;
18412 +}
18413 +
18414 +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
18415 +           remote_wakeup_store);
18416 +
18417 +/**
18418 + * Show the whether core is hibernated or not.
18419 + */
18420 +static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
18421 +                                    struct device_attribute *attr, char *buf)
18422 +{
18423 +#ifndef DWC_HOST_ONLY
18424 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18425 +
18426 +       if (dwc_otg_get_core_state(otg_dev->core_if)) {
18427 +               DWC_PRINTF("Core is in hibernation\n");
18428 +       } else {
18429 +               DWC_PRINTF("Core is not in hibernation\n");
18430 +       }
18431 +#endif /* DWC_HOST_ONLY */
18432 +       return 0;
18433 +}
18434 +
18435 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
18436 +                                             int rem_wakeup, int reset);
18437 +
18438 +/**
18439 + * Initiate a remote wakeup of the device to exit from hibernation.
18440 + */
18441 +static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,
18442 +                                     struct device_attribute *attr,
18443 +                                     const char *buf, size_t count)
18444 +{
18445 +#ifndef DWC_HOST_ONLY
18446 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18447 +       dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
18448 +#endif
18449 +       return count;
18450 +}
18451 +
18452 +DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,
18453 +           rem_wakeup_pwrdn_store);
18454 +
18455 +static ssize_t disconnect_us(struct device *_dev,
18456 +                            struct device_attribute *attr,
18457 +                            const char *buf, size_t count)
18458 +{
18459 +
18460 +#ifndef DWC_HOST_ONLY
18461 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18462 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18463 +       DWC_PRINTF("The Passed value is %04x\n", val);
18464 +
18465 +       dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);
18466 +
18467 +#endif /* DWC_HOST_ONLY */
18468 +       return count;
18469 +}
18470 +
18471 +DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);
18472 +
18473 +/**
18474 + * Dump global registers and either host or device registers (depending on the
18475 + * current mode of the core).
18476 + */
18477 +static ssize_t regdump_show(struct device *_dev,
18478 +                           struct device_attribute *attr, char *buf)
18479 +{
18480 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18481 +
18482 +       dwc_otg_dump_global_registers(otg_dev->core_if);
18483 +       if (dwc_otg_is_host_mode(otg_dev->core_if)) {
18484 +               dwc_otg_dump_host_registers(otg_dev->core_if);
18485 +       } else {
18486 +               dwc_otg_dump_dev_registers(otg_dev->core_if);
18487 +
18488 +       }
18489 +       return sprintf(buf, "Register Dump\n");
18490 +}
18491 +
18492 +DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
18493 +
18494 +/**
18495 + * Dump global registers and either host or device registers (depending on the
18496 + * current mode of the core).
18497 + */
18498 +static ssize_t spramdump_show(struct device *_dev,
18499 +                             struct device_attribute *attr, char *buf)
18500 +{
18501 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18502 +
18503 +       dwc_otg_dump_spram(otg_dev->core_if);
18504 +
18505 +       return sprintf(buf, "SPRAM Dump\n");
18506 +}
18507 +
18508 +DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
18509 +
18510 +/**
18511 + * Dump the current hcd state.
18512 + */
18513 +static ssize_t hcddump_show(struct device *_dev,
18514 +                           struct device_attribute *attr, char *buf)
18515 +{
18516 +#ifndef DWC_DEVICE_ONLY
18517 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18518 +       dwc_otg_hcd_dump_state(otg_dev->hcd);
18519 +#endif /* DWC_DEVICE_ONLY */
18520 +       return sprintf(buf, "HCD Dump\n");
18521 +}
18522 +
18523 +DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
18524 +
18525 +/**
18526 + * Dump the average frame remaining at SOF. This can be used to
18527 + * determine average interrupt latency. Frame remaining is also shown for
18528 + * start transfer and two additional sample points.
18529 + */
18530 +static ssize_t hcd_frrem_show(struct device *_dev,
18531 +                             struct device_attribute *attr, char *buf)
18532 +{
18533 +#ifndef DWC_DEVICE_ONLY
18534 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18535 +
18536 +       dwc_otg_hcd_dump_frrem(otg_dev->hcd);
18537 +#endif /* DWC_DEVICE_ONLY */
18538 +       return sprintf(buf, "HCD Dump Frame Remaining\n");
18539 +}
18540 +
18541 +DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
18542 +
18543 +/**
18544 + * Displays the time required to read the GNPTXFSIZ register many times (the
18545 + * output shows the number of times the register is read).
18546 + */
18547 +#define RW_REG_COUNT 10000000
18548 +#define MSEC_PER_JIFFIE 1000/HZ
18549 +static ssize_t rd_reg_test_show(struct device *_dev,
18550 +                               struct device_attribute *attr, char *buf)
18551 +{
18552 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18553 +       int i;
18554 +       int time;
18555 +       int start_jiffies;
18556 +
18557 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18558 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18559 +       start_jiffies = jiffies;
18560 +       for (i = 0; i < RW_REG_COUNT; i++) {
18561 +               dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18562 +       }
18563 +       time = jiffies - start_jiffies;
18564 +       return sprintf(buf,
18565 +                      "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18566 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18567 +}
18568 +
18569 +DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
18570 +
18571 +/**
18572 + * Displays the time required to write the GNPTXFSIZ register many times (the
18573 + * output shows the number of times the register is written).
18574 + */
18575 +static ssize_t wr_reg_test_show(struct device *_dev,
18576 +                               struct device_attribute *attr, char *buf)
18577 +{
18578 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18579 +       uint32_t reg_val;
18580 +       int i;
18581 +       int time;
18582 +       int start_jiffies;
18583 +
18584 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18585 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18586 +       reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18587 +       start_jiffies = jiffies;
18588 +       for (i = 0; i < RW_REG_COUNT; i++) {
18589 +               dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
18590 +       }
18591 +       time = jiffies - start_jiffies;
18592 +       return sprintf(buf,
18593 +                      "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18594 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18595 +}
18596 +
18597 +DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
18598 +
18599 +#ifdef CONFIG_USB_DWC_OTG_LPM
18600 +
18601 +/**
18602 +* Show the lpm_response attribute.
18603 +*/
18604 +static ssize_t lpmresp_show(struct device *_dev,
18605 +                           struct device_attribute *attr, char *buf)
18606 +{
18607 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18608 +
18609 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
18610 +               return sprintf(buf, "** LPM is DISABLED **\n");
18611 +
18612 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18613 +               return sprintf(buf, "** Current mode is not device mode\n");
18614 +       }
18615 +       return sprintf(buf, "lpm_response = %d\n",
18616 +                      dwc_otg_get_lpmresponse(otg_dev->core_if));
18617 +}
18618 +
18619 +/**
18620 +* Store the lpm_response attribute.
18621 +*/
18622 +static ssize_t lpmresp_store(struct device *_dev,
18623 +                            struct device_attribute *attr,
18624 +                            const char *buf, size_t count)
18625 +{
18626 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18627 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18628 +
18629 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
18630 +               return 0;
18631 +       }
18632 +
18633 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18634 +               return 0;
18635 +       }
18636 +
18637 +       dwc_otg_set_lpmresponse(otg_dev->core_if, val);
18638 +       return count;
18639 +}
18640 +
18641 +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
18642 +
18643 +/**
18644 +* Show the sleep_status attribute.
18645 +*/
18646 +static ssize_t sleepstatus_show(struct device *_dev,
18647 +                               struct device_attribute *attr, char *buf)
18648 +{
18649 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18650 +       return sprintf(buf, "Sleep Status = %d\n",
18651 +                      dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
18652 +}
18653 +
18654 +/**
18655 + * Store the sleep_status attribure.
18656 + */
18657 +static ssize_t sleepstatus_store(struct device *_dev,
18658 +                                struct device_attribute *attr,
18659 +                                const char *buf, size_t count)
18660 +{
18661 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18662 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
18663 +
18664 +       if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
18665 +               if (dwc_otg_is_host_mode(core_if)) {
18666 +
18667 +                       DWC_PRINTF("Host initiated resume\n");
18668 +                       dwc_otg_set_prtresume(otg_dev->core_if, 1);
18669 +               }
18670 +       }
18671 +
18672 +       return count;
18673 +}
18674 +
18675 +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
18676 +           sleepstatus_store);
18677 +
18678 +#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
18679 +
18680 +/**@}*/
18681 +
18682 +/**
18683 + * Create the device files
18684 + */
18685 +void dwc_otg_attr_create(
18686 +#ifdef LM_INTERFACE
18687 +       struct lm_device *dev
18688 +#elif  defined(PCI_INTERFACE)
18689 +       struct pci_dev *dev
18690 +#elif  defined(PLATFORM_INTERFACE)
18691 +        struct platform_device *dev
18692 +#endif
18693 +    )
18694 +{
18695 +       int error;
18696 +
18697 +       error = device_create_file(&dev->dev, &dev_attr_regoffset);
18698 +       error = device_create_file(&dev->dev, &dev_attr_regvalue);
18699 +       error = device_create_file(&dev->dev, &dev_attr_mode);
18700 +       error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
18701 +       error = device_create_file(&dev->dev, &dev_attr_srpcapable);
18702 +       error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
18703 +       error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
18704 +       error = device_create_file(&dev->dev, &dev_attr_hnp);
18705 +       error = device_create_file(&dev->dev, &dev_attr_srp);
18706 +       error = device_create_file(&dev->dev, &dev_attr_buspower);
18707 +       error = device_create_file(&dev->dev, &dev_attr_bussuspend);
18708 +       error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18709 +       error = device_create_file(&dev->dev, &dev_attr_fr_interval);
18710 +       error = device_create_file(&dev->dev, &dev_attr_busconnected);
18711 +       error = device_create_file(&dev->dev, &dev_attr_gotgctl);
18712 +       error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
18713 +       error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
18714 +       error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
18715 +       error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
18716 +       error = device_create_file(&dev->dev, &dev_attr_ggpio);
18717 +       error = device_create_file(&dev->dev, &dev_attr_guid);
18718 +       error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
18719 +       error = device_create_file(&dev->dev, &dev_attr_devspeed);
18720 +       error = device_create_file(&dev->dev, &dev_attr_enumspeed);
18721 +       error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
18722 +       error = device_create_file(&dev->dev, &dev_attr_hprt0);
18723 +       error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
18724 +       error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18725 +       error = device_create_file(&dev->dev, &dev_attr_disconnect_us);
18726 +       error = device_create_file(&dev->dev, &dev_attr_regdump);
18727 +       error = device_create_file(&dev->dev, &dev_attr_spramdump);
18728 +       error = device_create_file(&dev->dev, &dev_attr_hcddump);
18729 +       error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
18730 +       error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
18731 +       error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
18732 +#ifdef CONFIG_USB_DWC_OTG_LPM
18733 +       error = device_create_file(&dev->dev, &dev_attr_lpm_response);
18734 +       error = device_create_file(&dev->dev, &dev_attr_sleep_status);
18735 +#endif
18736 +}
18737 +
18738 +/**
18739 + * Remove the device files
18740 + */
18741 +void dwc_otg_attr_remove(
18742 +#ifdef LM_INTERFACE
18743 +       struct lm_device *dev
18744 +#elif  defined(PCI_INTERFACE)
18745 +       struct pci_dev *dev
18746 +#elif  defined(PLATFORM_INTERFACE)
18747 +       struct platform_device *dev
18748 +#endif
18749 +    )
18750 +{
18751 +       device_remove_file(&dev->dev, &dev_attr_regoffset);
18752 +       device_remove_file(&dev->dev, &dev_attr_regvalue);
18753 +       device_remove_file(&dev->dev, &dev_attr_mode);
18754 +       device_remove_file(&dev->dev, &dev_attr_hnpcapable);
18755 +       device_remove_file(&dev->dev, &dev_attr_srpcapable);
18756 +       device_remove_file(&dev->dev, &dev_attr_hsic_connect);
18757 +       device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
18758 +       device_remove_file(&dev->dev, &dev_attr_hnp);
18759 +       device_remove_file(&dev->dev, &dev_attr_srp);
18760 +       device_remove_file(&dev->dev, &dev_attr_buspower);
18761 +       device_remove_file(&dev->dev, &dev_attr_bussuspend);
18762 +       device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18763 +       device_remove_file(&dev->dev, &dev_attr_fr_interval);
18764 +       device_remove_file(&dev->dev, &dev_attr_busconnected);
18765 +       device_remove_file(&dev->dev, &dev_attr_gotgctl);
18766 +       device_remove_file(&dev->dev, &dev_attr_gusbcfg);
18767 +       device_remove_file(&dev->dev, &dev_attr_grxfsiz);
18768 +       device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
18769 +       device_remove_file(&dev->dev, &dev_attr_gpvndctl);
18770 +       device_remove_file(&dev->dev, &dev_attr_ggpio);
18771 +       device_remove_file(&dev->dev, &dev_attr_guid);
18772 +       device_remove_file(&dev->dev, &dev_attr_gsnpsid);
18773 +       device_remove_file(&dev->dev, &dev_attr_devspeed);
18774 +       device_remove_file(&dev->dev, &dev_attr_enumspeed);
18775 +       device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
18776 +       device_remove_file(&dev->dev, &dev_attr_hprt0);
18777 +       device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
18778 +       device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18779 +       device_remove_file(&dev->dev, &dev_attr_disconnect_us);
18780 +       device_remove_file(&dev->dev, &dev_attr_regdump);
18781 +       device_remove_file(&dev->dev, &dev_attr_spramdump);
18782 +       device_remove_file(&dev->dev, &dev_attr_hcddump);
18783 +       device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
18784 +       device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
18785 +       device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
18786 +#ifdef CONFIG_USB_DWC_OTG_LPM
18787 +       device_remove_file(&dev->dev, &dev_attr_lpm_response);
18788 +       device_remove_file(&dev->dev, &dev_attr_sleep_status);
18789 +#endif
18790 +}
18791 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18792 new file mode 100644
18793 index 0000000..e10b67f
18794 --- /dev/null
18795 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18796 @@ -0,0 +1,89 @@
18797 +/* ==========================================================================
18798 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
18799 + * $Revision: #13 $
18800 + * $Date: 2010/06/21 $
18801 + * $Change: 1532021 $
18802 + *
18803 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18804 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18805 + * otherwise expressly agreed to in writing between Synopsys and you.
18806 + *
18807 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18808 + * any End User Software License Agreement or Agreement for Licensed Product
18809 + * with Synopsys or any supplement thereto. You are permitted to use and
18810 + * redistribute this Software in source and binary forms, with or without
18811 + * modification, provided that redistributions of source code must retain this
18812 + * notice. You may not view, use, disclose, copy or distribute this file or
18813 + * any information contained herein except pursuant to this license grant from
18814 + * Synopsys. If you do not agree with this notice, including the disclaimer
18815 + * below, then you are not authorized to use the Software.
18816 + *
18817 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18818 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18819 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18820 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18821 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18822 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18823 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18824 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18825 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18826 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18827 + * DAMAGE.
18828 + * ========================================================================== */
18829 +
18830 +#if !defined(__DWC_OTG_ATTR_H__)
18831 +#define __DWC_OTG_ATTR_H__
18832 +
18833 +/** @file
18834 + * This file contains the interface to the Linux device attributes.
18835 + */
18836 +extern struct device_attribute dev_attr_regoffset;
18837 +extern struct device_attribute dev_attr_regvalue;
18838 +
18839 +extern struct device_attribute dev_attr_mode;
18840 +extern struct device_attribute dev_attr_hnpcapable;
18841 +extern struct device_attribute dev_attr_srpcapable;
18842 +extern struct device_attribute dev_attr_hnp;
18843 +extern struct device_attribute dev_attr_srp;
18844 +extern struct device_attribute dev_attr_buspower;
18845 +extern struct device_attribute dev_attr_bussuspend;
18846 +extern struct device_attribute dev_attr_mode_ch_tim_en;
18847 +extern struct device_attribute dev_attr_fr_interval;
18848 +extern struct device_attribute dev_attr_busconnected;
18849 +extern struct device_attribute dev_attr_gotgctl;
18850 +extern struct device_attribute dev_attr_gusbcfg;
18851 +extern struct device_attribute dev_attr_grxfsiz;
18852 +extern struct device_attribute dev_attr_gnptxfsiz;
18853 +extern struct device_attribute dev_attr_gpvndctl;
18854 +extern struct device_attribute dev_attr_ggpio;
18855 +extern struct device_attribute dev_attr_guid;
18856 +extern struct device_attribute dev_attr_gsnpsid;
18857 +extern struct device_attribute dev_attr_devspeed;
18858 +extern struct device_attribute dev_attr_enumspeed;
18859 +extern struct device_attribute dev_attr_hptxfsiz;
18860 +extern struct device_attribute dev_attr_hprt0;
18861 +#ifdef CONFIG_USB_DWC_OTG_LPM
18862 +extern struct device_attribute dev_attr_lpm_response;
18863 +extern struct device_attribute devi_attr_sleep_status;
18864 +#endif
18865 +
18866 +void dwc_otg_attr_create(
18867 +#ifdef LM_INTERFACE
18868 +                               struct lm_device *dev
18869 +#elif  defined(PCI_INTERFACE)
18870 +                               struct pci_dev *dev
18871 +#elif  defined(PLATFORM_INTERFACE)
18872 +       struct platform_device *dev
18873 +#endif
18874 +    );
18875 +
18876 +void dwc_otg_attr_remove(
18877 +#ifdef LM_INTERFACE
18878 +                               struct lm_device *dev
18879 +#elif  defined(PCI_INTERFACE)
18880 +                               struct pci_dev *dev
18881 +#elif  defined(PLATFORM_INTERFACE)
18882 +       struct platform_device *dev
18883 +#endif
18884 +    );
18885 +#endif
18886 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18887 new file mode 100644
18888 index 0000000..bbb3d32
18889 --- /dev/null
18890 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18891 @@ -0,0 +1,1876 @@
18892 +/* ==========================================================================
18893 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18894 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18895 + * otherwise expressly agreed to in writing between Synopsys and you.
18896 + *
18897 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18898 + * any End User Software License Agreement or Agreement for Licensed Product
18899 + * with Synopsys or any supplement thereto. You are permitted to use and
18900 + * redistribute this Software in source and binary forms, with or without
18901 + * modification, provided that redistributions of source code must retain this
18902 + * notice. You may not view, use, disclose, copy or distribute this file or
18903 + * any information contained herein except pursuant to this license grant from
18904 + * Synopsys. If you do not agree with this notice, including the disclaimer
18905 + * below, then you are not authorized to use the Software.
18906 + *
18907 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18908 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18909 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18910 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18911 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18912 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18913 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18914 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18915 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18916 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18917 + * DAMAGE.
18918 + * ========================================================================== */
18919 +
18920 +/** @file
18921 + *
18922 + * This file contains the most of the CFI(Core Feature Interface)
18923 + * implementation for the OTG.
18924 + */
18925 +
18926 +#ifdef DWC_UTE_CFI
18927 +
18928 +#include "dwc_otg_pcd.h"
18929 +#include "dwc_otg_cfi.h"
18930 +
18931 +/** This definition should actually migrate to the Portability Library */
18932 +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
18933 +
18934 +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
18935 +
18936 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
18937 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
18938 +                                struct dwc_otg_pcd *pcd,
18939 +                                struct cfi_usb_ctrlrequest *ctrl_req);
18940 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
18941 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18942 +                            struct cfi_usb_ctrlrequest *req);
18943 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18944 +                                struct cfi_usb_ctrlrequest *req);
18945 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18946 +                               struct cfi_usb_ctrlrequest *req);
18947 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
18948 +                            struct cfi_usb_ctrlrequest *req);
18949 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
18950 +
18951 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
18952 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
18953 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
18954 +
18955 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
18956 +
18957 +/** This is the header of the all features descriptor */
18958 +static cfi_all_features_header_t all_props_desc_header = {
18959 +       .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
18960 +       .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
18961 +       .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
18962 +};
18963 +
18964 +/** This is an array of statically allocated feature descriptors */
18965 +static cfi_feature_desc_header_t prop_descs[] = {
18966 +
18967 +       /* FT_ID_DMA_MODE */
18968 +       {
18969 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
18970 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18971 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
18972 +        },
18973 +
18974 +       /* FT_ID_DMA_BUFFER_SETUP */
18975 +       {
18976 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
18977 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18978 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18979 +        },
18980 +
18981 +       /* FT_ID_DMA_BUFF_ALIGN */
18982 +       {
18983 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
18984 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18985 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18986 +        },
18987 +
18988 +       /* FT_ID_DMA_CONCAT_SETUP */
18989 +       {
18990 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
18991 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18992 +        //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
18993 +        },
18994 +
18995 +       /* FT_ID_DMA_CIRCULAR */
18996 +       {
18997 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
18998 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18999 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
19000 +        },
19001 +
19002 +       /* FT_ID_THRESHOLD_SETUP */
19003 +       {
19004 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
19005 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19006 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
19007 +        },
19008 +
19009 +       /* FT_ID_DFIFO_DEPTH */
19010 +       {
19011 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
19012 +        .bmAttributes = CFI_FEATURE_ATTR_RO,
19013 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19014 +        },
19015 +
19016 +       /* FT_ID_TX_FIFO_DEPTH */
19017 +       {
19018 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
19019 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19020 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19021 +        },
19022 +
19023 +       /* FT_ID_RX_FIFO_DEPTH */
19024 +       {
19025 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
19026 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
19027 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
19028 +        }
19029 +};
19030 +
19031 +/** The table of feature names */
19032 +cfi_string_t prop_name_table[] = {
19033 +       {FT_ID_DMA_MODE, "dma_mode"},
19034 +       {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
19035 +       {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
19036 +       {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
19037 +       {FT_ID_DMA_CIRCULAR, "buffer_circular"},
19038 +       {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
19039 +       {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
19040 +       {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
19041 +       {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
19042 +       {}
19043 +};
19044 +
19045 +/************************************************************************/
19046 +
19047 +/**
19048 + * Returns the name of the feature by its ID
19049 + * or NULL if no featute ID matches.
19050 + *
19051 + */
19052 +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
19053 +{
19054 +       cfi_string_t *pstr;
19055 +       *len = 0;
19056 +
19057 +       for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
19058 +               if (pstr->id == prop_id) {
19059 +                       *len = DWC_STRLEN(pstr->s);
19060 +                       return pstr->s;
19061 +               }
19062 +       }
19063 +       return NULL;
19064 +}
19065 +
19066 +/**
19067 + * This function handles all CFI specific control requests.
19068 + *
19069 + * Return a negative value to stall the DCE.
19070 + */
19071 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
19072 +{
19073 +       int retval = 0;
19074 +       dwc_otg_pcd_ep_t *ep = NULL;
19075 +       cfiobject_t *cfi = pcd->cfi;
19076 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19077 +       uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
19078 +       uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
19079 +       uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
19080 +       uint32_t regaddr = 0;
19081 +       uint32_t regval = 0;
19082 +
19083 +       /* Save this Control Request in the CFI object.
19084 +        * The data field will be assigned in the data stage completion CB function.
19085 +        */
19086 +       cfi->ctrl_req = *ctrl;
19087 +       cfi->ctrl_req.data = NULL;
19088 +
19089 +       cfi->need_gadget_att = 0;
19090 +       cfi->need_status_in_complete = 0;
19091 +
19092 +       switch (ctrl->bRequest) {
19093 +       case VEN_CORE_GET_FEATURES:
19094 +               retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
19095 +               if (retval >= 0) {
19096 +                       //dump_msg(cfi->buf_in.buf, retval);
19097 +                       ep = &pcd->ep0;
19098 +
19099 +                       retval = min((uint16_t) retval, wLen);
19100 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19101 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19102 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19103 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19104 +                       ep->dwc_ep.xfer_len = retval;
19105 +                       ep->dwc_ep.xfer_count = 0;
19106 +                       ep->dwc_ep.sent_zlp = 0;
19107 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19108 +
19109 +                       pcd->ep0_pending = 1;
19110 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19111 +               }
19112 +               retval = 0;
19113 +               break;
19114 +
19115 +       case VEN_CORE_GET_FEATURE:
19116 +               CFI_INFO("VEN_CORE_GET_FEATURE\n");
19117 +               retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
19118 +                                              pcd, ctrl);
19119 +               if (retval >= 0) {
19120 +                       ep = &pcd->ep0;
19121 +
19122 +                       retval = min((uint16_t) retval, wLen);
19123 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19124 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19125 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19126 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19127 +                       ep->dwc_ep.xfer_len = retval;
19128 +                       ep->dwc_ep.xfer_count = 0;
19129 +                       ep->dwc_ep.sent_zlp = 0;
19130 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19131 +
19132 +                       pcd->ep0_pending = 1;
19133 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19134 +               }
19135 +               CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
19136 +               dump_msg(cfi->buf_in.buf, retval);
19137 +               break;
19138 +
19139 +       case VEN_CORE_SET_FEATURE:
19140 +               CFI_INFO("VEN_CORE_SET_FEATURE\n");
19141 +               /* Set up an XFER to get the data stage of the control request,
19142 +                * which is the new value of the feature to be modified.
19143 +                */
19144 +               ep = &pcd->ep0;
19145 +               ep->dwc_ep.is_in = 0;
19146 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19147 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19148 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19149 +               ep->dwc_ep.xfer_len = wLen;
19150 +               ep->dwc_ep.xfer_count = 0;
19151 +               ep->dwc_ep.sent_zlp = 0;
19152 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19153 +
19154 +               pcd->ep0_pending = 1;
19155 +               /* Read the control write's data stage */
19156 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19157 +               retval = 0;
19158 +               break;
19159 +
19160 +       case VEN_CORE_RESET_FEATURES:
19161 +               CFI_INFO("VEN_CORE_RESET_FEATURES\n");
19162 +               cfi->need_gadget_att = 1;
19163 +               cfi->need_status_in_complete = 1;
19164 +               retval = cfi_preproc_reset(pcd, ctrl);
19165 +               CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
19166 +               break;
19167 +
19168 +       case VEN_CORE_ACTIVATE_FEATURES:
19169 +               CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
19170 +               break;
19171 +
19172 +       case VEN_CORE_READ_REGISTER:
19173 +               CFI_INFO("VEN_CORE_READ_REGISTER\n");
19174 +               /* wValue optionally contains the HI WORD of the register offset and
19175 +                * wIndex contains the LOW WORD of the register offset
19176 +                */
19177 +               if (wValue == 0) {
19178 +                       /* @TODO - MAS - fix the access to the base field */
19179 +                       regaddr = 0;
19180 +                       //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
19181 +                       //GET_CORE_IF(pcd)->co
19182 +                       regaddr |= wIndex;
19183 +               } else {
19184 +                       regaddr = (wValue << 16) | wIndex;
19185 +               }
19186 +
19187 +               /* Read a 32-bit value of the memory at the regaddr */
19188 +               regval = DWC_READ_REG32((uint32_t *) regaddr);
19189 +
19190 +               ep = &pcd->ep0;
19191 +               dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
19192 +               ep->dwc_ep.is_in = 1;
19193 +               ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19194 +               ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19195 +               ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19196 +               ep->dwc_ep.xfer_len = wLen;
19197 +               ep->dwc_ep.xfer_count = 0;
19198 +               ep->dwc_ep.sent_zlp = 0;
19199 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19200 +
19201 +               pcd->ep0_pending = 1;
19202 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19203 +               cfi->need_gadget_att = 0;
19204 +               retval = 0;
19205 +               break;
19206 +
19207 +       case VEN_CORE_WRITE_REGISTER:
19208 +               CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
19209 +               /* Set up an XFER to get the data stage of the control request,
19210 +                * which is the new value of the register to be modified.
19211 +                */
19212 +               ep = &pcd->ep0;
19213 +               ep->dwc_ep.is_in = 0;
19214 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19215 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19216 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19217 +               ep->dwc_ep.xfer_len = wLen;
19218 +               ep->dwc_ep.xfer_count = 0;
19219 +               ep->dwc_ep.sent_zlp = 0;
19220 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19221 +
19222 +               pcd->ep0_pending = 1;
19223 +               /* Read the control write's data stage */
19224 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19225 +               retval = 0;
19226 +               break;
19227 +
19228 +       default:
19229 +               retval = -DWC_E_NOT_SUPPORTED;
19230 +               break;
19231 +       }
19232 +
19233 +       return retval;
19234 +}
19235 +
19236 +/**
19237 + * This function prepares the core features descriptors and copies its
19238 + * raw representation into the buffer <buf>.
19239 + *
19240 + * The buffer structure is as follows:
19241 + *     all_features_header (8 bytes)
19242 + *     features_#1 (8 bytes + feature name string length)
19243 + *     features_#2 (8 bytes + feature name string length)
19244 + *     .....
19245 + *     features_#n - where n=the total count of feature descriptors
19246 + */
19247 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
19248 +{
19249 +       cfi_feature_desc_header_t *prop_hdr = prop_descs;
19250 +       cfi_feature_desc_header_t *prop;
19251 +       cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
19252 +       cfi_all_features_header_t *tmp;
19253 +       uint8_t *tmpbuf = buf;
19254 +       const uint8_t *pname = NULL;
19255 +       int i, j, namelen = 0, totlen;
19256 +
19257 +       /* Prepare and copy the core features into the buffer */
19258 +       CFI_INFO("%s:\n", __func__);
19259 +
19260 +       tmp = (cfi_all_features_header_t *) tmpbuf;
19261 +       *tmp = *all_props_hdr;
19262 +       tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
19263 +
19264 +       j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
19265 +       for (i = 0; i < j; i++, prop_hdr++) {
19266 +               pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
19267 +               prop = (cfi_feature_desc_header_t *) tmpbuf;
19268 +               *prop = *prop_hdr;
19269 +
19270 +               prop->bNameLen = namelen;
19271 +               prop->wLength =
19272 +                   DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
19273 +                                            namelen);
19274 +
19275 +               tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
19276 +               dwc_memcpy(tmpbuf, pname, namelen);
19277 +               tmpbuf += namelen;
19278 +       }
19279 +
19280 +       totlen = tmpbuf - buf;
19281 +
19282 +       if (totlen > 0) {
19283 +               tmp = (cfi_all_features_header_t *) buf;
19284 +               tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
19285 +       }
19286 +
19287 +       return totlen;
19288 +}
19289 +
19290 +/**
19291 + * This function releases all the dynamic memory in the CFI object.
19292 + */
19293 +static void cfi_release(cfiobject_t * cfiobj)
19294 +{
19295 +       cfi_ep_t *cfiep;
19296 +       dwc_list_link_t *tmp;
19297 +
19298 +       CFI_INFO("%s\n", __func__);
19299 +
19300 +       if (cfiobj->buf_in.buf) {
19301 +               DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
19302 +                            cfiobj->buf_in.addr);
19303 +               cfiobj->buf_in.buf = NULL;
19304 +       }
19305 +
19306 +       if (cfiobj->buf_out.buf) {
19307 +               DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
19308 +                            cfiobj->buf_out.addr);
19309 +               cfiobj->buf_out.buf = NULL;
19310 +       }
19311 +
19312 +       /* Free the Buffer Setup values for each EP */
19313 +       //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
19314 +       DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
19315 +               cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19316 +               cfi_free_ep_bs_dyn_data(cfiep);
19317 +       }
19318 +}
19319 +
19320 +/**
19321 + * This function frees the dynamically allocated EP buffer setup data.
19322 + */
19323 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
19324 +{
19325 +       if (cfiep->bm_sg) {
19326 +               DWC_FREE(cfiep->bm_sg);
19327 +               cfiep->bm_sg = NULL;
19328 +       }
19329 +
19330 +       if (cfiep->bm_align) {
19331 +               DWC_FREE(cfiep->bm_align);
19332 +               cfiep->bm_align = NULL;
19333 +       }
19334 +
19335 +       if (cfiep->bm_concat) {
19336 +               if (NULL != cfiep->bm_concat->wTxBytes) {
19337 +                       DWC_FREE(cfiep->bm_concat->wTxBytes);
19338 +                       cfiep->bm_concat->wTxBytes = NULL;
19339 +               }
19340 +               DWC_FREE(cfiep->bm_concat);
19341 +               cfiep->bm_concat = NULL;
19342 +       }
19343 +}
19344 +
19345 +/**
19346 + * This function initializes the default values of the features
19347 + * for a specific endpoint and should be called only once when
19348 + * the EP is enabled first time.
19349 + */
19350 +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
19351 +{
19352 +       int retval = 0;
19353 +
19354 +       cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
19355 +       if (NULL == cfiep->bm_sg) {
19356 +               CFI_INFO("Failed to allocate memory for SG feature value\n");
19357 +               return -DWC_E_NO_MEMORY;
19358 +       }
19359 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19360 +
19361 +       /* For the Concatenation feature's default value we do not allocate
19362 +        * memory for the wTxBytes field - it will be done in the set_feature_value
19363 +        * request handler.
19364 +        */
19365 +       cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
19366 +       if (NULL == cfiep->bm_concat) {
19367 +               CFI_INFO
19368 +                   ("Failed to allocate memory for CONCATENATION feature value\n");
19369 +               DWC_FREE(cfiep->bm_sg);
19370 +               return -DWC_E_NO_MEMORY;
19371 +       }
19372 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19373 +
19374 +       cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
19375 +       if (NULL == cfiep->bm_align) {
19376 +               CFI_INFO
19377 +                   ("Failed to allocate memory for Alignment feature value\n");
19378 +               DWC_FREE(cfiep->bm_sg);
19379 +               DWC_FREE(cfiep->bm_concat);
19380 +               return -DWC_E_NO_MEMORY;
19381 +       }
19382 +       dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
19383 +
19384 +       return retval;
19385 +}
19386 +
19387 +/**
19388 + * The callback function that notifies the CFI on the activation of
19389 + * an endpoint in the PCD. The following steps are done in this function:
19390 + *
19391 + *     Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's
19392 + *             active endpoint)
19393 + *     Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
19394 + *     Set the Buffer Mode to standard
19395 + *     Initialize the default values for all EP modes (SG, Circular, Concat, Align)
19396 + *     Add the cfi_ep_t object to the list of active endpoints in the CFI object
19397 + */
19398 +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19399 +                        struct dwc_otg_pcd_ep *ep)
19400 +{
19401 +       cfi_ep_t *cfiep;
19402 +       int retval = -DWC_E_NOT_SUPPORTED;
19403 +
19404 +       CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
19405 +                "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
19406 +       /* MAS - Check whether this endpoint already is in the list */
19407 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19408 +
19409 +       if (NULL == cfiep) {
19410 +               /* Allocate a cfi_ep_t object */
19411 +               cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
19412 +               if (NULL == cfiep) {
19413 +                       CFI_INFO
19414 +                           ("Unable to allocate memory for <cfiep> in function %s\n",
19415 +                            __func__);
19416 +                       return -DWC_E_NO_MEMORY;
19417 +               }
19418 +               dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
19419 +
19420 +               /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
19421 +               cfiep->ep = ep;
19422 +
19423 +               /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
19424 +               ep->dwc_ep.descs =
19425 +                   DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
19426 +                                 sizeof(dwc_otg_dma_desc_t),
19427 +                                 &ep->dwc_ep.descs_dma_addr);
19428 +
19429 +               if (NULL == ep->dwc_ep.descs) {
19430 +                       DWC_FREE(cfiep);
19431 +                       return -DWC_E_NO_MEMORY;
19432 +               }
19433 +
19434 +               DWC_LIST_INIT(&cfiep->lh);
19435 +
19436 +               /* Set the buffer mode to BM_STANDARD. It will be modified
19437 +                * when building descriptors for a specific buffer mode */
19438 +               ep->dwc_ep.buff_mode = BM_STANDARD;
19439 +
19440 +               /* Create and initialize the default values for this EP's Buffer modes */
19441 +               if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
19442 +                       return retval;
19443 +
19444 +               /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
19445 +               DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
19446 +               retval = 0;
19447 +       } else {                /* The sought EP already is in the list */
19448 +               CFI_INFO("%s: The sought EP already is in the list\n",
19449 +                        __func__);
19450 +       }
19451 +
19452 +       return retval;
19453 +}
19454 +
19455 +/**
19456 + * This function is called when the data stage of a 3-stage Control Write request
19457 + * is complete.
19458 + *
19459 + */
19460 +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
19461 +                                  struct dwc_otg_pcd *pcd)
19462 +{
19463 +       uint32_t addr, reg_value;
19464 +       uint16_t wIndex, wValue;
19465 +       uint8_t bRequest;
19466 +       uint8_t *buf = cfi->buf_out.buf;
19467 +       //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
19468 +       struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
19469 +       int retval = -DWC_E_NOT_SUPPORTED;
19470 +
19471 +       CFI_INFO("%s\n", __func__);
19472 +
19473 +       bRequest = ctrl_req->bRequest;
19474 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
19475 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
19476 +
19477 +       /*
19478 +        * Save the pointer to the data stage in the ctrl_req's <data> field.
19479 +        * The request should be already saved in the command stage by now.
19480 +        */
19481 +       ctrl_req->data = cfi->buf_out.buf;
19482 +       cfi->need_status_in_complete = 0;
19483 +       cfi->need_gadget_att = 0;
19484 +
19485 +       switch (bRequest) {
19486 +       case VEN_CORE_WRITE_REGISTER:
19487 +               /* The buffer contains raw data of the new value for the register */
19488 +               reg_value = *((uint32_t *) buf);
19489 +               if (wValue == 0) {
19490 +                       addr = 0;
19491 +                       //addr = (uint32_t) pcd->otg_dev->os_dep.base;
19492 +                       addr += wIndex;
19493 +               } else {
19494 +                       addr = (wValue << 16) | wIndex;
19495 +               }
19496 +
19497 +               //writel(reg_value, addr);
19498 +
19499 +               retval = 0;
19500 +               cfi->need_status_in_complete = 1;
19501 +               break;
19502 +
19503 +       case VEN_CORE_SET_FEATURE:
19504 +               /* The buffer contains raw data of the new value of the feature */
19505 +               retval = cfi_set_feature_value(pcd);
19506 +               if (retval < 0)
19507 +                       return retval;
19508 +
19509 +               cfi->need_status_in_complete = 1;
19510 +               break;
19511 +
19512 +       default:
19513 +               break;
19514 +       }
19515 +
19516 +       return retval;
19517 +}
19518 +
19519 +/**
19520 + * This function builds the DMA descriptors for the SG buffer mode.
19521 + */
19522 +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19523 +                              dwc_otg_pcd_request_t * req)
19524 +{
19525 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19526 +       ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
19527 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19528 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19529 +       dma_addr_t buff_addr = req->dma;
19530 +       int i;
19531 +       uint32_t txsize, off;
19532 +
19533 +       txsize = sgval->wSize;
19534 +       off = sgval->bOffset;
19535 +
19536 +//      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n",
19537 +//              __func__, cfiep->ep->ep.name, txsize, off);
19538 +
19539 +       for (i = 0; i < sgval->bCount; i++) {
19540 +               desc->status.b.bs = BS_HOST_BUSY;
19541 +               desc->buf = buff_addr;
19542 +               desc->status.b.l = 0;
19543 +               desc->status.b.ioc = 0;
19544 +               desc->status.b.sp = 0;
19545 +               desc->status.b.bytes = txsize;
19546 +               desc->status.b.bs = BS_HOST_READY;
19547 +
19548 +               /* Set the next address of the buffer */
19549 +               buff_addr += txsize + off;
19550 +               desc_last = desc;
19551 +               desc++;
19552 +       }
19553 +
19554 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19555 +       desc_last->status.b.l = 1;
19556 +       desc_last->status.b.ioc = 1;
19557 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19558 +       /* Save the last DMA descriptor pointer */
19559 +       cfiep->dma_desc_last = desc_last;
19560 +       cfiep->desc_count = sgval->bCount;
19561 +}
19562 +
19563 +/**
19564 + * This function builds the DMA descriptors for the Concatenation buffer mode.
19565 + */
19566 +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19567 +                                  dwc_otg_pcd_request_t * req)
19568 +{
19569 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19570 +       ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
19571 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19572 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19573 +       dma_addr_t buff_addr = req->dma;
19574 +       int i;
19575 +       uint16_t *txsize;
19576 +
19577 +       txsize = concatval->wTxBytes;
19578 +
19579 +       for (i = 0; i < concatval->hdr.bDescCount; i++) {
19580 +               desc->buf = buff_addr;
19581 +               desc->status.b.bs = BS_HOST_BUSY;
19582 +               desc->status.b.l = 0;
19583 +               desc->status.b.ioc = 0;
19584 +               desc->status.b.sp = 0;
19585 +               desc->status.b.bytes = *txsize;
19586 +               desc->status.b.bs = BS_HOST_READY;
19587 +
19588 +               txsize++;
19589 +               /* Set the next address of the buffer */
19590 +               buff_addr += UGETW(ep->desc->wMaxPacketSize);
19591 +               desc_last = desc;
19592 +               desc++;
19593 +       }
19594 +
19595 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19596 +       desc_last->status.b.l = 1;
19597 +       desc_last->status.b.ioc = 1;
19598 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19599 +       cfiep->dma_desc_last = desc_last;
19600 +       cfiep->desc_count = concatval->hdr.bDescCount;
19601 +}
19602 +
19603 +/**
19604 + * This function builds the DMA descriptors for the Circular buffer mode
19605 + */
19606 +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19607 +                                dwc_otg_pcd_request_t * req)
19608 +{
19609 +       /* @todo: MAS - add implementation when this feature needs to be tested */
19610 +}
19611 +
19612 +/**
19613 + * This function builds the DMA descriptors for the Alignment buffer mode
19614 + */
19615 +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19616 +                                 dwc_otg_pcd_request_t * req)
19617 +{
19618 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19619 +       ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
19620 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19621 +       dma_addr_t buff_addr = req->dma;
19622 +
19623 +       desc->status.b.bs = BS_HOST_BUSY;
19624 +       desc->status.b.l = 1;
19625 +       desc->status.b.ioc = 1;
19626 +       desc->status.b.sp = ep->dwc_ep.sent_zlp;
19627 +       desc->status.b.bytes = req->length;
19628 +       /* Adjust the buffer alignment */
19629 +       desc->buf = (buff_addr + alignval->bAlign);
19630 +       desc->status.b.bs = BS_HOST_READY;
19631 +       cfiep->dma_desc_last = desc;
19632 +       cfiep->desc_count = 1;
19633 +}
19634 +
19635 +/**
19636 + * This function builds the DMA descriptors chain for different modes of the
19637 + * buffer setup of an endpoint.
19638 + */
19639 +static void cfi_build_descriptors(struct cfiobject *cfi,
19640 +                                 struct dwc_otg_pcd *pcd,
19641 +                                 struct dwc_otg_pcd_ep *ep,
19642 +                                 dwc_otg_pcd_request_t * req)
19643 +{
19644 +       cfi_ep_t *cfiep;
19645 +
19646 +       /* Get the cfiep by the dwc_otg_pcd_ep */
19647 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19648 +       if (NULL == cfiep) {
19649 +               CFI_INFO("%s: Unable to find a matching active endpoint\n",
19650 +                        __func__);
19651 +               return;
19652 +       }
19653 +
19654 +       cfiep->xfer_len = req->length;
19655 +
19656 +       /* Iterate through all the DMA descriptors */
19657 +       switch (cfiep->ep->dwc_ep.buff_mode) {
19658 +       case BM_SG:
19659 +               cfi_build_sg_descs(cfi, cfiep, req);
19660 +               break;
19661 +
19662 +       case BM_CONCAT:
19663 +               cfi_build_concat_descs(cfi, cfiep, req);
19664 +               break;
19665 +
19666 +       case BM_CIRCULAR:
19667 +               cfi_build_circ_descs(cfi, cfiep, req);
19668 +               break;
19669 +
19670 +       case BM_ALIGN:
19671 +               cfi_build_align_descs(cfi, cfiep, req);
19672 +               break;
19673 +
19674 +       default:
19675 +               break;
19676 +       }
19677 +}
19678 +
19679 +/**
19680 + * Allocate DMA buffer for different Buffer modes.
19681 + */
19682 +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19683 +                             struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
19684 +                             unsigned size, gfp_t flags)
19685 +{
19686 +       return DWC_DMA_ALLOC(size, dma);
19687 +}
19688 +
19689 +/**
19690 + * This function initializes the CFI object.
19691 + */
19692 +int init_cfi(cfiobject_t * cfiobj)
19693 +{
19694 +       CFI_INFO("%s\n", __func__);
19695 +
19696 +       /* Allocate a buffer for IN XFERs */
19697 +       cfiobj->buf_in.buf =
19698 +           DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
19699 +       if (NULL == cfiobj->buf_in.buf) {
19700 +               CFI_INFO("Unable to allocate buffer for INs\n");
19701 +               return -DWC_E_NO_MEMORY;
19702 +       }
19703 +
19704 +       /* Allocate a buffer for OUT XFERs */
19705 +       cfiobj->buf_out.buf =
19706 +           DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
19707 +       if (NULL == cfiobj->buf_out.buf) {
19708 +               CFI_INFO("Unable to allocate buffer for OUT\n");
19709 +               return -DWC_E_NO_MEMORY;
19710 +       }
19711 +
19712 +       /* Initialize the callback function pointers */
19713 +       cfiobj->ops.release = cfi_release;
19714 +       cfiobj->ops.ep_enable = cfi_ep_enable;
19715 +       cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
19716 +       cfiobj->ops.build_descriptors = cfi_build_descriptors;
19717 +       cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
19718 +
19719 +       /* Initialize the list of active endpoints in the CFI object */
19720 +       DWC_LIST_INIT(&cfiobj->active_eps);
19721 +
19722 +       return 0;
19723 +}
19724 +
19725 +/**
19726 + * This function reads the required feature's current value into the buffer
19727 + *
19728 + * @retval: Returns negative as error, or the data length of the feature
19729 + */
19730 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
19731 +                                struct dwc_otg_pcd *pcd,
19732 +                                struct cfi_usb_ctrlrequest *ctrl_req)
19733 +{
19734 +       int retval = -DWC_E_NOT_SUPPORTED;
19735 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19736 +       uint16_t dfifo, rxfifo, txfifo;
19737 +
19738 +       switch (ctrl_req->wIndex) {
19739 +               /* Whether the DDMA is enabled or not */
19740 +       case FT_ID_DMA_MODE:
19741 +               *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
19742 +               retval = 1;
19743 +               break;
19744 +
19745 +       case FT_ID_DMA_BUFFER_SETUP:
19746 +               retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
19747 +               break;
19748 +
19749 +       case FT_ID_DMA_BUFF_ALIGN:
19750 +               retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
19751 +               break;
19752 +
19753 +       case FT_ID_DMA_CONCAT_SETUP:
19754 +               retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
19755 +               break;
19756 +
19757 +       case FT_ID_DMA_CIRCULAR:
19758 +               CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
19759 +               break;
19760 +
19761 +       case FT_ID_THRESHOLD_SETUP:
19762 +               CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
19763 +               break;
19764 +
19765 +       case FT_ID_DFIFO_DEPTH:
19766 +               dfifo = get_dfifo_size(coreif);
19767 +               *((uint16_t *) buf) = dfifo;
19768 +               retval = sizeof(uint16_t);
19769 +               break;
19770 +
19771 +       case FT_ID_TX_FIFO_DEPTH:
19772 +               retval = get_txfifo_size(pcd, ctrl_req->wValue);
19773 +               if (retval >= 0) {
19774 +                       txfifo = retval;
19775 +                       *((uint16_t *) buf) = txfifo;
19776 +                       retval = sizeof(uint16_t);
19777 +               }
19778 +               break;
19779 +
19780 +       case FT_ID_RX_FIFO_DEPTH:
19781 +               retval = get_rxfifo_size(coreif, ctrl_req->wValue);
19782 +               if (retval >= 0) {
19783 +                       rxfifo = retval;
19784 +                       *((uint16_t *) buf) = rxfifo;
19785 +                       retval = sizeof(uint16_t);
19786 +               }
19787 +               break;
19788 +       }
19789 +
19790 +       return retval;
19791 +}
19792 +
19793 +/**
19794 + * This function resets the SG for the specified EP to its default value
19795 + */
19796 +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
19797 +{
19798 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19799 +       return 0;
19800 +}
19801 +
19802 +/**
19803 + * This function resets the Alignment for the specified EP to its default value
19804 + */
19805 +static int cfi_reset_align_val(cfi_ep_t * cfiep)
19806 +{
19807 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19808 +       return 0;
19809 +}
19810 +
19811 +/**
19812 + * This function resets the Concatenation for the specified EP to its default value
19813 + * This function will also set the value of the wTxBytes field to NULL after
19814 + * freeing the memory previously allocated for this field.
19815 + */
19816 +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
19817 +{
19818 +       /* First we need to free the wTxBytes field */
19819 +       if (cfiep->bm_concat->wTxBytes) {
19820 +               DWC_FREE(cfiep->bm_concat->wTxBytes);
19821 +               cfiep->bm_concat->wTxBytes = NULL;
19822 +       }
19823 +
19824 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19825 +       return 0;
19826 +}
19827 +
19828 +/**
19829 + * This function resets all the buffer setups of the specified endpoint
19830 + */
19831 +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
19832 +{
19833 +       cfi_reset_sg_val(cfiep);
19834 +       cfi_reset_align_val(cfiep);
19835 +       cfi_reset_concat_val(cfiep);
19836 +       return 0;
19837 +}
19838 +
19839 +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
19840 +                                    uint8_t rx_rst, uint8_t tx_rst)
19841 +{
19842 +       int retval = -DWC_E_INVALID;
19843 +       uint16_t tx_siz[15];
19844 +       uint16_t rx_siz = 0;
19845 +       dwc_otg_pcd_ep_t *ep = NULL;
19846 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
19847 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
19848 +
19849 +       if (rx_rst) {
19850 +               rx_siz = params->dev_rx_fifo_size;
19851 +               params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
19852 +       }
19853 +
19854 +       if (tx_rst) {
19855 +               if (ep_addr == 0) {
19856 +                       int i;
19857 +
19858 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
19859 +                               tx_siz[i] =
19860 +                                   core_if->core_params->dev_tx_fifo_size[i];
19861 +                               core_if->core_params->dev_tx_fifo_size[i] =
19862 +                                   core_if->init_txfsiz[i];
19863 +                       }
19864 +               } else {
19865 +
19866 +                       ep = get_ep_by_addr(pcd, ep_addr);
19867 +
19868 +                       if (NULL == ep) {
19869 +                               CFI_INFO
19870 +                                   ("%s: Unable to get the endpoint addr=0x%02x\n",
19871 +                                    __func__, ep_addr);
19872 +                               return -DWC_E_INVALID;
19873 +                       }
19874 +
19875 +                       tx_siz[0] =
19876 +                           params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
19877 +                                                    1];
19878 +                       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
19879 +                           GET_CORE_IF(pcd)->init_txfsiz[ep->
19880 +                                                         dwc_ep.tx_fifo_num -
19881 +                                                         1];
19882 +               }
19883 +       }
19884 +
19885 +       if (resize_fifos(GET_CORE_IF(pcd))) {
19886 +               retval = 0;
19887 +       } else {
19888 +               CFI_INFO
19889 +                   ("%s: Error resetting the feature Reset All(FIFO size)\n",
19890 +                    __func__);
19891 +               if (rx_rst) {
19892 +                       params->dev_rx_fifo_size = rx_siz;
19893 +               }
19894 +
19895 +               if (tx_rst) {
19896 +                       if (ep_addr == 0) {
19897 +                               int i;
19898 +                               for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
19899 +                                    i++) {
19900 +                                       core_if->
19901 +                                           core_params->dev_tx_fifo_size[i] =
19902 +                                           tx_siz[i];
19903 +                               }
19904 +                       } else {
19905 +                               params->dev_tx_fifo_size[ep->
19906 +                                                        dwc_ep.tx_fifo_num -
19907 +                                                        1] = tx_siz[0];
19908 +                       }
19909 +               }
19910 +               retval = -DWC_E_INVALID;
19911 +       }
19912 +       return retval;
19913 +}
19914 +
19915 +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
19916 +{
19917 +       int retval = 0;
19918 +       cfi_ep_t *cfiep;
19919 +       cfiobject_t *cfi = pcd->cfi;
19920 +       dwc_list_link_t *tmp;
19921 +
19922 +       retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
19923 +       if (retval < 0) {
19924 +               return retval;
19925 +       }
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_ep_reset_all_setup_vals(cfiep);
19936 +               cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19937 +       }
19938 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19939 +       else {
19940 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19941 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19942 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19943 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19944 +                       retval = cfi_ep_reset_all_setup_vals(cfiep);
19945 +                       cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19946 +                       if (retval < 0) {
19947 +                               CFI_INFO
19948 +                                   ("%s: Error resetting the feature Reset All\n",
19949 +                                    __func__);
19950 +                               return retval;
19951 +                       }
19952 +               }
19953 +       }
19954 +       return retval;
19955 +}
19956 +
19957 +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
19958 +                                          uint8_t addr)
19959 +{
19960 +       int retval = 0;
19961 +       cfi_ep_t *cfiep;
19962 +       cfiobject_t *cfi = pcd->cfi;
19963 +       dwc_list_link_t *tmp;
19964 +
19965 +       /* If the EP address is known then reset the features for only that EP */
19966 +       if (addr) {
19967 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19968 +               if (NULL == cfiep) {
19969 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19970 +                                __func__, addr);
19971 +                       return -DWC_E_INVALID;
19972 +               }
19973 +               retval = cfi_reset_sg_val(cfiep);
19974 +       }
19975 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19976 +       else {
19977 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19978 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19979 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19980 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19981 +                       retval = cfi_reset_sg_val(cfiep);
19982 +                       if (retval < 0) {
19983 +                               CFI_INFO
19984 +                                   ("%s: Error resetting the feature Buffer Setup\n",
19985 +                                    __func__);
19986 +                               return retval;
19987 +                       }
19988 +               }
19989 +       }
19990 +       return retval;
19991 +}
19992 +
19993 +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19994 +{
19995 +       int retval = 0;
19996 +       cfi_ep_t *cfiep;
19997 +       cfiobject_t *cfi = pcd->cfi;
19998 +       dwc_list_link_t *tmp;
19999 +
20000 +       /* If the EP address is known then reset the features for only that EP */
20001 +       if (addr) {
20002 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
20003 +               if (NULL == cfiep) {
20004 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
20005 +                                __func__, addr);
20006 +                       return -DWC_E_INVALID;
20007 +               }
20008 +               retval = cfi_reset_concat_val(cfiep);
20009 +       }
20010 +       /* Otherwise (wValue == 0), reset all features of all EP's */
20011 +       else {
20012 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
20013 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
20014 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20015 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20016 +                       retval = cfi_reset_concat_val(cfiep);
20017 +                       if (retval < 0) {
20018 +                               CFI_INFO
20019 +                                   ("%s: Error resetting the feature Concatenation Value\n",
20020 +                                    __func__);
20021 +                               return retval;
20022 +                       }
20023 +               }
20024 +       }
20025 +       return retval;
20026 +}
20027 +
20028 +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
20029 +{
20030 +       int retval = 0;
20031 +       cfi_ep_t *cfiep;
20032 +       cfiobject_t *cfi = pcd->cfi;
20033 +       dwc_list_link_t *tmp;
20034 +
20035 +       /* If the EP address is known then reset the features for only that EP */
20036 +       if (addr) {
20037 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
20038 +               if (NULL == cfiep) {
20039 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
20040 +                                __func__, addr);
20041 +                       return -DWC_E_INVALID;
20042 +               }
20043 +               retval = cfi_reset_align_val(cfiep);
20044 +       }
20045 +       /* Otherwise (wValue == 0), reset all features of all EP's */
20046 +       else {
20047 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
20048 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
20049 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20050 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20051 +                       retval = cfi_reset_align_val(cfiep);
20052 +                       if (retval < 0) {
20053 +                               CFI_INFO
20054 +                                   ("%s: Error resetting the feature Aliignment Value\n",
20055 +                                    __func__);
20056 +                               return retval;
20057 +                       }
20058 +               }
20059 +       }
20060 +       return retval;
20061 +
20062 +}
20063 +
20064 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
20065 +                            struct cfi_usb_ctrlrequest *req)
20066 +{
20067 +       int retval = 0;
20068 +
20069 +       switch (req->wIndex) {
20070 +       case 0:
20071 +               /* Reset all features */
20072 +               retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
20073 +               break;
20074 +
20075 +       case FT_ID_DMA_BUFFER_SETUP:
20076 +               /* Reset the SG buffer setup */
20077 +               retval =
20078 +                   cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
20079 +               break;
20080 +
20081 +       case FT_ID_DMA_CONCAT_SETUP:
20082 +               /* Reset the Concatenation buffer setup */
20083 +               retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
20084 +               break;
20085 +
20086 +       case FT_ID_DMA_BUFF_ALIGN:
20087 +               /* Reset the Alignment buffer setup */
20088 +               retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
20089 +               break;
20090 +
20091 +       case FT_ID_TX_FIFO_DEPTH:
20092 +               retval =
20093 +                   cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
20094 +               pcd->cfi->need_gadget_att = 0;
20095 +               break;
20096 +
20097 +       case FT_ID_RX_FIFO_DEPTH:
20098 +               retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
20099 +               pcd->cfi->need_gadget_att = 0;
20100 +               break;
20101 +       default:
20102 +               break;
20103 +       }
20104 +       return retval;
20105 +}
20106 +
20107 +/**
20108 + * This function sets a new value for the SG buffer setup.
20109 + */
20110 +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20111 +{
20112 +       uint8_t inaddr, outaddr;
20113 +       cfi_ep_t *epin, *epout;
20114 +       ddma_sg_buffer_setup_t *psgval;
20115 +       uint32_t desccount, size;
20116 +
20117 +       CFI_INFO("%s\n", __func__);
20118 +
20119 +       psgval = (ddma_sg_buffer_setup_t *) buf;
20120 +       desccount = (uint32_t) psgval->bCount;
20121 +       size = (uint32_t) psgval->wSize;
20122 +
20123 +       /* Check the DMA descriptor count */
20124 +       if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
20125 +               CFI_INFO
20126 +                   ("%s: The count of DMA Descriptors should be between 1 and %d\n",
20127 +                    __func__, MAX_DMA_DESCS_PER_EP);
20128 +               return -DWC_E_INVALID;
20129 +       }
20130 +
20131 +       /* Check the DMA descriptor count */
20132 +
20133 +       if (size == 0) {
20134 +
20135 +               CFI_INFO("%s: The transfer size should be at least 1 byte\n",
20136 +                        __func__);
20137 +
20138 +               return -DWC_E_INVALID;
20139 +
20140 +       }
20141 +
20142 +       inaddr = psgval->bInEndpointAddress;
20143 +       outaddr = psgval->bOutEndpointAddress;
20144 +
20145 +       epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
20146 +       epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
20147 +
20148 +       if (NULL == epin || NULL == epout) {
20149 +               CFI_INFO
20150 +                   ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
20151 +                    __func__, inaddr, outaddr);
20152 +               return -DWC_E_INVALID;
20153 +       }
20154 +
20155 +       epin->ep->dwc_ep.buff_mode = BM_SG;
20156 +       dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20157 +
20158 +       epout->ep->dwc_ep.buff_mode = BM_SG;
20159 +       dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20160 +
20161 +       return 0;
20162 +}
20163 +
20164 +/**
20165 + * This function sets a new value for the buffer Alignment setup.
20166 + */
20167 +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20168 +{
20169 +       cfi_ep_t *ep;
20170 +       uint8_t addr;
20171 +       ddma_align_buffer_setup_t *palignval;
20172 +
20173 +       palignval = (ddma_align_buffer_setup_t *) buf;
20174 +       addr = palignval->bEndpointAddress;
20175 +
20176 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20177 +
20178 +       if (NULL == ep) {
20179 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20180 +                        __func__, addr);
20181 +               return -DWC_E_INVALID;
20182 +       }
20183 +
20184 +       ep->ep->dwc_ep.buff_mode = BM_ALIGN;
20185 +       dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
20186 +
20187 +       return 0;
20188 +}
20189 +
20190 +/**
20191 + * This function sets a new value for the Concatenation buffer setup.
20192 + */
20193 +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20194 +{
20195 +       uint8_t addr;
20196 +       cfi_ep_t *ep;
20197 +       struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
20198 +       uint16_t *pVals;
20199 +       uint32_t desccount;
20200 +       int i;
20201 +       uint16_t mps;
20202 +
20203 +       pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
20204 +       desccount = (uint32_t) pConcatValHdr->bDescCount;
20205 +       pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
20206 +
20207 +       /* Check the DMA descriptor count */
20208 +       if (desccount > MAX_DMA_DESCS_PER_EP) {
20209 +               CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
20210 +                        __func__, MAX_DMA_DESCS_PER_EP);
20211 +               return -DWC_E_INVALID;
20212 +       }
20213 +
20214 +       addr = pConcatValHdr->bEndpointAddress;
20215 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20216 +       if (NULL == ep) {
20217 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20218 +                        __func__, addr);
20219 +               return -DWC_E_INVALID;
20220 +       }
20221 +
20222 +       mps = UGETW(ep->ep->desc->wMaxPacketSize);
20223 +
20224 +#if 0
20225 +       for (i = 0; i < desccount; i++) {
20226 +               CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
20227 +       }
20228 +       CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
20229 +#endif
20230 +
20231 +       /* Check the wTxSizes to be less than or equal to the mps */
20232 +       for (i = 0; i < desccount; i++) {
20233 +               if (pVals[i] > mps) {
20234 +                       CFI_INFO
20235 +                           ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
20236 +                            __func__, i, pVals[i]);
20237 +                       return -DWC_E_INVALID;
20238 +               }
20239 +       }
20240 +
20241 +       ep->ep->dwc_ep.buff_mode = BM_CONCAT;
20242 +       dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
20243 +
20244 +       /* Free the previously allocated storage for the wTxBytes */
20245 +       if (ep->bm_concat->wTxBytes) {
20246 +               DWC_FREE(ep->bm_concat->wTxBytes);
20247 +       }
20248 +
20249 +       /* Allocate a new storage for the wTxBytes field */
20250 +       ep->bm_concat->wTxBytes =
20251 +           DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
20252 +       if (NULL == ep->bm_concat->wTxBytes) {
20253 +               CFI_INFO("%s: Unable to allocate memory\n", __func__);
20254 +               return -DWC_E_NO_MEMORY;
20255 +       }
20256 +
20257 +       /* Copy the new values into the wTxBytes filed */
20258 +       dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
20259 +                  sizeof(uint16_t) * pConcatValHdr->bDescCount);
20260 +
20261 +       return 0;
20262 +}
20263 +
20264 +/**
20265 + * This function calculates the total of all FIFO sizes
20266 + *
20267 + * @param core_if Programming view of DWC_otg controller
20268 + *
20269 + * @return The total of data FIFO sizes.
20270 + *
20271 + */
20272 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
20273 +{
20274 +       dwc_otg_core_params_t *params = core_if->core_params;
20275 +       uint16_t dfifo_total = 0;
20276 +       int i;
20277 +
20278 +       /* The shared RxFIFO size */
20279 +       dfifo_total =
20280 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20281 +
20282 +       /* Add up each TxFIFO size to the total */
20283 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20284 +               dfifo_total += params->dev_tx_fifo_size[i];
20285 +       }
20286 +
20287 +       return dfifo_total;
20288 +}
20289 +
20290 +/**
20291 + * This function returns Rx FIFO size
20292 + *
20293 + * @param core_if Programming view of DWC_otg controller
20294 + *
20295 + * @return The total of data FIFO sizes.
20296 + *
20297 + */
20298 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
20299 +{
20300 +       switch (wValue >> 8) {
20301 +       case 0:
20302 +               return (core_if->pwron_rxfsiz <
20303 +                       32768) ? core_if->pwron_rxfsiz : 32768;
20304 +               break;
20305 +       case 1:
20306 +               return core_if->core_params->dev_rx_fifo_size;
20307 +               break;
20308 +       default:
20309 +               return -DWC_E_INVALID;
20310 +               break;
20311 +       }
20312 +}
20313 +
20314 +/**
20315 + * This function returns Tx FIFO size for IN EP
20316 + *
20317 + * @param core_if Programming view of DWC_otg controller
20318 + *
20319 + * @return The total of data FIFO sizes.
20320 + *
20321 + */
20322 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
20323 +{
20324 +       dwc_otg_pcd_ep_t *ep;
20325 +
20326 +       ep = get_ep_by_addr(pcd, wValue & 0xff);
20327 +
20328 +       if (NULL == ep) {
20329 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20330 +                        __func__, wValue & 0xff);
20331 +               return -DWC_E_INVALID;
20332 +       }
20333 +
20334 +       if (!ep->dwc_ep.is_in) {
20335 +               CFI_INFO
20336 +                   ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
20337 +                    __func__, wValue & 0xff);
20338 +               return -DWC_E_INVALID;
20339 +       }
20340 +
20341 +       switch (wValue >> 8) {
20342 +       case 0:
20343 +               return (GET_CORE_IF(pcd)->pwron_txfsiz
20344 +                       [ep->dwc_ep.tx_fifo_num - 1] <
20345 +                       768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
20346 +                                                             dwc_ep.tx_fifo_num
20347 +                                                             - 1] : 32768;
20348 +               break;
20349 +       case 1:
20350 +               return GET_CORE_IF(pcd)->core_params->
20351 +                   dev_tx_fifo_size[ep->dwc_ep.num - 1];
20352 +               break;
20353 +       default:
20354 +               return -DWC_E_INVALID;
20355 +               break;
20356 +       }
20357 +}
20358 +
20359 +/**
20360 + * This function checks if the submitted combination of
20361 + * device mode FIFO sizes is possible or not.
20362 + *
20363 + * @param core_if Programming view of DWC_otg controller
20364 + *
20365 + * @return 1 if possible, 0 otherwise.
20366 + *
20367 + */
20368 +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
20369 +{
20370 +       uint16_t dfifo_actual = 0;
20371 +       dwc_otg_core_params_t *params = core_if->core_params;
20372 +       uint16_t start_addr = 0;
20373 +       int i;
20374 +
20375 +       dfifo_actual =
20376 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20377 +
20378 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20379 +               dfifo_actual += params->dev_tx_fifo_size[i];
20380 +       }
20381 +
20382 +       if (dfifo_actual > core_if->total_fifo_size) {
20383 +               return 0;
20384 +       }
20385 +
20386 +       if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
20387 +               return 0;
20388 +
20389 +       if (params->dev_nperio_tx_fifo_size > 32768
20390 +           || params->dev_nperio_tx_fifo_size < 16)
20391 +               return 0;
20392 +
20393 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20394 +
20395 +               if (params->dev_tx_fifo_size[i] > 768
20396 +                   || params->dev_tx_fifo_size[i] < 4)
20397 +                       return 0;
20398 +       }
20399 +
20400 +       if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
20401 +               return 0;
20402 +       start_addr = params->dev_rx_fifo_size;
20403 +
20404 +       if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
20405 +               return 0;
20406 +       start_addr += params->dev_nperio_tx_fifo_size;
20407 +
20408 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20409 +
20410 +               if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
20411 +                       return 0;
20412 +               start_addr += params->dev_tx_fifo_size[i];
20413 +       }
20414 +
20415 +       return 1;
20416 +}
20417 +
20418 +/**
20419 + * This function resizes Device mode FIFOs
20420 + *
20421 + * @param core_if Programming view of DWC_otg controller
20422 + *
20423 + * @return 1 if successful, 0 otherwise
20424 + *
20425 + */
20426 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
20427 +{
20428 +       int i = 0;
20429 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
20430 +       dwc_otg_core_params_t *params = core_if->core_params;
20431 +       uint32_t rx_fifo_size;
20432 +       fifosize_data_t nptxfifosize;
20433 +       fifosize_data_t txfifosize[15];
20434 +
20435 +       uint32_t rx_fsz_bak;
20436 +       uint32_t nptxfsz_bak;
20437 +       uint32_t txfsz_bak[15];
20438 +
20439 +       uint16_t start_address;
20440 +       uint8_t retval = 1;
20441 +
20442 +       if (!check_fifo_sizes(core_if)) {
20443 +               return 0;
20444 +       }
20445 +
20446 +       /* Configure data FIFO sizes */
20447 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
20448 +               rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
20449 +               rx_fifo_size = params->dev_rx_fifo_size;
20450 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
20451 +
20452 +               /*
20453 +                * Tx FIFOs These FIFOs are numbered from 1 to 15.
20454 +                * Indexes of the FIFO size module parameters in the
20455 +                * dev_tx_fifo_size array and the FIFO size registers in
20456 +                * the dtxfsiz array run from 0 to 14.
20457 +                */
20458 +
20459 +               /* Non-periodic Tx FIFO */
20460 +               nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
20461 +               nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
20462 +               start_address = params->dev_rx_fifo_size;
20463 +               nptxfifosize.b.startaddr = start_address;
20464 +
20465 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
20466 +
20467 +               start_address += nptxfifosize.b.depth;
20468 +
20469 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20470 +                       txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
20471 +
20472 +                       txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
20473 +                       txfifosize[i].b.startaddr = start_address;
20474 +                       DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20475 +                                       txfifosize[i].d32);
20476 +
20477 +                       start_address += txfifosize[i].b.depth;
20478 +               }
20479 +
20480 +               /** Check if register values are set correctly */
20481 +               if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
20482 +                       retval = 0;
20483 +               }
20484 +
20485 +               if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
20486 +                       retval = 0;
20487 +               }
20488 +
20489 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20490 +                       if (txfifosize[i].d32 !=
20491 +                           DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
20492 +                               retval = 0;
20493 +                       }
20494 +               }
20495 +
20496 +               /** If register values are not set correctly, reset old values */
20497 +               if (retval == 0) {
20498 +                       DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
20499 +
20500 +                       /* Non-periodic Tx FIFO */
20501 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
20502 +
20503 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20504 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20505 +                                               txfsz_bak[i]);
20506 +                       }
20507 +               }
20508 +       } else {
20509 +               return 0;
20510 +       }
20511 +
20512 +       /* Flush the FIFOs */
20513 +       dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
20514 +       dwc_otg_flush_rx_fifo(core_if);
20515 +
20516 +       return retval;
20517 +}
20518 +
20519 +/**
20520 + * This function sets a new value for the buffer Alignment setup.
20521 + */
20522 +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20523 +{
20524 +       int retval;
20525 +       uint32_t fsiz;
20526 +       uint16_t size;
20527 +       uint16_t ep_addr;
20528 +       dwc_otg_pcd_ep_t *ep;
20529 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20530 +       tx_fifo_size_setup_t *ptxfifoval;
20531 +
20532 +       ptxfifoval = (tx_fifo_size_setup_t *) buf;
20533 +       ep_addr = ptxfifoval->bEndpointAddress;
20534 +       size = ptxfifoval->wDepth;
20535 +
20536 +       ep = get_ep_by_addr(pcd, ep_addr);
20537 +
20538 +       CFI_INFO
20539 +           ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
20540 +            __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
20541 +
20542 +       if (NULL == ep) {
20543 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20544 +                        __func__, ep_addr);
20545 +               return -DWC_E_INVALID;
20546 +       }
20547 +
20548 +       fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
20549 +       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
20550 +
20551 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20552 +               retval = 0;
20553 +       } else {
20554 +               CFI_INFO
20555 +                   ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
20556 +                    __func__, ep_addr);
20557 +               params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
20558 +               retval = -DWC_E_INVALID;
20559 +       }
20560 +
20561 +       return retval;
20562 +}
20563 +
20564 +/**
20565 + * This function sets a new value for the buffer Alignment setup.
20566 + */
20567 +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20568 +{
20569 +       int retval;
20570 +       uint32_t fsiz;
20571 +       uint16_t size;
20572 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20573 +       rx_fifo_size_setup_t *prxfifoval;
20574 +
20575 +       prxfifoval = (rx_fifo_size_setup_t *) buf;
20576 +       size = prxfifoval->wDepth;
20577 +
20578 +       fsiz = params->dev_rx_fifo_size;
20579 +       params->dev_rx_fifo_size = size;
20580 +
20581 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20582 +               retval = 0;
20583 +       } else {
20584 +               CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
20585 +                        __func__);
20586 +               params->dev_rx_fifo_size = fsiz;
20587 +               retval = -DWC_E_INVALID;
20588 +       }
20589 +
20590 +       return retval;
20591 +}
20592 +
20593 +/**
20594 + * This function reads the SG of an EP's buffer setup into the buffer buf
20595 + */
20596 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20597 +                            struct cfi_usb_ctrlrequest *req)
20598 +{
20599 +       int retval = -DWC_E_INVALID;
20600 +       uint8_t addr;
20601 +       cfi_ep_t *ep;
20602 +
20603 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20604 +       addr = req->wValue & 0xFF;
20605 +       if (addr == 0)          /* The address should be non-zero */
20606 +               return retval;
20607 +
20608 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20609 +       if (NULL == ep) {
20610 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20611 +                        __func__, addr);
20612 +               return retval;
20613 +       }
20614 +
20615 +       dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
20616 +       retval = BS_SG_VAL_DESC_LEN;
20617 +       return retval;
20618 +}
20619 +
20620 +/**
20621 + * This function reads the Concatenation value of an EP's buffer mode into
20622 + * the buffer buf
20623 + */
20624 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20625 +                                struct cfi_usb_ctrlrequest *req)
20626 +{
20627 +       int retval = -DWC_E_INVALID;
20628 +       uint8_t addr;
20629 +       cfi_ep_t *ep;
20630 +       uint8_t desc_count;
20631 +
20632 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20633 +       addr = req->wValue & 0xFF;
20634 +       if (addr == 0)          /* The address should be non-zero */
20635 +               return retval;
20636 +
20637 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20638 +       if (NULL == ep) {
20639 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20640 +                        __func__, addr);
20641 +               return retval;
20642 +       }
20643 +
20644 +       /* Copy the header to the buffer */
20645 +       dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
20646 +       /* Advance the buffer pointer by the header size */
20647 +       buf += BS_CONCAT_VAL_HDR_LEN;
20648 +
20649 +       desc_count = ep->bm_concat->hdr.bDescCount;
20650 +       /* Copy alll the wTxBytes to the buffer */
20651 +       dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
20652 +
20653 +       retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
20654 +       return retval;
20655 +}
20656 +
20657 +/**
20658 + * This function reads the buffer Alignment value of an EP's buffer mode into
20659 + * the buffer buf
20660 + *
20661 + * @return The total number of bytes copied to the buffer or negative error code.
20662 + */
20663 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20664 +                               struct cfi_usb_ctrlrequest *req)
20665 +{
20666 +       int retval = -DWC_E_INVALID;
20667 +       uint8_t addr;
20668 +       cfi_ep_t *ep;
20669 +
20670 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20671 +       addr = req->wValue & 0xFF;
20672 +       if (addr == 0)          /* The address should be non-zero */
20673 +               return retval;
20674 +
20675 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20676 +       if (NULL == ep) {
20677 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20678 +                        __func__, addr);
20679 +               return retval;
20680 +       }
20681 +
20682 +       dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
20683 +       retval = BS_ALIGN_VAL_HDR_LEN;
20684 +
20685 +       return retval;
20686 +}
20687 +
20688 +/**
20689 + * This function sets a new value for the specified feature
20690 + *
20691 + * @param      pcd     A pointer to the PCD object
20692 + *
20693 + * @return 0 if successful, negative error code otherwise to stall the DCE.
20694 + */
20695 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
20696 +{
20697 +       int retval = -DWC_E_NOT_SUPPORTED;
20698 +       uint16_t wIndex, wValue;
20699 +       uint8_t bRequest;
20700 +       struct dwc_otg_core_if *coreif;
20701 +       cfiobject_t *cfi = pcd->cfi;
20702 +       struct cfi_usb_ctrlrequest *ctrl_req;
20703 +       uint8_t *buf;
20704 +       ctrl_req = &cfi->ctrl_req;
20705 +
20706 +       buf = pcd->cfi->ctrl_req.data;
20707 +
20708 +       coreif = GET_CORE_IF(pcd);
20709 +       bRequest = ctrl_req->bRequest;
20710 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
20711 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
20712 +
20713 +       /* See which feature is to be modified */
20714 +       switch (wIndex) {
20715 +       case FT_ID_DMA_BUFFER_SETUP:
20716 +               /* Modify the feature */
20717 +               if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
20718 +                       return retval;
20719 +
20720 +               /* And send this request to the gadget */
20721 +               cfi->need_gadget_att = 1;
20722 +               break;
20723 +
20724 +       case FT_ID_DMA_BUFF_ALIGN:
20725 +               if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
20726 +                       return retval;
20727 +               cfi->need_gadget_att = 1;
20728 +               break;
20729 +
20730 +       case FT_ID_DMA_CONCAT_SETUP:
20731 +               /* Modify the feature */
20732 +               if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
20733 +                       return retval;
20734 +               cfi->need_gadget_att = 1;
20735 +               break;
20736 +
20737 +       case FT_ID_DMA_CIRCULAR:
20738 +               CFI_INFO("FT_ID_DMA_CIRCULAR\n");
20739 +               break;
20740 +
20741 +       case FT_ID_THRESHOLD_SETUP:
20742 +               CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
20743 +               break;
20744 +
20745 +       case FT_ID_DFIFO_DEPTH:
20746 +               CFI_INFO("FT_ID_DFIFO_DEPTH\n");
20747 +               break;
20748 +
20749 +       case FT_ID_TX_FIFO_DEPTH:
20750 +               CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
20751 +               if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
20752 +                       return retval;
20753 +               cfi->need_gadget_att = 0;
20754 +               break;
20755 +
20756 +       case FT_ID_RX_FIFO_DEPTH:
20757 +               CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
20758 +               if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
20759 +                       return retval;
20760 +               cfi->need_gadget_att = 0;
20761 +               break;
20762 +       }
20763 +
20764 +       return retval;
20765 +}
20766 +
20767 +#endif //DWC_UTE_CFI
20768 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20769 new file mode 100644
20770 index 0000000..55fd337
20771 --- /dev/null
20772 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20773 @@ -0,0 +1,320 @@
20774 +/* ==========================================================================
20775 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20776 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20777 + * otherwise expressly agreed to in writing between Synopsys and you.
20778 + *
20779 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20780 + * any End User Software License Agreement or Agreement for Licensed Product
20781 + * with Synopsys or any supplement thereto. You are permitted to use and
20782 + * redistribute this Software in source and binary forms, with or without
20783 + * modification, provided that redistributions of source code must retain this
20784 + * notice. You may not view, use, disclose, copy or distribute this file or
20785 + * any information contained herein except pursuant to this license grant from
20786 + * Synopsys. If you do not agree with this notice, including the disclaimer
20787 + * below, then you are not authorized to use the Software.
20788 + *
20789 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20790 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20791 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20792 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20793 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20794 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20795 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20796 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20797 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20798 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20799 + * DAMAGE.
20800 + * ========================================================================== */
20801 +
20802 +#if !defined(__DWC_OTG_CFI_H__)
20803 +#define __DWC_OTG_CFI_H__
20804 +
20805 +#include "dwc_otg_pcd.h"
20806 +#include "dwc_cfi_common.h"
20807 +
20808 +/**
20809 + * @file
20810 + * This file contains the CFI related OTG PCD specific common constants,
20811 + * interfaces(functions and macros) and data structures.The CFI Protocol is an
20812 + * optional interface for internal testing purposes that a DUT may implement to
20813 + * support testing of configurable features.
20814 + *
20815 + */
20816 +
20817 +struct dwc_otg_pcd;
20818 +struct dwc_otg_pcd_ep;
20819 +
20820 +/** OTG CFI Features (properties) ID constants */
20821 +/** This is a request for all Core Features */
20822 +#define FT_ID_DMA_MODE                                 0x0001
20823 +#define FT_ID_DMA_BUFFER_SETUP                 0x0002
20824 +#define FT_ID_DMA_BUFF_ALIGN                   0x0003
20825 +#define FT_ID_DMA_CONCAT_SETUP                 0x0004
20826 +#define FT_ID_DMA_CIRCULAR                             0x0005
20827 +#define FT_ID_THRESHOLD_SETUP                  0x0006
20828 +#define FT_ID_DFIFO_DEPTH                              0x0007
20829 +#define FT_ID_TX_FIFO_DEPTH                            0x0008
20830 +#define FT_ID_RX_FIFO_DEPTH                            0x0009
20831 +
20832 +/**********************************************************/
20833 +#define CFI_INFO_DEF
20834 +
20835 +#ifdef CFI_INFO_DEF
20836 +#define CFI_INFO(fmt...)       DWC_PRINTF("CFI: " fmt);
20837 +#else
20838 +#define CFI_INFO(fmt...)
20839 +#endif
20840 +
20841 +#define min(x,y) ({ \
20842 +       x < y ? x : y; })
20843 +
20844 +#define max(x,y) ({ \
20845 +       x > y ? x : y; })
20846 +
20847 +/**
20848 + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
20849 + * also used for setting up a buffer for Circular DDMA.
20850 + */
20851 +struct _ddma_sg_buffer_setup {
20852 +#define BS_SG_VAL_DESC_LEN     6
20853 +       /* The OUT EP address */
20854 +       uint8_t bOutEndpointAddress;
20855 +       /* The IN EP address */
20856 +       uint8_t bInEndpointAddress;
20857 +       /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
20858 +       uint8_t bOffset;
20859 +       /* The number of transfer segments (a DMA descriptors per each segment) */
20860 +       uint8_t bCount;
20861 +       /* Size (in byte) of each transfer segment */
20862 +       uint16_t wSize;
20863 +} __attribute__ ((packed));
20864 +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
20865 +
20866 +/** Descriptor DMA Concatenation Buffer setup structure */
20867 +struct _ddma_concat_buffer_setup_hdr {
20868 +#define BS_CONCAT_VAL_HDR_LEN  4
20869 +       /* The endpoint for which the buffer is to be set up */
20870 +       uint8_t bEndpointAddress;
20871 +       /* The count of descriptors to be used */
20872 +       uint8_t bDescCount;
20873 +       /* The total size of the transfer */
20874 +       uint16_t wSize;
20875 +} __attribute__ ((packed));
20876 +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
20877 +
20878 +/** Descriptor DMA Concatenation Buffer setup structure */
20879 +struct _ddma_concat_buffer_setup {
20880 +       /* The SG header */
20881 +       ddma_concat_buffer_setup_hdr_t hdr;
20882 +
20883 +       /* The XFER sizes pointer (allocated dynamically) */
20884 +       uint16_t *wTxBytes;
20885 +} __attribute__ ((packed));
20886 +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
20887 +
20888 +/** Descriptor DMA Alignment Buffer setup structure */
20889 +struct _ddma_align_buffer_setup {
20890 +#define BS_ALIGN_VAL_HDR_LEN   2
20891 +       uint8_t bEndpointAddress;
20892 +       uint8_t bAlign;
20893 +} __attribute__ ((packed));
20894 +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
20895 +
20896 +/** Transmit FIFO Size setup structure */
20897 +struct _tx_fifo_size_setup {
20898 +       uint8_t bEndpointAddress;
20899 +       uint16_t wDepth;
20900 +} __attribute__ ((packed));
20901 +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
20902 +
20903 +/** Transmit FIFO Size setup structure */
20904 +struct _rx_fifo_size_setup {
20905 +       uint16_t wDepth;
20906 +} __attribute__ ((packed));
20907 +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
20908 +
20909 +/**
20910 + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
20911 + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer
20912 + * to the data returned in the data stage of a 3-stage Control Write requests.
20913 + */
20914 +struct cfi_usb_ctrlrequest {
20915 +       uint8_t bRequestType;
20916 +       uint8_t bRequest;
20917 +       uint16_t wValue;
20918 +       uint16_t wIndex;
20919 +       uint16_t wLength;
20920 +       uint8_t *data;
20921 +} UPACKED;
20922 +
20923 +/*---------------------------------------------------------------------------*/
20924 +
20925 +/**
20926 + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
20927 + * This structure is used to store the buffer setup data for any
20928 + * enabled endpoint in the PCD.
20929 + */
20930 +struct cfi_ep {
20931 +       /* Entry for the list container */
20932 +       dwc_list_link_t lh;
20933 +       /* Pointer to the active PCD endpoint structure */
20934 +       struct dwc_otg_pcd_ep *ep;
20935 +       /* The last descriptor in the chain of DMA descriptors of the endpoint */
20936 +       struct dwc_otg_dma_desc *dma_desc_last;
20937 +       /* The SG feature value */
20938 +       ddma_sg_buffer_setup_t *bm_sg;
20939 +       /* The Circular feature value */
20940 +       ddma_sg_buffer_setup_t *bm_circ;
20941 +       /* The Concatenation feature value */
20942 +       ddma_concat_buffer_setup_t *bm_concat;
20943 +       /* The Alignment feature value */
20944 +       ddma_align_buffer_setup_t *bm_align;
20945 +       /* XFER length */
20946 +       uint32_t xfer_len;
20947 +       /*
20948 +        * Count of DMA descriptors currently used.
20949 +        * The total should not exceed the MAX_DMA_DESCS_PER_EP value
20950 +        * defined in the dwc_otg_cil.h
20951 +        */
20952 +       uint32_t desc_count;
20953 +};
20954 +typedef struct cfi_ep cfi_ep_t;
20955 +
20956 +typedef struct cfi_dma_buff {
20957 +#define CFI_IN_BUF_LEN 1024
20958 +#define CFI_OUT_BUF_LEN        1024
20959 +       dma_addr_t addr;
20960 +       uint8_t *buf;
20961 +} cfi_dma_buff_t;
20962 +
20963 +struct cfiobject;
20964 +
20965 +/**
20966 + * This is the interface for the CFI operations.
20967 + *
20968 + * @param      ep_enable                       Called when any endpoint is enabled and activated.
20969 + * @param      release                         Called when the CFI object is released and it needs to correctly
20970 + *                                                             deallocate the dynamic memory
20971 + * @param      ctrl_write_complete     Called when the data stage of the request is complete
20972 + */
20973 +typedef struct cfi_ops {
20974 +       int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20975 +                         struct dwc_otg_pcd_ep * ep);
20976 +       void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20977 +                              struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
20978 +                              unsigned size, gfp_t flags);
20979 +       void (*release) (struct cfiobject * cfi);
20980 +       int (*ctrl_write_complete) (struct cfiobject * cfi,
20981 +                                   struct dwc_otg_pcd * pcd);
20982 +       void (*build_descriptors) (struct cfiobject * cfi,
20983 +                                  struct dwc_otg_pcd * pcd,
20984 +                                  struct dwc_otg_pcd_ep * ep,
20985 +                                  dwc_otg_pcd_request_t * req);
20986 +} cfi_ops_t;
20987 +
20988 +struct cfiobject {
20989 +       cfi_ops_t ops;
20990 +       struct dwc_otg_pcd *pcd;
20991 +       struct usb_gadget *gadget;
20992 +
20993 +       /* Buffers used to send/receive CFI-related request data */
20994 +       cfi_dma_buff_t buf_in;
20995 +       cfi_dma_buff_t buf_out;
20996 +
20997 +       /* CFI specific Control request wrapper */
20998 +       struct cfi_usb_ctrlrequest ctrl_req;
20999 +
21000 +       /* The list of active EP's in the PCD of type cfi_ep_t */
21001 +       dwc_list_link_t active_eps;
21002 +
21003 +       /* This flag shall control the propagation of a specific request
21004 +        * to the gadget's processing routines.
21005 +        * 0 - no gadget handling
21006 +        * 1 - the gadget needs to know about this request (w/o completing a status
21007 +        * phase - just return a 0 to the _setup callback)
21008 +        */
21009 +       uint8_t need_gadget_att;
21010 +
21011 +       /* Flag indicating whether the status IN phase needs to be
21012 +        * completed by the PCD
21013 +        */
21014 +       uint8_t need_status_in_complete;
21015 +};
21016 +typedef struct cfiobject cfiobject_t;
21017 +
21018 +#define DUMP_MSG
21019 +
21020 +#if defined(DUMP_MSG)
21021 +static inline void dump_msg(const u8 * buf, unsigned int length)
21022 +{
21023 +       unsigned int start, num, i;
21024 +       char line[52], *p;
21025 +
21026 +       if (length >= 512)
21027 +               return;
21028 +
21029 +       start = 0;
21030 +       while (length > 0) {
21031 +               num = min(length, 16u);
21032 +               p = line;
21033 +               for (i = 0; i < num; ++i) {
21034 +                       if (i == 8)
21035 +                               *p++ = ' ';
21036 +                       DWC_SPRINTF(p, " %02x", buf[i]);
21037 +                       p += 3;
21038 +               }
21039 +               *p = 0;
21040 +               DWC_DEBUG("%6x: %s\n", start, line);
21041 +               buf += num;
21042 +               start += num;
21043 +               length -= num;
21044 +       }
21045 +}
21046 +#else
21047 +static inline void dump_msg(const u8 * buf, unsigned int length)
21048 +{
21049 +}
21050 +#endif
21051 +
21052 +/**
21053 + * This function returns a pointer to cfi_ep_t object with the addr address.
21054 + */
21055 +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
21056 +                                               uint8_t addr)
21057 +{
21058 +       struct cfi_ep *pcfiep;
21059 +       dwc_list_link_t *tmp;
21060 +
21061 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
21062 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
21063 +
21064 +               if (pcfiep->ep->desc->bEndpointAddress == addr) {
21065 +                       return pcfiep;
21066 +               }
21067 +       }
21068 +
21069 +       return NULL;
21070 +}
21071 +
21072 +/**
21073 + * This function returns a pointer to cfi_ep_t object that matches
21074 + * the dwc_otg_pcd_ep object.
21075 + */
21076 +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
21077 +                                                 struct dwc_otg_pcd_ep *ep)
21078 +{
21079 +       struct cfi_ep *pcfiep = NULL;
21080 +       dwc_list_link_t *tmp;
21081 +
21082 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
21083 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
21084 +               if (pcfiep->ep == ep) {
21085 +                       return pcfiep;
21086 +               }
21087 +       }
21088 +       return NULL;
21089 +}
21090 +
21091 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
21092 +
21093 +#endif /* (__DWC_OTG_CFI_H__) */
21094 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
21095 new file mode 100644
21096 index 0000000..6a32c5c
21097 --- /dev/null
21098 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
21099 @@ -0,0 +1,7151 @@
21100 +/* ==========================================================================
21101 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
21102 + * $Revision: #191 $
21103 + * $Date: 2012/08/10 $
21104 + * $Change: 2047372 $
21105 + *
21106 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
21107 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
21108 + * otherwise expressly agreed to in writing between Synopsys and you.
21109 + *
21110 + * The Software IS NOT an item of Licensed Software or Licensed Product under
21111 + * any End User Software License Agreement or Agreement for Licensed Product
21112 + * with Synopsys or any supplement thereto. You are permitted to use and
21113 + * redistribute this Software in source and binary forms, with or without
21114 + * modification, provided that redistributions of source code must retain this
21115 + * notice. You may not view, use, disclose, copy or distribute this file or
21116 + * any information contained herein except pursuant to this license grant from
21117 + * Synopsys. If you do not agree with this notice, including the disclaimer
21118 + * below, then you are not authorized to use the Software.
21119 + *
21120 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
21121 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21122 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21123 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
21124 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21125 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21126 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21127 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21128 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21129 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
21130 + * DAMAGE.
21131 + * ========================================================================== */
21132 +
21133 +/** @file
21134 + *
21135 + * The Core Interface Layer provides basic services for accessing and
21136 + * managing the DWC_otg hardware. These services are used by both the
21137 + * Host Controller Driver and the Peripheral Controller Driver.
21138 + *
21139 + * The CIL manages the memory map for the core so that the HCD and PCD
21140 + * don't have to do this separately. It also handles basic tasks like
21141 + * reading/writing the registers and data FIFOs in the controller.
21142 + * Some of the data access functions provide encapsulation of several
21143 + * operations required to perform a task, such as writing multiple
21144 + * registers to start a transfer. Finally, the CIL performs basic
21145 + * services that are not specific to either the host or device modes
21146 + * of operation. These services include management of the OTG Host
21147 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
21148 + * Diagnostic API is also provided to allow testing of the controller
21149 + * hardware.
21150 + *
21151 + * The Core Interface Layer has the following requirements:
21152 + * - Provides basic controller operations.
21153 + * - Minimal use of OS services.
21154 + * - The OS services used will be abstracted by using inline functions
21155 + *      or macros.
21156 + *
21157 + */
21158 +
21159 +#include "dwc_os.h"
21160 +#include "dwc_otg_regs.h"
21161 +#include "dwc_otg_cil.h"
21162 +
21163 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
21164 +
21165 +/**
21166 + * This function is called to initialize the DWC_otg CSR data
21167 + * structures. The register addresses in the device and host
21168 + * structures are initialized from the base address supplied by the
21169 + * caller. The calling function must make the OS calls to get the
21170 + * base address of the DWC_otg controller registers. The core_params
21171 + * argument holds the parameters that specify how the core should be
21172 + * configured.
21173 + *
21174 + * @param reg_base_addr Base address of DWC_otg core registers
21175 + *
21176 + */
21177 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
21178 +{
21179 +       dwc_otg_core_if_t *core_if = 0;
21180 +       dwc_otg_dev_if_t *dev_if = 0;
21181 +       dwc_otg_host_if_t *host_if = 0;
21182 +       uint8_t *reg_base = (uint8_t *) reg_base_addr;
21183 +       int i = 0;
21184 +
21185 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
21186 +
21187 +       core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));
21188 +
21189 +       if (core_if == NULL) {
21190 +               DWC_DEBUGPL(DBG_CIL,
21191 +                           "Allocation of dwc_otg_core_if_t failed\n");
21192 +               return 0;
21193 +       }
21194 +       core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
21195 +
21196 +       /*
21197 +        * Allocate the Device Mode structures.
21198 +        */
21199 +       dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));
21200 +
21201 +       if (dev_if == NULL) {
21202 +               DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
21203 +               DWC_FREE(core_if);
21204 +               return 0;
21205 +       }
21206 +
21207 +       dev_if->dev_global_regs =
21208 +           (dwc_otg_device_global_regs_t *) (reg_base +
21209 +                                             DWC_DEV_GLOBAL_REG_OFFSET);
21210 +
21211 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21212 +               dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
21213 +                   (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
21214 +                    (i * DWC_EP_REG_OFFSET));
21215 +
21216 +               dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
21217 +                   (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
21218 +                    (i * DWC_EP_REG_OFFSET));
21219 +               DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
21220 +                           i, &dev_if->in_ep_regs[i]->diepctl);
21221 +               DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
21222 +                           i, &dev_if->out_ep_regs[i]->doepctl);
21223 +       }
21224 +
21225 +       dev_if->speed = 0;      // unknown
21226 +
21227 +       core_if->dev_if = dev_if;
21228 +
21229 +       /*
21230 +        * Allocate the Host Mode structures.
21231 +        */
21232 +       host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));
21233 +
21234 +       if (host_if == NULL) {
21235 +               DWC_DEBUGPL(DBG_CIL,
21236 +                           "Allocation of dwc_otg_host_if_t failed\n");
21237 +               DWC_FREE(dev_if);
21238 +               DWC_FREE(core_if);
21239 +               return 0;
21240 +       }
21241 +
21242 +       host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
21243 +           (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
21244 +
21245 +       host_if->hprt0 =
21246 +           (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
21247 +
21248 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21249 +               host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
21250 +                   (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
21251 +                    (i * DWC_OTG_CHAN_REGS_OFFSET));
21252 +               DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
21253 +                           i, &host_if->hc_regs[i]->hcchar);
21254 +       }
21255 +
21256 +       host_if->num_host_channels = MAX_EPS_CHANNELS;
21257 +       core_if->host_if = host_if;
21258 +
21259 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21260 +               core_if->data_fifo[i] =
21261 +                   (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
21262 +                                 (i * DWC_OTG_DATA_FIFO_SIZE));
21263 +               DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",
21264 +                           i, (unsigned long)core_if->data_fifo[i]);
21265 +       }
21266 +
21267 +       core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
21268 +
21269 +       /* Initiate lx_state to L3 disconnected state */
21270 +       core_if->lx_state = DWC_OTG_L3;
21271 +       /*
21272 +        * Store the contents of the hardware configuration registers here for
21273 +        * easy access later.
21274 +        */
21275 +       core_if->hwcfg1.d32 =
21276 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
21277 +       core_if->hwcfg2.d32 =
21278 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
21279 +       core_if->hwcfg3.d32 =
21280 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
21281 +       core_if->hwcfg4.d32 =
21282 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
21283 +
21284 +       /* Force host mode to get HPTXFSIZ exact power on value */
21285 +       {
21286 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
21287 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21288 +               gusbcfg.b.force_host_mode = 1;
21289 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21290 +               dwc_mdelay(100);
21291 +               core_if->hptxfsiz.d32 =
21292 +               DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21293 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21294 +               gusbcfg.b.force_host_mode = 0;
21295 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21296 +               dwc_mdelay(100);
21297 +       }
21298 +
21299 +       DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
21300 +       DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
21301 +       DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
21302 +       DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
21303 +
21304 +       core_if->hcfg.d32 =
21305 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21306 +       core_if->dcfg.d32 =
21307 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21308 +
21309 +       DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
21310 +       DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
21311 +
21312 +       DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
21313 +       DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
21314 +       DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
21315 +       DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
21316 +                   core_if->hwcfg2.b.num_host_chan);
21317 +       DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
21318 +                   core_if->hwcfg2.b.nonperio_tx_q_depth);
21319 +       DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
21320 +                   core_if->hwcfg2.b.host_perio_tx_q_depth);
21321 +       DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
21322 +                   core_if->hwcfg2.b.dev_token_q_depth);
21323 +
21324 +       DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
21325 +                   core_if->hwcfg3.b.dfifo_depth);
21326 +       DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
21327 +                   core_if->hwcfg3.b.xfer_size_cntr_width);
21328 +
21329 +       /*
21330 +        * Set the SRP sucess bit for FS-I2c
21331 +        */
21332 +       core_if->srp_success = 0;
21333 +       core_if->srp_timer_started = 0;
21334 +
21335 +       /*
21336 +        * Create new workqueue and init works
21337 +        */
21338 +       core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
21339 +       if (core_if->wq_otg == 0) {
21340 +               DWC_WARN("DWC_WORKQ_ALLOC failed\n");
21341 +               DWC_FREE(host_if);
21342 +               DWC_FREE(dev_if);
21343 +               DWC_FREE(core_if);
21344 +               return 0;
21345 +       }
21346 +
21347 +       core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
21348 +
21349 +       DWC_PRINTF("Core Release: %x.%x%x%x\n",
21350 +                  (core_if->snpsid >> 12 & 0xF),
21351 +                  (core_if->snpsid >> 8 & 0xF),
21352 +                  (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
21353 +
21354 +       core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
21355 +                                            w_wakeup_detected, core_if);
21356 +       if (core_if->wkp_timer == 0) {
21357 +               DWC_WARN("DWC_TIMER_ALLOC failed\n");
21358 +               DWC_FREE(host_if);
21359 +               DWC_FREE(dev_if);
21360 +               DWC_WORKQ_FREE(core_if->wq_otg);
21361 +               DWC_FREE(core_if);
21362 +               return 0;
21363 +       }
21364 +
21365 +       if (dwc_otg_setup_params(core_if)) {
21366 +               DWC_WARN("Error while setting core params\n");
21367 +       }
21368 +
21369 +       core_if->hibernation_suspend = 0;
21370 +
21371 +       /** ADP initialization */
21372 +       dwc_otg_adp_init(core_if);
21373 +
21374 +       return core_if;
21375 +}
21376 +
21377 +/**
21378 + * This function frees the structures allocated by dwc_otg_cil_init().
21379 + *
21380 + * @param core_if The core interface pointer returned from
21381 + *               dwc_otg_cil_init().
21382 + *
21383 + */
21384 +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
21385 +{
21386 +       dctl_data_t dctl = {.d32 = 0 };
21387 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
21388 +
21389 +       /* Disable all interrupts */
21390 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);
21391 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
21392 +
21393 +       dctl.b.sftdiscon = 1;
21394 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
21395 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,
21396 +                                dctl.d32);
21397 +       }
21398 +
21399 +       if (core_if->wq_otg) {
21400 +               DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
21401 +               DWC_WORKQ_FREE(core_if->wq_otg);
21402 +       }
21403 +       if (core_if->dev_if) {
21404 +               DWC_FREE(core_if->dev_if);
21405 +       }
21406 +       if (core_if->host_if) {
21407 +               DWC_FREE(core_if->host_if);
21408 +       }
21409 +
21410 +       /** Remove ADP Stuff  */
21411 +       dwc_otg_adp_remove(core_if);
21412 +       if (core_if->core_params) {
21413 +               DWC_FREE(core_if->core_params);
21414 +       }
21415 +       if (core_if->wkp_timer) {
21416 +               DWC_TIMER_FREE(core_if->wkp_timer);
21417 +       }
21418 +       if (core_if->srp_timer) {
21419 +               DWC_TIMER_FREE(core_if->srp_timer);
21420 +       }
21421 +       DWC_FREE(core_if);
21422 +}
21423 +
21424 +/**
21425 + * This function enables the controller's Global Interrupt in the AHB Config
21426 + * register.
21427 + *
21428 + * @param core_if Programming view of DWC_otg controller.
21429 + */
21430 +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
21431 +{
21432 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21433 +       ahbcfg.b.glblintrmsk = 1;       /* Enable interrupts */
21434 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
21435 +}
21436 +
21437 +/**
21438 + * This function disables the controller's Global Interrupt in the AHB Config
21439 + * register.
21440 + *
21441 + * @param core_if Programming view of DWC_otg controller.
21442 + */
21443 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
21444 +{
21445 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21446 +       ahbcfg.b.glblintrmsk = 1;       /* Disable interrupts */
21447 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
21448 +}
21449 +
21450 +/**
21451 + * This function initializes the commmon interrupts, used in both
21452 + * device and host modes.
21453 + *
21454 + * @param core_if Programming view of the DWC_otg controller
21455 + *
21456 + */
21457 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
21458 +{
21459 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
21460 +       gintmsk_data_t intr_mask = {.d32 = 0 };
21461 +
21462 +       /* Clear any pending OTG Interrupts */
21463 +       DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);
21464 +
21465 +       /* Clear any pending interrupts */
21466 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
21467 +
21468 +       /*
21469 +        * Enable the interrupts in the GINTMSK.
21470 +        */
21471 +       intr_mask.b.modemismatch = 1;
21472 +       intr_mask.b.otgintr = 1;
21473 +
21474 +       if (!core_if->dma_enable) {
21475 +               intr_mask.b.rxstsqlvl = 1;
21476 +       }
21477 +
21478 +       intr_mask.b.conidstschng = 1;
21479 +       intr_mask.b.wkupintr = 1;
21480 +       intr_mask.b.disconnect = 0;
21481 +       intr_mask.b.usbsuspend = 1;
21482 +       intr_mask.b.sessreqintr = 1;
21483 +#ifdef CONFIG_USB_DWC_OTG_LPM
21484 +       if (core_if->core_params->lpm_enable) {
21485 +               intr_mask.b.lpmtranrcvd = 1;
21486 +       }
21487 +#endif
21488 +       DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
21489 +}
21490 +
21491 +/*
21492 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21493 + * Hibernation. This function is for exiting from Device mode hibernation by
21494 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21495 + * @param core_if Programming view of DWC_otg controller.
21496 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21497 + * @param reset - indicates whether resume is initiated by Reset.
21498 + */
21499 +int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
21500 +                                      int rem_wakeup, int reset)
21501 +{
21502 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21503 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
21504 +       dctl_data_t dctl = {.d32 = 0 };
21505 +
21506 +       int timeout = 2000;
21507 +
21508 +       if (!core_if->hibernation_suspend) {
21509 +               DWC_PRINTF("Already exited from Hibernation\n");
21510 +               return 1;
21511 +       }
21512 +
21513 +       DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);
21514 +       /* Switch-on voltage to the core */
21515 +       gpwrdn.b.pwrdnswtch = 1;
21516 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21517 +       dwc_udelay(10);
21518 +
21519 +       /* Reset core */
21520 +       gpwrdn.d32 = 0;
21521 +       gpwrdn.b.pwrdnrstn = 1;
21522 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21523 +       dwc_udelay(10);
21524 +
21525 +       /* Assert Restore signal */
21526 +       gpwrdn.d32 = 0;
21527 +       gpwrdn.b.restore = 1;
21528 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21529 +       dwc_udelay(10);
21530 +
21531 +       /* Disable power clamps */
21532 +       gpwrdn.d32 = 0;
21533 +       gpwrdn.b.pwrdnclmp = 1;
21534 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21535 +
21536 +       if (rem_wakeup) {
21537 +               dwc_udelay(70);
21538 +       }
21539 +
21540 +       /* Deassert Reset core */
21541 +       gpwrdn.d32 = 0;
21542 +       gpwrdn.b.pwrdnrstn = 1;
21543 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21544 +       dwc_udelay(10);
21545 +
21546 +       /* Disable PMU interrupt */
21547 +       gpwrdn.d32 = 0;
21548 +       gpwrdn.b.pmuintsel = 1;
21549 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21550 +
21551 +       /* Mask interrupts from gpwrdn */
21552 +       gpwrdn.d32 = 0;
21553 +       gpwrdn.b.connect_det_msk = 1;
21554 +       gpwrdn.b.srp_det_msk = 1;
21555 +       gpwrdn.b.disconn_det_msk = 1;
21556 +       gpwrdn.b.rst_det_msk = 1;
21557 +       gpwrdn.b.lnstchng_msk = 1;
21558 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21559 +
21560 +       /* Indicates that we are going out from hibernation */
21561 +       core_if->hibernation_suspend = 0;
21562 +
21563 +       /*
21564 +        * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1
21565 +        * indicates restore from remote_wakeup
21566 +        */
21567 +       restore_essential_regs(core_if, rem_wakeup, 0);
21568 +
21569 +       /*
21570 +        * Wait a little for seeing new value of variable hibernation_suspend if
21571 +        * Restore done interrupt received before polling
21572 +        */
21573 +       dwc_udelay(10);
21574 +
21575 +       if (core_if->hibernation_suspend == 0) {
21576 +               /*
21577 +                * Wait For Restore_done Interrupt. This mechanism of polling the
21578 +                * interrupt is introduced to avoid any possible race conditions
21579 +                */
21580 +               do {
21581 +                       gintsts_data_t gintsts;
21582 +                       gintsts.d32 =
21583 +                           DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21584 +                       if (gintsts.b.restoredone) {
21585 +                               gintsts.d32 = 0;
21586 +                               gintsts.b.restoredone = 1;
21587 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
21588 +                                               gintsts, gintsts.d32);
21589 +                               DWC_PRINTF("Restore Done Interrupt seen\n");
21590 +                               break;
21591 +                       }
21592 +                       dwc_udelay(10);
21593 +               } while (--timeout);
21594 +               if (!timeout) {
21595 +                       DWC_PRINTF("Restore Done interrupt wasn't generated here\n");
21596 +               }
21597 +       }
21598 +       /* Clear all pending interupts */
21599 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21600 +
21601 +       /* De-assert Restore */
21602 +       gpwrdn.d32 = 0;
21603 +       gpwrdn.b.restore = 1;
21604 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21605 +       dwc_udelay(10);
21606 +
21607 +       if (!rem_wakeup) {
21608 +               pcgcctl.d32 = 0;
21609 +               pcgcctl.b.rstpdwnmodule = 1;
21610 +               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
21611 +       }
21612 +
21613 +       /* Restore GUSBCFG and DCFG */
21614 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21615 +                       core_if->gr_backup->gusbcfg_local);
21616 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
21617 +                       core_if->dr_backup->dcfg);
21618 +
21619 +       /* De-assert Wakeup Logic */
21620 +       gpwrdn.d32 = 0;
21621 +       gpwrdn.b.pmuactv = 1;
21622 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21623 +       dwc_udelay(10);
21624 +
21625 +       if (!rem_wakeup) {
21626 +               /* Set Device programming done bit */
21627 +               dctl.b.pwronprgdone = 1;
21628 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
21629 +       } else {
21630 +               /* Start Remote Wakeup Signaling */
21631 +               dctl.d32 = core_if->dr_backup->dctl;
21632 +               dctl.b.rmtwkupsig = 1;
21633 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
21634 +       }
21635 +
21636 +       dwc_mdelay(2);
21637 +       /* Clear all pending interupts */
21638 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21639 +
21640 +       /* Restore global registers */
21641 +       dwc_otg_restore_global_regs(core_if);
21642 +       /* Restore device global registers */
21643 +       dwc_otg_restore_dev_regs(core_if, rem_wakeup);
21644 +
21645 +       if (rem_wakeup) {
21646 +               dwc_mdelay(7);
21647 +               dctl.d32 = 0;
21648 +               dctl.b.rmtwkupsig = 1;
21649 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
21650 +       }
21651 +
21652 +       core_if->hibernation_suspend = 0;
21653 +       /* The core will be in ON STATE */
21654 +       core_if->lx_state = DWC_OTG_L0;
21655 +       DWC_PRINTF("Hibernation recovery completes here\n");
21656 +
21657 +       return 1;
21658 +}
21659 +
21660 +/*
21661 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21662 + * Hibernation. This function is for exiting from Host mode hibernation by
21663 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21664 + * @param core_if Programming view of DWC_otg controller.
21665 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21666 + * @param reset - indicates whether resume is initiated by Reset.
21667 + */
21668 +int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
21669 +                                    int rem_wakeup, int reset)
21670 +{
21671 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21672 +       hprt0_data_t hprt0 = {.d32 = 0 };
21673 +
21674 +       int timeout = 2000;
21675 +
21676 +       DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);
21677 +       /* Switch-on voltage to the core */
21678 +       gpwrdn.b.pwrdnswtch = 1;
21679 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21680 +       dwc_udelay(10);
21681 +
21682 +       /* Reset core */
21683 +       gpwrdn.d32 = 0;
21684 +       gpwrdn.b.pwrdnrstn = 1;
21685 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21686 +       dwc_udelay(10);
21687 +
21688 +       /* Assert Restore signal */
21689 +       gpwrdn.d32 = 0;
21690 +       gpwrdn.b.restore = 1;
21691 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21692 +       dwc_udelay(10);
21693 +
21694 +       /* Disable power clamps */
21695 +       gpwrdn.d32 = 0;
21696 +       gpwrdn.b.pwrdnclmp = 1;
21697 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21698 +
21699 +       if (!rem_wakeup) {
21700 +               dwc_udelay(50);
21701 +       }
21702 +
21703 +       /* Deassert Reset core */
21704 +       gpwrdn.d32 = 0;
21705 +       gpwrdn.b.pwrdnrstn = 1;
21706 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21707 +       dwc_udelay(10);
21708 +
21709 +       /* Disable PMU interrupt */
21710 +       gpwrdn.d32 = 0;
21711 +       gpwrdn.b.pmuintsel = 1;
21712 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21713 +
21714 +       gpwrdn.d32 = 0;
21715 +       gpwrdn.b.connect_det_msk = 1;
21716 +       gpwrdn.b.srp_det_msk = 1;
21717 +       gpwrdn.b.disconn_det_msk = 1;
21718 +       gpwrdn.b.rst_det_msk = 1;
21719 +       gpwrdn.b.lnstchng_msk = 1;
21720 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21721 +
21722 +       /* Indicates that we are going out from hibernation */
21723 +       core_if->hibernation_suspend = 0;
21724 +
21725 +       /* Set Restore Essential Regs bit in PCGCCTL register */
21726 +       restore_essential_regs(core_if, rem_wakeup, 1);
21727 +
21728 +       /* Wait a little for seeing new value of variable hibernation_suspend if
21729 +        * Restore done interrupt received before polling */
21730 +       dwc_udelay(10);
21731 +
21732 +       if (core_if->hibernation_suspend == 0) {
21733 +               /* Wait For Restore_done Interrupt. This mechanism of polling the
21734 +                * interrupt is introduced to avoid any possible race conditions
21735 +                */
21736 +               do {
21737 +                       gintsts_data_t gintsts;
21738 +                       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21739 +                       if (gintsts.b.restoredone) {
21740 +                               gintsts.d32 = 0;
21741 +                               gintsts.b.restoredone = 1;
21742 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
21743 +                               DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");
21744 +                               break;
21745 +                       }
21746 +                       dwc_udelay(10);
21747 +               } while (--timeout);
21748 +               if (!timeout) {
21749 +                       DWC_WARN("Restore Done interrupt wasn't generated\n");
21750 +               }
21751 +       }
21752 +
21753 +       /* Set the flag's value to 0 again after receiving restore done interrupt */
21754 +       core_if->hibernation_suspend = 0;
21755 +
21756 +       /* This step is not described in functional spec but if not wait for this
21757 +        * delay, mismatch interrupts occurred because just after restore core is
21758 +        * in Device mode(gintsts.curmode == 0) */
21759 +       dwc_mdelay(100);
21760 +
21761 +       /* Clear all pending interrupts */
21762 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21763 +
21764 +       /* De-assert Restore */
21765 +       gpwrdn.d32 = 0;
21766 +       gpwrdn.b.restore = 1;
21767 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21768 +       dwc_udelay(10);
21769 +
21770 +       /* Restore GUSBCFG and HCFG */
21771 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21772 +                       core_if->gr_backup->gusbcfg_local);
21773 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
21774 +                       core_if->hr_backup->hcfg_local);
21775 +
21776 +       /* De-assert Wakeup Logic */
21777 +       gpwrdn.d32 = 0;
21778 +       gpwrdn.b.pmuactv = 1;
21779 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21780 +       dwc_udelay(10);
21781 +
21782 +       /* Start the Resume operation by programming HPRT0 */
21783 +       hprt0.d32 = core_if->hr_backup->hprt0_local;
21784 +       hprt0.b.prtpwr = 1;
21785 +       hprt0.b.prtena = 0;
21786 +       hprt0.b.prtsusp = 0;
21787 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21788 +
21789 +       DWC_PRINTF("Resume Starts Now\n");
21790 +       if (!reset) {           // Indicates it is Resume Operation
21791 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21792 +               hprt0.b.prtres = 1;
21793 +               hprt0.b.prtpwr = 1;
21794 +               hprt0.b.prtena = 0;
21795 +               hprt0.b.prtsusp = 0;
21796 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21797 +
21798 +               if (!rem_wakeup)
21799 +                       hprt0.b.prtres = 0;
21800 +               /* Wait for Resume time and then program HPRT again */
21801 +               dwc_mdelay(100);
21802 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21803 +
21804 +       } else {                // Indicates it is Reset Operation
21805 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21806 +               hprt0.b.prtrst = 1;
21807 +               hprt0.b.prtpwr = 1;
21808 +               hprt0.b.prtena = 0;
21809 +               hprt0.b.prtsusp = 0;
21810 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21811 +               /* Wait for Reset time and then program HPRT again */
21812 +               dwc_mdelay(60);
21813 +               hprt0.b.prtrst = 0;
21814 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21815 +       }
21816 +       /* Clear all interrupt status */
21817 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
21818 +       hprt0.b.prtconndet = 1;
21819 +       hprt0.b.prtenchng = 1;
21820 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21821 +
21822 +       /* Clear all pending interupts */
21823 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21824 +
21825 +       /* Restore global registers */
21826 +       dwc_otg_restore_global_regs(core_if);
21827 +       /* Restore host global registers */
21828 +       dwc_otg_restore_host_regs(core_if, reset);
21829 +
21830 +       /* The core will be in ON STATE */
21831 +       core_if->lx_state = DWC_OTG_L0;
21832 +       DWC_PRINTF("Hibernation recovery is complete here\n");
21833 +       return 0;
21834 +}
21835 +
21836 +/** Saves some register values into system memory. */
21837 +int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)
21838 +{
21839 +       struct dwc_otg_global_regs_backup *gr;
21840 +       int i;
21841 +
21842 +       gr = core_if->gr_backup;
21843 +       if (!gr) {
21844 +               gr = DWC_ALLOC(sizeof(*gr));
21845 +               if (!gr) {
21846 +                       return -DWC_E_NO_MEMORY;
21847 +               }
21848 +               core_if->gr_backup = gr;
21849 +       }
21850 +
21851 +       gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
21852 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21853 +       gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
21854 +       gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21855 +       gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
21856 +       gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
21857 +       gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21858 +#ifdef CONFIG_USB_DWC_OTG_LPM
21859 +       gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
21860 +#endif
21861 +       gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);
21862 +       gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);
21863 +       gr->gdfifocfg_local =
21864 +           DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);
21865 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21866 +               gr->dtxfsiz_local[i] =
21867 +                   DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));
21868 +       }
21869 +
21870 +       DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");
21871 +       DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl   = %08x\n", gr->gotgctl_local);
21872 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21873 +       DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg   = %08x\n", gr->gahbcfg_local);
21874 +       DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg   = %08x\n", gr->gusbcfg_local);
21875 +       DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz   = %08x\n", gr->grxfsiz_local);
21876 +       DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",
21877 +                   gr->gnptxfsiz_local);
21878 +       DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz  = %08x\n",
21879 +                   gr->hptxfsiz_local);
21880 +#ifdef CONFIG_USB_DWC_OTG_LPM
21881 +       DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg   = %08x\n", gr->glpmcfg_local);
21882 +#endif
21883 +       DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl   = %08x\n", gr->gi2cctl_local);
21884 +       DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl   = %08x\n", gr->pcgcctl_local);
21885 +       DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg   = %08x\n",gr->gdfifocfg_local);
21886 +
21887 +       return 0;
21888 +}
21889 +
21890 +/** Saves GINTMSK register before setting the msk bits. */
21891 +int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)
21892 +{
21893 +       struct dwc_otg_global_regs_backup *gr;
21894 +
21895 +       gr = core_if->gr_backup;
21896 +       if (!gr) {
21897 +               gr = DWC_ALLOC(sizeof(*gr));
21898 +               if (!gr) {
21899 +                       return -DWC_E_NO_MEMORY;
21900 +               }
21901 +               core_if->gr_backup = gr;
21902 +       }
21903 +
21904 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21905 +
21906 +       DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");
21907 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21908 +
21909 +       return 0;
21910 +}
21911 +
21912 +int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)
21913 +{
21914 +       struct dwc_otg_dev_regs_backup *dr;
21915 +       int i;
21916 +
21917 +       dr = core_if->dr_backup;
21918 +       if (!dr) {
21919 +               dr = DWC_ALLOC(sizeof(*dr));
21920 +               if (!dr) {
21921 +                       return -DWC_E_NO_MEMORY;
21922 +               }
21923 +               core_if->dr_backup = dr;
21924 +       }
21925 +
21926 +       dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21927 +       dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
21928 +       dr->daintmsk =
21929 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
21930 +       dr->diepmsk =
21931 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);
21932 +       dr->doepmsk =
21933 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);
21934 +
21935 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21936 +               dr->diepctl[i] =
21937 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
21938 +               dr->dieptsiz[i] =
21939 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);
21940 +               dr->diepdma[i] =
21941 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
21942 +       }
21943 +
21944 +       DWC_DEBUGPL(DBG_ANY,
21945 +                   "=============Backing Host registers==============\n");
21946 +       DWC_DEBUGPL(DBG_ANY, "Backed up dcfg            = %08x\n", dr->dcfg);
21947 +       DWC_DEBUGPL(DBG_ANY, "Backed up dctl        = %08x\n", dr->dctl);
21948 +       DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk            = %08x\n",
21949 +                   dr->daintmsk);
21950 +       DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk        = %08x\n", dr->diepmsk);
21951 +       DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk        = %08x\n", dr->doepmsk);
21952 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21953 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d]        = %08x\n", i,
21954 +                           dr->diepctl[i]);
21955 +               DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d]        = %08x\n",
21956 +                           i, dr->dieptsiz[i]);
21957 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d]        = %08x\n", i,
21958 +                           dr->diepdma[i]);
21959 +       }
21960 +
21961 +       return 0;
21962 +}
21963 +
21964 +int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)
21965 +{
21966 +       struct dwc_otg_host_regs_backup *hr;
21967 +       int i;
21968 +
21969 +       hr = core_if->hr_backup;
21970 +       if (!hr) {
21971 +               hr = DWC_ALLOC(sizeof(*hr));
21972 +               if (!hr) {
21973 +                       return -DWC_E_NO_MEMORY;
21974 +               }
21975 +               core_if->hr_backup = hr;
21976 +       }
21977 +
21978 +       hr->hcfg_local =
21979 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21980 +       hr->haintmsk_local =
21981 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
21982 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21983 +               hr->hcintmsk_local[i] =
21984 +                   DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);
21985 +       }
21986 +       hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);
21987 +       hr->hfir_local =
21988 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
21989 +
21990 +       DWC_DEBUGPL(DBG_ANY,
21991 +                   "=============Backing Host registers===============\n");
21992 +       DWC_DEBUGPL(DBG_ANY, "Backed up hcfg            = %08x\n",
21993 +                   hr->hcfg_local);
21994 +       DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);
21995 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21996 +               DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,
21997 +                           hr->hcintmsk_local[i]);
21998 +       }
21999 +       DWC_DEBUGPL(DBG_ANY, "Backed up hprt0           = %08x\n",
22000 +                   hr->hprt0_local);
22001 +       DWC_DEBUGPL(DBG_ANY, "Backed up hfir           = %08x\n",
22002 +                   hr->hfir_local);
22003 +
22004 +       return 0;
22005 +}
22006 +
22007 +int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)
22008 +{
22009 +       struct dwc_otg_global_regs_backup *gr;
22010 +       int i;
22011 +
22012 +       gr = core_if->gr_backup;
22013 +       if (!gr) {
22014 +               return -DWC_E_INVALID;
22015 +       }
22016 +
22017 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
22018 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
22019 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
22020 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);
22021 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);
22022 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,
22023 +                       gr->gnptxfsiz_local);
22024 +       DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,
22025 +                       gr->hptxfsiz_local);
22026 +       DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,
22027 +                       gr->gdfifocfg_local);
22028 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
22029 +               DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],
22030 +                               gr->dtxfsiz_local[i]);
22031 +       }
22032 +
22033 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
22034 +       DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);
22035 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,
22036 +                       (gr->gahbcfg_local));
22037 +       return 0;
22038 +}
22039 +
22040 +int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)
22041 +{
22042 +       struct dwc_otg_dev_regs_backup *dr;
22043 +       int i;
22044 +
22045 +       dr = core_if->dr_backup;
22046 +
22047 +       if (!dr) {
22048 +               return -DWC_E_INVALID;
22049 +       }
22050 +
22051 +       if (!rem_wakeup) {
22052 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
22053 +                               dr->dctl);
22054 +       }
22055 +
22056 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
22057 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
22058 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
22059 +
22060 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22061 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
22062 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
22063 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);
22064 +       }
22065 +
22066 +       return 0;
22067 +}
22068 +
22069 +int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)
22070 +{
22071 +       struct dwc_otg_host_regs_backup *hr;
22072 +       int i;
22073 +       hr = core_if->hr_backup;
22074 +
22075 +       if (!hr) {
22076 +               return -DWC_E_INVALID;
22077 +       }
22078 +
22079 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);
22080 +       //if (!reset)
22081 +       //{
22082 +       //      DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);
22083 +       //}
22084 +
22085 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,
22086 +                       hr->haintmsk_local);
22087 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
22088 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,
22089 +                               hr->hcintmsk_local[i]);
22090 +       }
22091 +
22092 +       return 0;
22093 +}
22094 +
22095 +int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)
22096 +{
22097 +       struct dwc_otg_global_regs_backup *gr;
22098 +
22099 +       gr = core_if->gr_backup;
22100 +
22101 +       /* Restore values for LPM and I2C */
22102 +#ifdef CONFIG_USB_DWC_OTG_LPM
22103 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);
22104 +#endif
22105 +       DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);
22106 +
22107 +       return 0;
22108 +}
22109 +
22110 +int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)
22111 +{
22112 +       struct dwc_otg_global_regs_backup *gr;
22113 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
22114 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
22115 +       gusbcfg_data_t gusbcfg = {.d32 = 0 };
22116 +       gintmsk_data_t gintmsk = {.d32 = 0 };
22117 +
22118 +       /* Restore LPM and I2C registers */
22119 +       restore_lpm_i2c_regs(core_if);
22120 +
22121 +       /* Set PCGCCTL to 0 */
22122 +       DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);
22123 +
22124 +       gr = core_if->gr_backup;
22125 +       /* Load restore values for [31:14] bits */
22126 +       DWC_WRITE_REG32(core_if->pcgcctl,
22127 +                       ((gr->pcgcctl_local & 0xffffc000) | 0x00020000));
22128 +
22129 +       /* Umnask global Interrupt in GAHBCFG and restore it */
22130 +       gahbcfg.d32 = gr->gahbcfg_local;
22131 +       gahbcfg.b.glblintrmsk = 1;
22132 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
22133 +
22134 +       /* Clear all pending interupts */
22135 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
22136 +
22137 +       /* Unmask restore done interrupt */
22138 +       gintmsk.b.restoredone = 1;
22139 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
22140 +
22141 +       /* Restore GUSBCFG and HCFG/DCFG */
22142 +       gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;
22143 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
22144 +
22145 +       if (is_host) {
22146 +               hcfg_data_t hcfg = {.d32 = 0 };
22147 +               hcfg.d32 = core_if->hr_backup->hcfg_local;
22148 +               DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
22149 +                               hcfg.d32);
22150 +
22151 +               /* Load restore values for [31:14] bits */
22152 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22153 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22154 +
22155 +               if (rmode)
22156 +                       pcgcctl.b.restoremode = 1;
22157 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22158 +               dwc_udelay(10);
22159 +
22160 +               /* Load restore values for [31:14] bits and set EssRegRestored bit */
22161 +               pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;
22162 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22163 +               pcgcctl.b.ess_reg_restored = 1;
22164 +               if (rmode)
22165 +                       pcgcctl.b.restoremode = 1;
22166 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22167 +       } else {
22168 +               dcfg_data_t dcfg = {.d32 = 0 };
22169 +               dcfg.d32 = core_if->dr_backup->dcfg;
22170 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22171 +
22172 +               /* Load restore values for [31:14] bits */
22173 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22174 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22175 +               if (!rmode) {
22176 +                       pcgcctl.d32 |= 0x208;
22177 +               }
22178 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22179 +               dwc_udelay(10);
22180 +
22181 +               /* Load restore values for [31:14] bits */
22182 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22183 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22184 +               pcgcctl.b.ess_reg_restored = 1;
22185 +               if (!rmode)
22186 +                       pcgcctl.d32 |= 0x208;
22187 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22188 +       }
22189 +
22190 +       return 0;
22191 +}
22192 +
22193 +/**
22194 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
22195 + * type.
22196 + */
22197 +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
22198 +{
22199 +       uint32_t val;
22200 +       hcfg_data_t hcfg;
22201 +
22202 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22203 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22204 +            (core_if->core_params->ulpi_fs_ls)) ||
22205 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22206 +               /* Full speed PHY */
22207 +               val = DWC_HCFG_48_MHZ;
22208 +       } else {
22209 +               /* High speed PHY running at full speed or high speed */
22210 +               val = DWC_HCFG_30_60_MHZ;
22211 +       }
22212 +
22213 +       DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
22214 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
22215 +       hcfg.b.fslspclksel = val;
22216 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
22217 +}
22218 +
22219 +/**
22220 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
22221 + * and the enumeration speed of the device.
22222 + */
22223 +static void init_devspd(dwc_otg_core_if_t * core_if)
22224 +{
22225 +       uint32_t val;
22226 +       dcfg_data_t dcfg;
22227 +
22228 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22229 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22230 +            (core_if->core_params->ulpi_fs_ls)) ||
22231 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22232 +               /* Full speed PHY */
22233 +               val = 0x3;
22234 +       } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
22235 +               /* High speed PHY running at full speed */
22236 +               val = 0x1;
22237 +       } else {
22238 +               /* High speed PHY running at high speed */
22239 +               val = 0x0;
22240 +       }
22241 +
22242 +       DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
22243 +
22244 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
22245 +       dcfg.b.devspd = val;
22246 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22247 +}
22248 +
22249 +/**
22250 + * This function calculates the number of IN EPS
22251 + * using GHWCFG1 and GHWCFG2 registers values
22252 + *
22253 + * @param core_if Programming view of the DWC_otg controller
22254 + */
22255 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
22256 +{
22257 +       uint32_t num_in_eps = 0;
22258 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22259 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
22260 +       uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
22261 +       int i;
22262 +
22263 +       for (i = 0; i < num_eps; ++i) {
22264 +               if (!(hwcfg1 & 0x1))
22265 +                       num_in_eps++;
22266 +
22267 +               hwcfg1 >>= 2;
22268 +       }
22269 +
22270 +       if (core_if->hwcfg4.b.ded_fifo_en) {
22271 +               num_in_eps =
22272 +                   (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
22273 +       }
22274 +
22275 +       return num_in_eps;
22276 +}
22277 +
22278 +/**
22279 + * This function calculates the number of OUT EPS
22280 + * using GHWCFG1 and GHWCFG2 registers values
22281 + *
22282 + * @param core_if Programming view of the DWC_otg controller
22283 + */
22284 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
22285 +{
22286 +       uint32_t num_out_eps = 0;
22287 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22288 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
22289 +       int i;
22290 +
22291 +       for (i = 0; i < num_eps; ++i) {
22292 +               if (!(hwcfg1 & 0x1))
22293 +                       num_out_eps++;
22294 +
22295 +               hwcfg1 >>= 2;
22296 +       }
22297 +       return num_out_eps;
22298 +}
22299 +
22300 +/**
22301 + * This function initializes the DWC_otg controller registers and
22302 + * prepares the core for device mode or host mode operation.
22303 + *
22304 + * @param core_if Programming view of the DWC_otg controller
22305 + *
22306 + */
22307 +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
22308 +{
22309 +       int i = 0;
22310 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22311 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22312 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
22313 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
22314 +       gi2cctl_data_t i2cctl = {.d32 = 0 };
22315 +
22316 +       DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
22317 +                    core_if, global_regs);
22318 +
22319 +       /* Common Initialization */
22320 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22321 +
22322 +       /* Program the ULPI External VBUS bit if needed */
22323 +       usbcfg.b.ulpi_ext_vbus_drv =
22324 +           (core_if->core_params->phy_ulpi_ext_vbus ==
22325 +            DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
22326 +
22327 +       /* Set external TS Dline pulsing */
22328 +       usbcfg.b.term_sel_dl_pulse =
22329 +           (core_if->core_params->ts_dline == 1) ? 1 : 0;
22330 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22331 +
22332 +       /* Reset the Controller */
22333 +       dwc_otg_core_reset(core_if);
22334 +
22335 +       core_if->adp_enable = core_if->core_params->adp_supp_enable;
22336 +       core_if->power_down = core_if->core_params->power_down;
22337 +       core_if->otg_sts = 0;
22338 +
22339 +       /* Initialize parameters from Hardware configuration registers. */
22340 +       dev_if->num_in_eps = calc_num_in_eps(core_if);
22341 +       dev_if->num_out_eps = calc_num_out_eps(core_if);
22342 +
22343 +       DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
22344 +                   core_if->hwcfg4.b.num_dev_perio_in_ep);
22345 +
22346 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22347 +               dev_if->perio_tx_fifo_size[i] =
22348 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22349 +               DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
22350 +                           i, dev_if->perio_tx_fifo_size[i]);
22351 +       }
22352 +
22353 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22354 +               dev_if->tx_fifo_size[i] =
22355 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22356 +               DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
22357 +                           i, dev_if->tx_fifo_size[i]);
22358 +       }
22359 +
22360 +       core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
22361 +       core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
22362 +       core_if->nperio_tx_fifo_size =
22363 +           DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
22364 +
22365 +       DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
22366 +       DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
22367 +       DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
22368 +                   core_if->nperio_tx_fifo_size);
22369 +
22370 +       /* This programming sequence needs to happen in FS mode before any other
22371 +        * programming occurs */
22372 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
22373 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22374 +               /* If FS mode with FS PHY */
22375 +
22376 +               /* core_init() is now called on every switch so only call the
22377 +                * following for the first time through. */
22378 +               if (!core_if->phy_init_done) {
22379 +                       core_if->phy_init_done = 1;
22380 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
22381 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22382 +                       usbcfg.b.physel = 1;
22383 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22384 +
22385 +                       /* Reset after a PHY select */
22386 +                       dwc_otg_core_reset(core_if);
22387 +               }
22388 +
22389 +               /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also
22390 +                * do this on HNP Dev/Host mode switches (done in dev_init and
22391 +                * host_init). */
22392 +               if (dwc_otg_is_host_mode(core_if)) {
22393 +                       init_fslspclksel(core_if);
22394 +               } else {
22395 +                       init_devspd(core_if);
22396 +               }
22397 +
22398 +               if (core_if->core_params->i2c_enable) {
22399 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
22400 +                       /* Program GUSBCFG.OtgUtmifsSel to I2C */
22401 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22402 +                       usbcfg.b.otgutmifssel = 1;
22403 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22404 +
22405 +                       /* Program GI2CCTL.I2CEn */
22406 +                       i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);
22407 +                       i2cctl.b.i2cdevaddr = 1;
22408 +                       i2cctl.b.i2cen = 0;
22409 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22410 +                       i2cctl.b.i2cen = 1;
22411 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22412 +               }
22413 +
22414 +       } /* endif speed == DWC_SPEED_PARAM_FULL */
22415 +       else {
22416 +               /* High speed PHY. */
22417 +               if (!core_if->phy_init_done) {
22418 +                       core_if->phy_init_done = 1;
22419 +                       /* HS PHY parameters.  These parameters are preserved
22420 +                        * during soft reset so only program the first time.  Do
22421 +                        * a soft reset immediately after setting phyif.  */
22422 +
22423 +                       if (core_if->core_params->phy_type == 2) {
22424 +                               /* ULPI interface */
22425 +                               usbcfg.b.ulpi_utmi_sel = 1;
22426 +                               usbcfg.b.phyif = 0;
22427 +                               usbcfg.b.ddrsel =
22428 +                                   core_if->core_params->phy_ulpi_ddr;
22429 +                       } else if (core_if->core_params->phy_type == 1) {
22430 +                               /* UTMI+ interface */
22431 +                               usbcfg.b.ulpi_utmi_sel = 0;
22432 +                               if (core_if->core_params->phy_utmi_width == 16) {
22433 +                                       usbcfg.b.phyif = 1;
22434 +
22435 +                               } else {
22436 +                                       usbcfg.b.phyif = 0;
22437 +                               }
22438 +                       } else {
22439 +                               DWC_ERROR("FS PHY TYPE\n");
22440 +                       }
22441 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22442 +                       /* Reset after setting the PHY parameters */
22443 +                       dwc_otg_core_reset(core_if);
22444 +               }
22445 +       }
22446 +
22447 +       if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
22448 +           (core_if->hwcfg2.b.fs_phy_type == 1) &&
22449 +           (core_if->core_params->ulpi_fs_ls)) {
22450 +               DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
22451 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22452 +               usbcfg.b.ulpi_fsls = 1;
22453 +               usbcfg.b.ulpi_clk_sus_m = 1;
22454 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22455 +       } else {
22456 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22457 +               usbcfg.b.ulpi_fsls = 0;
22458 +               usbcfg.b.ulpi_clk_sus_m = 0;
22459 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22460 +       }
22461 +
22462 +       /* Program the GAHBCFG Register. */
22463 +       switch (core_if->hwcfg2.b.architecture) {
22464 +
22465 +       case DWC_SLAVE_ONLY_ARCH:
22466 +               DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
22467 +               ahbcfg.b.nptxfemplvl_txfemplvl =
22468 +                   DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22469 +               ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22470 +               core_if->dma_enable = 0;
22471 +               core_if->dma_desc_enable = 0;
22472 +               break;
22473 +
22474 +       case DWC_EXT_DMA_ARCH:
22475 +               DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
22476 +               {
22477 +                       uint8_t brst_sz = core_if->core_params->dma_burst_size;
22478 +                       ahbcfg.b.hburstlen = 0;
22479 +                       while (brst_sz > 1) {
22480 +                               ahbcfg.b.hburstlen++;
22481 +                               brst_sz >>= 1;
22482 +                       }
22483 +               }
22484 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22485 +               core_if->dma_desc_enable =
22486 +                   (core_if->core_params->dma_desc_enable != 0);
22487 +               break;
22488 +
22489 +       case DWC_INT_DMA_ARCH:
22490 +               DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
22491 +               /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
22492 +                 Host mode ISOC in issue fix - vahrama */
22493 +               /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */
22494 +               ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;
22495 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22496 +               core_if->dma_desc_enable =
22497 +                   (core_if->core_params->dma_desc_enable != 0);
22498 +               break;
22499 +
22500 +       }
22501 +       if (core_if->dma_enable) {
22502 +               if (core_if->dma_desc_enable) {
22503 +                       DWC_PRINTF("Using Descriptor DMA mode\n");
22504 +               } else {
22505 +                       DWC_PRINTF("Using Buffer DMA mode\n");
22506 +
22507 +               }
22508 +       } else {
22509 +               DWC_PRINTF("Using Slave mode\n");
22510 +               core_if->dma_desc_enable = 0;
22511 +       }
22512 +
22513 +       if (core_if->core_params->ahb_single) {
22514 +               ahbcfg.b.ahbsingle = 1;
22515 +       }
22516 +
22517 +       ahbcfg.b.dmaenable = core_if->dma_enable;
22518 +       DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
22519 +
22520 +       core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
22521 +
22522 +       core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
22523 +       core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
22524 +       DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
22525 +                  ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
22526 +       DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
22527 +                  ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
22528 +
22529 +       /*
22530 +        * Program the GUSBCFG register.
22531 +        */
22532 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22533 +
22534 +       switch (core_if->hwcfg2.b.op_mode) {
22535 +       case DWC_MODE_HNP_SRP_CAPABLE:
22536 +               usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
22537 +                                  DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
22538 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22539 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22540 +               break;
22541 +
22542 +       case DWC_MODE_SRP_ONLY_CAPABLE:
22543 +               usbcfg.b.hnpcap = 0;
22544 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22545 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22546 +               break;
22547 +
22548 +       case DWC_MODE_NO_HNP_SRP_CAPABLE:
22549 +               usbcfg.b.hnpcap = 0;
22550 +               usbcfg.b.srpcap = 0;
22551 +               break;
22552 +
22553 +       case DWC_MODE_SRP_CAPABLE_DEVICE:
22554 +               usbcfg.b.hnpcap = 0;
22555 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22556 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22557 +               break;
22558 +
22559 +       case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
22560 +               usbcfg.b.hnpcap = 0;
22561 +               usbcfg.b.srpcap = 0;
22562 +               break;
22563 +
22564 +       case DWC_MODE_SRP_CAPABLE_HOST:
22565 +               usbcfg.b.hnpcap = 0;
22566 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22567 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22568 +               break;
22569 +
22570 +       case DWC_MODE_NO_SRP_CAPABLE_HOST:
22571 +               usbcfg.b.hnpcap = 0;
22572 +               usbcfg.b.srpcap = 0;
22573 +               break;
22574 +       }
22575 +
22576 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22577 +
22578 +#ifdef CONFIG_USB_DWC_OTG_LPM
22579 +       if (core_if->core_params->lpm_enable) {
22580 +               glpmcfg_data_t lpmcfg = {.d32 = 0 };
22581 +
22582 +               /* To enable LPM support set lpm_cap_en bit */
22583 +               lpmcfg.b.lpm_cap_en = 1;
22584 +
22585 +               /* Make AppL1Res ACK */
22586 +               lpmcfg.b.appl_resp = 1;
22587 +
22588 +               /* Retry 3 times */
22589 +               lpmcfg.b.retry_count = 3;
22590 +
22591 +               DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,
22592 +                                0, lpmcfg.d32);
22593 +
22594 +       }
22595 +#endif
22596 +       if (core_if->core_params->ic_usb_cap) {
22597 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
22598 +               gusbcfg.b.ic_usb_cap = 1;
22599 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,
22600 +                                0, gusbcfg.d32);
22601 +       }
22602 +       {
22603 +               gotgctl_data_t gotgctl = {.d32 = 0 };
22604 +               gotgctl.b.otgver = core_if->core_params->otg_ver;
22605 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,
22606 +                                gotgctl.d32);
22607 +               /* Set OTG version supported */
22608 +               core_if->otg_ver = core_if->core_params->otg_ver;
22609 +               DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
22610 +                          core_if->core_params->otg_ver, core_if->otg_ver);
22611 +       }
22612 +
22613 +
22614 +       /* Enable common interrupts */
22615 +       dwc_otg_enable_common_interrupts(core_if);
22616 +
22617 +       /* Do device or host intialization based on mode during PCD
22618 +        * and HCD initialization  */
22619 +       if (dwc_otg_is_host_mode(core_if)) {
22620 +               DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
22621 +               core_if->op_state = A_HOST;
22622 +       } else {
22623 +               DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
22624 +               core_if->op_state = B_PERIPHERAL;
22625 +#ifdef DWC_DEVICE_ONLY
22626 +               dwc_otg_core_dev_init(core_if);
22627 +#endif
22628 +       }
22629 +}
22630 +
22631 +/**
22632 + * This function enables the Device mode interrupts.
22633 + *
22634 + * @param core_if Programming view of DWC_otg controller
22635 + */
22636 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
22637 +{
22638 +       gintmsk_data_t intr_mask = {.d32 = 0 };
22639 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22640 +
22641 +       DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
22642 +
22643 +       /* Disable all interrupts. */
22644 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22645 +
22646 +       /* Clear any pending interrupts */
22647 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22648 +
22649 +       /* Enable the common interrupts */
22650 +       dwc_otg_enable_common_interrupts(core_if);
22651 +
22652 +       /* Enable interrupts */
22653 +       intr_mask.b.usbreset = 1;
22654 +       intr_mask.b.enumdone = 1;
22655 +       /* Disable Disconnect interrupt in Device mode */
22656 +       intr_mask.b.disconnect = 0;
22657 +
22658 +       if (!core_if->multiproc_int_enable) {
22659 +               intr_mask.b.inepintr = 1;
22660 +               intr_mask.b.outepintr = 1;
22661 +       }
22662 +
22663 +       intr_mask.b.erlysuspend = 1;
22664 +
22665 +       if (core_if->en_multiple_tx_fifo == 0) {
22666 +               intr_mask.b.epmismatch = 1;
22667 +       }
22668 +
22669 +       //intr_mask.b.incomplisoout = 1;
22670 +       intr_mask.b.incomplisoin = 1;
22671 +
22672 +/* Enable the ignore frame number for ISOC xfers - MAS */
22673 +/* Disable to support high bandwith ISOC transfers - manukz */
22674 +#if 0
22675 +#ifdef DWC_UTE_PER_IO
22676 +       if (core_if->dma_enable) {
22677 +               if (core_if->dma_desc_enable) {
22678 +                       dctl_data_t dctl1 = {.d32 = 0 };
22679 +                       dctl1.b.ifrmnum = 1;
22680 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
22681 +                                        dctl, 0, dctl1.d32);
22682 +                       DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",
22683 +                                 DWC_READ_REG32(&core_if->dev_if->
22684 +                                                dev_global_regs->dctl));
22685 +               }
22686 +       }
22687 +#endif
22688 +#endif
22689 +#ifdef DWC_EN_ISOC
22690 +       if (core_if->dma_enable) {
22691 +               if (core_if->dma_desc_enable == 0) {
22692 +                       if (core_if->pti_enh_enable) {
22693 +                               dctl_data_t dctl = {.d32 = 0 };
22694 +                               dctl.b.ifrmnum = 1;
22695 +                               DWC_MODIFY_REG32(&core_if->
22696 +                                                dev_if->dev_global_regs->dctl,
22697 +                                                0, dctl.d32);
22698 +                       } else {
22699 +                               intr_mask.b.incomplisoin = 1;
22700 +                               intr_mask.b.incomplisoout = 1;
22701 +                       }
22702 +               }
22703 +       } else {
22704 +               intr_mask.b.incomplisoin = 1;
22705 +               intr_mask.b.incomplisoout = 1;
22706 +       }
22707 +#endif /* DWC_EN_ISOC */
22708 +
22709 +       /** @todo NGS: Should this be a module parameter? */
22710 +#ifdef USE_PERIODIC_EP
22711 +       intr_mask.b.isooutdrop = 1;
22712 +       intr_mask.b.eopframe = 1;
22713 +       intr_mask.b.incomplisoin = 1;
22714 +       intr_mask.b.incomplisoout = 1;
22715 +#endif
22716 +
22717 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
22718 +
22719 +       DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
22720 +                   DWC_READ_REG32(&global_regs->gintmsk));
22721 +}
22722 +
22723 +/**
22724 + * This function initializes the DWC_otg controller registers for
22725 + * device mode.
22726 + *
22727 + * @param core_if Programming view of DWC_otg controller
22728 + *
22729 + */
22730 +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
22731 +{
22732 +       int i;
22733 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22734 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22735 +       dwc_otg_core_params_t *params = core_if->core_params;
22736 +       dcfg_data_t dcfg = {.d32 = 0 };
22737 +       depctl_data_t diepctl = {.d32 = 0 };
22738 +       grstctl_t resetctl = {.d32 = 0 };
22739 +       uint32_t rx_fifo_size;
22740 +       fifosize_data_t nptxfifosize;
22741 +       fifosize_data_t txfifosize;
22742 +       dthrctl_data_t dthrctl;
22743 +       fifosize_data_t ptxfifosize;
22744 +       uint16_t rxfsiz, nptxfsiz;
22745 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
22746 +       hwcfg3_data_t hwcfg3 = {.d32 = 0 };
22747 +
22748 +       /* Restart the Phy Clock */
22749 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
22750 +
22751 +       /* Device configuration register */
22752 +       init_devspd(core_if);
22753 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22754 +       dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
22755 +       dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
22756 +       /* Enable Device OUT NAK in case of DDMA mode*/
22757 +       if (core_if->core_params->dev_out_nak) {
22758 +               dcfg.b.endevoutnak = 1;
22759 +       }
22760 +
22761 +       if (core_if->core_params->cont_on_bna) {
22762 +               dctl_data_t dctl = {.d32 = 0 };
22763 +               dctl.b.encontonbna = 1;
22764 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22765 +       }
22766 +
22767 +
22768 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22769 +
22770 +       /* Configure data FIFO sizes */
22771 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
22772 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
22773 +                           core_if->total_fifo_size);
22774 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
22775 +                           params->dev_rx_fifo_size);
22776 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
22777 +                           params->dev_nperio_tx_fifo_size);
22778 +
22779 +               /* Rx FIFO */
22780 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
22781 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22782 +
22783 +#ifdef DWC_UTE_CFI
22784 +               core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);
22785 +               core_if->init_rxfsiz = params->dev_rx_fifo_size;
22786 +#endif
22787 +               rx_fifo_size = params->dev_rx_fifo_size;
22788 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
22789 +
22790 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
22791 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22792 +
22793 +               /** Set Periodic Tx FIFO Mask all bits 0 */
22794 +               core_if->p_tx_msk = 0;
22795 +
22796 +               /** Set Tx FIFO Mask all bits 0 */
22797 +               core_if->tx_msk = 0;
22798 +
22799 +               if (core_if->en_multiple_tx_fifo == 0) {
22800 +                       /* Non-periodic Tx FIFO */
22801 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22802 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22803 +
22804 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22805 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22806 +
22807 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22808 +                                       nptxfifosize.d32);
22809 +
22810 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22811 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22812 +
22813 +                       /**@todo NGS: Fix Periodic FIFO Sizing! */
22814 +                       /*
22815 +                        * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
22816 +                        * Indexes of the FIFO size module parameters in the
22817 +                        * dev_perio_tx_fifo_size array and the FIFO size registers in
22818 +                        * the dptxfsiz array run from 0 to 14.
22819 +                        */
22820 +                       /** @todo Finish debug of this */
22821 +                       ptxfifosize.b.startaddr =
22822 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22823 +                       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22824 +                               ptxfifosize.b.depth =
22825 +                                   params->dev_perio_tx_fifo_size[i];
22826 +                               DWC_DEBUGPL(DBG_CIL,
22827 +                                           "initial dtxfsiz[%d]=%08x\n", i,
22828 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22829 +                                                          [i]));
22830 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22831 +                                               ptxfifosize.d32);
22832 +                               DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",
22833 +                                           i,
22834 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22835 +                                                          [i]));
22836 +                               ptxfifosize.b.startaddr += ptxfifosize.b.depth;
22837 +                       }
22838 +               } else {
22839 +                       /*
22840 +                        * Tx FIFOs These FIFOs are numbered from 1 to 15.
22841 +                        * Indexes of the FIFO size module parameters in the
22842 +                        * dev_tx_fifo_size array and the FIFO size registers in
22843 +                        * the dtxfsiz array run from 0 to 14.
22844 +                        */
22845 +
22846 +                       /* Non-periodic Tx FIFO */
22847 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22848 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22849 +
22850 +#ifdef DWC_UTE_CFI
22851 +                       core_if->pwron_gnptxfsiz =
22852 +                           (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22853 +                       core_if->init_gnptxfsiz =
22854 +                           params->dev_nperio_tx_fifo_size;
22855 +#endif
22856 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22857 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22858 +
22859 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22860 +                                       nptxfifosize.d32);
22861 +
22862 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22863 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22864 +
22865 +                       txfifosize.b.startaddr =
22866 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22867 +
22868 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22869 +
22870 +                               txfifosize.b.depth =
22871 +                                   params->dev_tx_fifo_size[i];
22872 +
22873 +                               DWC_DEBUGPL(DBG_CIL,
22874 +                                           "initial dtxfsiz[%d]=%08x\n",
22875 +                                           i,
22876 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22877 +                                                          [i]));
22878 +
22879 +#ifdef DWC_UTE_CFI
22880 +                               core_if->pwron_txfsiz[i] =
22881 +                                   (DWC_READ_REG32
22882 +                                    (&global_regs->dtxfsiz[i]) >> 16);
22883 +                               core_if->init_txfsiz[i] =
22884 +                                   params->dev_tx_fifo_size[i];
22885 +#endif
22886 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22887 +                                               txfifosize.d32);
22888 +
22889 +                               DWC_DEBUGPL(DBG_CIL,
22890 +                                           "new dtxfsiz[%d]=%08x\n",
22891 +                                           i,
22892 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22893 +                                                          [i]));
22894 +
22895 +                               txfifosize.b.startaddr += txfifosize.b.depth;
22896 +                       }
22897 +                       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
22898 +                               /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */
22899 +                               gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
22900 +                               hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);
22901 +                               gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);
22902 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22903 +                               rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
22904 +                               nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22905 +                               gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;
22906 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22907 +                       }
22908 +               }
22909 +
22910 +               /* Flush the FIFOs */
22911 +               dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
22912 +               dwc_otg_flush_rx_fifo(core_if);
22913 +
22914 +               /* Flush the Learning Queue. */
22915 +               resetctl.b.intknqflsh = 1;
22916 +               DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
22917 +
22918 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
22919 +                       core_if->start_predict = 0;
22920 +                       for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
22921 +                               core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
22922 +                       }
22923 +                       core_if->nextep_seq[0] = 0;
22924 +                       core_if->first_in_nextep_seq = 0;
22925 +                       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
22926 +                       diepctl.b.nextep = 0;
22927 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
22928 +
22929 +                       /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
22930 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22931 +                       dcfg.b.epmscnt = 2;
22932 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22933 +
22934 +                       DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
22935 +                               __func__, core_if->first_in_nextep_seq);
22936 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
22937 +                               DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
22938 +                       }
22939 +                       DWC_DEBUGPL(DBG_CILV,"\n");
22940 +               }
22941 +
22942 +               /* Clear all pending Device Interrupts */
22943 +               /** @todo - if the condition needed to be checked
22944 +                *  or in any case all pending interrutps should be cleared?
22945 +            */
22946 +               if (core_if->multiproc_int_enable) {
22947 +                       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22948 +                               DWC_WRITE_REG32(&dev_if->
22949 +                                               dev_global_regs->diepeachintmsk[i], 0);
22950 +                       }
22951 +               }
22952 +
22953 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
22954 +                       DWC_WRITE_REG32(&dev_if->
22955 +                                       dev_global_regs->doepeachintmsk[i], 0);
22956 +               }
22957 +
22958 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
22959 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);
22960 +       } else {
22961 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
22962 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
22963 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
22964 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
22965 +       }
22966 +
22967 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
22968 +               depctl_data_t depctl;
22969 +               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
22970 +               if (depctl.b.epena) {
22971 +                       depctl.d32 = 0;
22972 +                       depctl.b.epdis = 1;
22973 +                       depctl.b.snak = 1;
22974 +               } else {
22975 +                       depctl.d32 = 0;
22976 +               }
22977 +
22978 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
22979 +
22980 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
22981 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
22982 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
22983 +       }
22984 +
22985 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
22986 +               depctl_data_t depctl;
22987 +               depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
22988 +               if (depctl.b.epena) {
22989 +                       dctl_data_t dctl = {.d32 = 0 };
22990 +                       gintmsk_data_t gintsts = {.d32 = 0 };
22991 +                       doepint_data_t doepint = {.d32 = 0 };
22992 +                       dctl.b.sgoutnak = 1;
22993 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22994 +                       do {
22995 +                               dwc_udelay(10);
22996 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
22997 +                       } while (!gintsts.b.goutnakeff);
22998 +                       gintsts.d32 = 0;
22999 +                       gintsts.b.goutnakeff = 1;
23000 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
23001 +
23002 +                       depctl.d32 = 0;
23003 +                       depctl.b.epdis = 1;
23004 +                       depctl.b.snak = 1;
23005 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);
23006 +                       do {
23007 +                               dwc_udelay(10);
23008 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
23009 +                                       out_ep_regs[i]->doepint);
23010 +                       } while (!doepint.b.epdisabled);
23011 +
23012 +                       doepint.b.epdisabled = 1;
23013 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);
23014 +
23015 +                       dctl.d32 = 0;
23016 +                       dctl.b.cgoutnak = 1;
23017 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
23018 +               } else {
23019 +                       depctl.d32 = 0;
23020 +               }
23021 +
23022 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
23023 +
23024 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
23025 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
23026 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
23027 +       }
23028 +
23029 +       if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
23030 +               dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
23031 +               dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
23032 +               dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
23033 +
23034 +               dev_if->rx_thr_length = params->rx_thr_length;
23035 +               dev_if->tx_thr_length = params->tx_thr_length;
23036 +
23037 +               dev_if->setup_desc_index = 0;
23038 +
23039 +               dthrctl.d32 = 0;
23040 +               dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
23041 +               dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
23042 +               dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
23043 +               dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
23044 +               dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
23045 +               dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
23046 +
23047 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
23048 +                               dthrctl.d32);
23049 +
23050 +               DWC_DEBUGPL(DBG_CIL,
23051 +                           "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
23052 +                           dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
23053 +                           dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
23054 +                           dthrctl.b.rx_thr_len);
23055 +
23056 +       }
23057 +
23058 +       dwc_otg_enable_device_interrupts(core_if);
23059 +
23060 +       {
23061 +               diepmsk_data_t msk = {.d32 = 0 };
23062 +               msk.b.txfifoundrn = 1;
23063 +               if (core_if->multiproc_int_enable) {
23064 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->
23065 +                                        diepeachintmsk[0], msk.d32, msk.d32);
23066 +               } else {
23067 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,
23068 +                                        msk.d32, msk.d32);
23069 +               }
23070 +       }
23071 +
23072 +       if (core_if->multiproc_int_enable) {
23073 +               /* Set NAK on Babble */
23074 +               dctl_data_t dctl = {.d32 = 0 };
23075 +               dctl.b.nakonbble = 1;
23076 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
23077 +       }
23078 +
23079 +       if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
23080 +               dctl_data_t dctl = {.d32 = 0 };
23081 +               dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
23082 +               dctl.b.sftdiscon = 0;
23083 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
23084 +       }
23085 +}
23086 +
23087 +/**
23088 + * This function enables the Host mode interrupts.
23089 + *
23090 + * @param core_if Programming view of DWC_otg controller
23091 + */
23092 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
23093 +{
23094 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23095 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23096 +
23097 +       DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
23098 +
23099 +       /* Disable all interrupts. */
23100 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
23101 +
23102 +       /* Clear any pending interrupts. */
23103 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
23104 +
23105 +       /* Enable the common interrupts */
23106 +       dwc_otg_enable_common_interrupts(core_if);
23107 +
23108 +       /*
23109 +        * Enable host mode interrupts without disturbing common
23110 +        * interrupts.
23111 +        */
23112 +
23113 +       intr_mask.b.disconnect = 1;
23114 +       intr_mask.b.portintr = 1;
23115 +       intr_mask.b.hcintr = 1;
23116 +
23117 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
23118 +}
23119 +
23120 +/**
23121 + * This function disables the Host Mode interrupts.
23122 + *
23123 + * @param core_if Programming view of DWC_otg controller
23124 + */
23125 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
23126 +{
23127 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23128 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23129 +
23130 +       DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
23131 +
23132 +       /*
23133 +        * Disable host mode interrupts without disturbing common
23134 +        * interrupts.
23135 +        */
23136 +       intr_mask.b.sofintr = 1;
23137 +       intr_mask.b.portintr = 1;
23138 +       intr_mask.b.hcintr = 1;
23139 +       intr_mask.b.ptxfempty = 1;
23140 +       intr_mask.b.nptxfempty = 1;
23141 +
23142 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);
23143 +}
23144 +
23145 +/**
23146 + * This function initializes the DWC_otg controller registers for
23147 + * host mode.
23148 + *
23149 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
23150 + * request queues. Host channels are reset to ensure that they are ready for
23151 + * performing transfers.
23152 + *
23153 + * @param core_if Programming view of DWC_otg controller
23154 + *
23155 + */
23156 +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
23157 +{
23158 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23159 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23160 +       dwc_otg_core_params_t *params = core_if->core_params;
23161 +       hprt0_data_t hprt0 = {.d32 = 0 };
23162 +       fifosize_data_t nptxfifosize;
23163 +       fifosize_data_t ptxfifosize;
23164 +       uint16_t rxfsiz, nptxfsiz, hptxfsiz;
23165 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
23166 +       int i;
23167 +       hcchar_data_t hcchar;
23168 +       hcfg_data_t hcfg;
23169 +       hfir_data_t hfir;
23170 +       dwc_otg_hc_regs_t *hc_regs;
23171 +       int num_channels;
23172 +       gotgctl_data_t gotgctl = {.d32 = 0 };
23173 +
23174 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
23175 +
23176 +       /* Restart the Phy Clock */
23177 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
23178 +
23179 +       /* Initialize Host Configuration Register */
23180 +       init_fslspclksel(core_if);
23181 +       if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
23182 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23183 +               hcfg.b.fslssupp = 1;
23184 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23185 +
23186 +       }
23187 +
23188 +       /* This bit allows dynamic reloading of the HFIR register
23189 +        * during runtime. This bit needs to be programmed during
23190 +        * initial configuration and its value must not be changed
23191 +        * during runtime.*/
23192 +       if (core_if->core_params->reload_ctl == 1) {
23193 +               hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
23194 +               hfir.b.hfirrldctrl = 1;
23195 +               DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
23196 +       }
23197 +
23198 +       if (core_if->core_params->dma_desc_enable) {
23199 +               uint8_t op_mode = core_if->hwcfg2.b.op_mode;
23200 +               if (!
23201 +                   (core_if->hwcfg4.b.desc_dma
23202 +                    && (core_if->snpsid >= OTG_CORE_REV_2_90a)
23203 +                    && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
23204 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
23205 +                        || (op_mode ==
23206 +                            DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)
23207 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
23208 +                        || (op_mode ==
23209 +                            DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
23210 +
23211 +                       DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
23212 +                                 "Either core version is below 2.90a or "
23213 +                                 "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
23214 +                                 "To run the driver in Buffer DMA host mode set dma_desc_enable "
23215 +                                 "module parameter to 0.\n");
23216 +                       return;
23217 +               }
23218 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23219 +               hcfg.b.descdma = 1;
23220 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23221 +       }
23222 +
23223 +       /* Configure data FIFO sizes */
23224 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
23225 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
23226 +                           core_if->total_fifo_size);
23227 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
23228 +                           params->host_rx_fifo_size);
23229 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
23230 +                           params->host_nperio_tx_fifo_size);
23231 +               DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
23232 +                           params->host_perio_tx_fifo_size);
23233 +
23234 +               /* Rx FIFO */
23235 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
23236 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23237 +               DWC_WRITE_REG32(&global_regs->grxfsiz,
23238 +                               params->host_rx_fifo_size);
23239 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
23240 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23241 +
23242 +               /* Non-periodic Tx FIFO */
23243 +               DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
23244 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23245 +               nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
23246 +               nptxfifosize.b.startaddr = params->host_rx_fifo_size;
23247 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
23248 +               DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
23249 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23250 +
23251 +               /* Periodic Tx FIFO */
23252 +               DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
23253 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23254 +               ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
23255 +               ptxfifosize.b.startaddr =
23256 +                   nptxfifosize.b.startaddr + nptxfifosize.b.depth;
23257 +               DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
23258 +               DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
23259 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23260 +
23261 +               if (core_if->en_multiple_tx_fifo
23262 +                   && core_if->snpsid <= OTG_CORE_REV_2_94a) {
23263 +                       /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
23264 +                       gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
23265 +                       rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
23266 +                       nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
23267 +                       hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);
23268 +                       gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;
23269 +                       DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
23270 +               }
23271 +       }
23272 +
23273 +       /* TODO - check this */
23274 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23275 +       gotgctl.b.hstsethnpen = 1;
23276 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23277 +       /* Make sure the FIFOs are flushed. */
23278 +       dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );
23279 +       dwc_otg_flush_rx_fifo(core_if);
23280 +
23281 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23282 +       gotgctl.b.hstsethnpen = 1;
23283 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23284 +
23285 +       if (!core_if->core_params->dma_desc_enable) {
23286 +               /* Flush out any leftover queued requests. */
23287 +               num_channels = core_if->core_params->host_channels;
23288 +
23289 +               for (i = 0; i < num_channels; i++) {
23290 +                       hc_regs = core_if->host_if->hc_regs[i];
23291 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23292 +                       hcchar.b.chen = 0;
23293 +                       hcchar.b.chdis = 1;
23294 +                       hcchar.b.epdir = 0;
23295 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23296 +               }
23297 +
23298 +               /* Halt all channels to put them into a known state. */
23299 +               for (i = 0; i < num_channels; i++) {
23300 +                       int count = 0;
23301 +                       hc_regs = core_if->host_if->hc_regs[i];
23302 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23303 +                       hcchar.b.chen = 1;
23304 +                       hcchar.b.chdis = 1;
23305 +                       hcchar.b.epdir = 0;
23306 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23307 +                       DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
23308 +                       do {
23309 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23310 +                               if (++count > 1000) {
23311 +                                       DWC_ERROR
23312 +                                           ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
23313 +                                            __func__, i, hcchar.d32, &hc_regs->hcchar);
23314 +                                       break;
23315 +                               }
23316 +                               dwc_udelay(1);
23317 +                       } while (hcchar.b.chen);
23318 +               }
23319 +       }
23320 +
23321 +       /* Turn on the vbus power. */
23322 +       DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
23323 +       if (core_if->op_state == A_HOST) {
23324 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
23325 +               DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
23326 +               if (hprt0.b.prtpwr == 0) {
23327 +                       hprt0.b.prtpwr = 1;
23328 +                       DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);
23329 +               }
23330 +       }
23331 +
23332 +       dwc_otg_enable_host_interrupts(core_if);
23333 +}
23334 +
23335 +/**
23336 + * Prepares a host channel for transferring packets to/from a specific
23337 + * endpoint. The HCCHARn register is set up with the characteristics specified
23338 + * in _hc. Host channel interrupts that may need to be serviced while this
23339 + * transfer is in progress are enabled.
23340 + *
23341 + * @param core_if Programming view of DWC_otg controller
23342 + * @param hc Information needed to initialize the host channel
23343 + */
23344 +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23345 +{
23346 +       uint32_t intr_enable;
23347 +       hcintmsk_data_t hc_intr_mask;
23348 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23349 +       hcchar_data_t hcchar;
23350 +       hcsplt_data_t hcsplt;
23351 +
23352 +       uint8_t hc_num = hc->hc_num;
23353 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23354 +       dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
23355 +
23356 +       /* Clear old interrupt conditions for this host channel. */
23357 +       hc_intr_mask.d32 = 0xFFFFFFFF;
23358 +       hc_intr_mask.b.reserved14_31 = 0;
23359 +       DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);
23360 +
23361 +       /* Enable channel interrupts required for this transfer. */
23362 +       hc_intr_mask.d32 = 0;
23363 +       hc_intr_mask.b.chhltd = 1;
23364 +       if (core_if->dma_enable) {
23365 +               /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
23366 +               if (!core_if->dma_desc_enable)
23367 +                       hc_intr_mask.b.ahberr = 1;
23368 +               else {
23369 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23370 +                               hc_intr_mask.b.xfercompl = 1;
23371 +               }
23372 +
23373 +               if (hc->error_state && !hc->do_split &&
23374 +                   hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
23375 +                       hc_intr_mask.b.ack = 1;
23376 +                       if (hc->ep_is_in) {
23377 +                               hc_intr_mask.b.datatglerr = 1;
23378 +                               if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23379 +                                       hc_intr_mask.b.nak = 1;
23380 +                               }
23381 +                       }
23382 +               }
23383 +       } else {
23384 +               switch (hc->ep_type) {
23385 +               case DWC_OTG_EP_TYPE_CONTROL:
23386 +               case DWC_OTG_EP_TYPE_BULK:
23387 +                       hc_intr_mask.b.xfercompl = 1;
23388 +                       hc_intr_mask.b.stall = 1;
23389 +                       hc_intr_mask.b.xacterr = 1;
23390 +                       hc_intr_mask.b.datatglerr = 1;
23391 +                       if (hc->ep_is_in) {
23392 +                               hc_intr_mask.b.bblerr = 1;
23393 +                       } else {
23394 +                               hc_intr_mask.b.nak = 1;
23395 +                               hc_intr_mask.b.nyet = 1;
23396 +                               if (hc->do_ping) {
23397 +                                       hc_intr_mask.b.ack = 1;
23398 +                               }
23399 +                       }
23400 +
23401 +                       if (hc->do_split) {
23402 +                               hc_intr_mask.b.nak = 1;
23403 +                               if (hc->complete_split) {
23404 +                                       hc_intr_mask.b.nyet = 1;
23405 +                               } else {
23406 +                                       hc_intr_mask.b.ack = 1;
23407 +                               }
23408 +                       }
23409 +
23410 +                       if (hc->error_state) {
23411 +                               hc_intr_mask.b.ack = 1;
23412 +                       }
23413 +                       break;
23414 +               case DWC_OTG_EP_TYPE_INTR:
23415 +                       hc_intr_mask.b.xfercompl = 1;
23416 +                       hc_intr_mask.b.nak = 1;
23417 +                       hc_intr_mask.b.stall = 1;
23418 +                       hc_intr_mask.b.xacterr = 1;
23419 +                       hc_intr_mask.b.datatglerr = 1;
23420 +                       hc_intr_mask.b.frmovrun = 1;
23421 +
23422 +                       if (hc->ep_is_in) {
23423 +                               hc_intr_mask.b.bblerr = 1;
23424 +                       }
23425 +                       if (hc->error_state) {
23426 +                               hc_intr_mask.b.ack = 1;
23427 +                       }
23428 +                       if (hc->do_split) {
23429 +                               if (hc->complete_split) {
23430 +                                       hc_intr_mask.b.nyet = 1;
23431 +                               } else {
23432 +                                       hc_intr_mask.b.ack = 1;
23433 +                               }
23434 +                       }
23435 +                       break;
23436 +               case DWC_OTG_EP_TYPE_ISOC:
23437 +                       hc_intr_mask.b.xfercompl = 1;
23438 +                       hc_intr_mask.b.frmovrun = 1;
23439 +                       hc_intr_mask.b.ack = 1;
23440 +
23441 +                       if (hc->ep_is_in) {
23442 +                               hc_intr_mask.b.xacterr = 1;
23443 +                               hc_intr_mask.b.bblerr = 1;
23444 +                       }
23445 +                       break;
23446 +               }
23447 +       }
23448 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
23449 +
23450 +       /* Enable the top level host channel interrupt. */
23451 +       intr_enable = (1 << hc_num);
23452 +       DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
23453 +
23454 +       /* Make sure host channel interrupts are enabled. */
23455 +       gintmsk.b.hcintr = 1;
23456 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
23457 +
23458 +       /*
23459 +        * Program the HCCHARn register with the endpoint characteristics for
23460 +        * the current transfer.
23461 +        */
23462 +       hcchar.d32 = 0;
23463 +       hcchar.b.devaddr = hc->dev_addr;
23464 +       hcchar.b.epnum = hc->ep_num;
23465 +       hcchar.b.epdir = hc->ep_is_in;
23466 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
23467 +       hcchar.b.eptype = hc->ep_type;
23468 +       hcchar.b.mps = hc->max_packet;
23469 +
23470 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
23471 +
23472 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",
23473 +                    __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);
23474 +       DWC_DEBUGPL(DBG_HCDV, "  Is In %d, Is Low Speed %d, EP Type %d, "
23475 +                                "Max Pkt %d, Multi Cnt %d\n",
23476 +                    hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,
23477 +                    hcchar.b.mps, hcchar.b.multicnt);
23478 +
23479 +       /*
23480 +        * Program the HCSPLIT register for SPLITs
23481 +        */
23482 +       hcsplt.d32 = 0;
23483 +       if (hc->do_split) {
23484 +               DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
23485 +                           hc->hc_num,
23486 +                           hc->complete_split ? "CSPLIT" : "SSPLIT");
23487 +               hcsplt.b.compsplt = hc->complete_split;
23488 +               hcsplt.b.xactpos = hc->xact_pos;
23489 +               hcsplt.b.hubaddr = hc->hub_addr;
23490 +               hcsplt.b.prtaddr = hc->port_addr;
23491 +               DWC_DEBUGPL(DBG_HCDV, "\t  comp split %d\n", hc->complete_split);
23492 +               DWC_DEBUGPL(DBG_HCDV, "\t  xact pos %d\n", hc->xact_pos);
23493 +               DWC_DEBUGPL(DBG_HCDV, "\t  hub addr %d\n", hc->hub_addr);
23494 +               DWC_DEBUGPL(DBG_HCDV, "\t  port addr %d\n", hc->port_addr);
23495 +               DWC_DEBUGPL(DBG_HCDV, "\t  is_in %d\n", hc->ep_is_in);
23496 +               DWC_DEBUGPL(DBG_HCDV, "\t  Max Pkt: %d\n", hcchar.b.mps);
23497 +               DWC_DEBUGPL(DBG_HCDV, "\t  xferlen: %d\n", hc->xfer_len);
23498 +       }
23499 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
23500 +
23501 +}
23502 +
23503 +/**
23504 + * Attempts to halt a host channel. This function should only be called in
23505 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
23506 + * normal circumstances in DMA mode, the controller halts the channel when the
23507 + * transfer is complete or a condition occurs that requires application
23508 + * intervention.
23509 + *
23510 + * In slave mode, checks for a free request queue entry, then sets the Channel
23511 + * Enable and Channel Disable bits of the Host Channel Characteristics
23512 + * register of the specified channel to intiate the halt. If there is no free
23513 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
23514 + * register to flush requests for this channel. In the latter case, sets a
23515 + * flag to indicate that the host channel needs to be halted when a request
23516 + * queue slot is open.
23517 + *
23518 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
23519 + * HCCHARn register. The controller ensures there is space in the request
23520 + * queue before submitting the halt request.
23521 + *
23522 + * Some time may elapse before the core flushes any posted requests for this
23523 + * host channel and halts. The Channel Halted interrupt handler completes the
23524 + * deactivation of the host channel.
23525 + *
23526 + * @param core_if Controller register interface.
23527 + * @param hc Host channel to halt.
23528 + * @param halt_status Reason for halting the channel.
23529 + */
23530 +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
23531 +                    dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
23532 +{
23533 +       gnptxsts_data_t nptxsts;
23534 +       hptxsts_data_t hptxsts;
23535 +       hcchar_data_t hcchar;
23536 +       dwc_otg_hc_regs_t *hc_regs;
23537 +       dwc_otg_core_global_regs_t *global_regs;
23538 +       dwc_otg_host_global_regs_t *host_global_regs;
23539 +
23540 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23541 +       global_regs = core_if->core_global_regs;
23542 +       host_global_regs = core_if->host_if->host_global_regs;
23543 +
23544 +       DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
23545 +                  "halt_status = %d\n", halt_status);
23546 +
23547 +       if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
23548 +           halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
23549 +               /*
23550 +                * Disable all channel interrupts except Ch Halted. The QTD
23551 +                * and QH state associated with this transfer has been cleared
23552 +                * (in the case of URB_DEQUEUE), so the channel needs to be
23553 +                * shut down carefully to prevent crashes.
23554 +                */
23555 +               hcintmsk_data_t hcintmsk;
23556 +               hcintmsk.d32 = 0;
23557 +               hcintmsk.b.chhltd = 1;
23558 +               DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);
23559 +
23560 +               /*
23561 +                * Make sure no other interrupts besides halt are currently
23562 +                * pending. Handling another interrupt could cause a crash due
23563 +                * to the QTD and QH state.
23564 +                */
23565 +               DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);
23566 +
23567 +               /*
23568 +                * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
23569 +                * even if the channel was already halted for some other
23570 +                * reason.
23571 +                */
23572 +               hc->halt_status = halt_status;
23573 +
23574 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23575 +               if (hcchar.b.chen == 0) {
23576 +                       /*
23577 +                        * The channel is either already halted or it hasn't
23578 +                        * started yet. In DMA mode, the transfer may halt if
23579 +                        * it finishes normally or a condition occurs that
23580 +                        * requires driver intervention. Don't want to halt
23581 +                        * the channel again. In either Slave or DMA mode,
23582 +                        * it's possible that the transfer has been assigned
23583 +                        * to a channel, but not started yet when an URB is
23584 +                        * dequeued. Don't want to halt a channel that hasn't
23585 +                        * started yet.
23586 +                        */
23587 +                       return;
23588 +               }
23589 +       }
23590 +       if (hc->halt_pending) {
23591 +               /*
23592 +                * A halt has already been issued for this channel. This might
23593 +                * happen when a transfer is aborted by a higher level in
23594 +                * the stack.
23595 +                */
23596 +#ifdef DEBUG
23597 +               DWC_PRINTF
23598 +                   ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
23599 +                    __func__, hc->hc_num);
23600 +
23601 +#endif
23602 +               return;
23603 +       }
23604 +
23605 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23606 +
23607 +       /* No need to set the bit in DDMA for disabling the channel */
23608 +       //TODO check it everywhere channel is disabled
23609 +       if (!core_if->core_params->dma_desc_enable)
23610 +               hcchar.b.chen = 1;
23611 +       hcchar.b.chdis = 1;
23612 +
23613 +       if (!core_if->dma_enable) {
23614 +               /* Check for space in the request queue to issue the halt. */
23615 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
23616 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
23617 +                       nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
23618 +                       if (nptxsts.b.nptxqspcavail == 0) {
23619 +                               hcchar.b.chen = 0;
23620 +                       }
23621 +               } else {
23622 +                       hptxsts.d32 =
23623 +                           DWC_READ_REG32(&host_global_regs->hptxsts);
23624 +                       if ((hptxsts.b.ptxqspcavail == 0)
23625 +                           || (core_if->queuing_high_bandwidth)) {
23626 +                               hcchar.b.chen = 0;
23627 +                       }
23628 +               }
23629 +       }
23630 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23631 +
23632 +       hc->halt_status = halt_status;
23633 +
23634 +       if (hcchar.b.chen) {
23635 +               hc->halt_pending = 1;
23636 +               hc->halt_on_queue = 0;
23637 +       } else {
23638 +               hc->halt_on_queue = 1;
23639 +       }
23640 +
23641 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23642 +       DWC_DEBUGPL(DBG_HCDV, "  hcchar: 0x%08x\n", hcchar.d32);
23643 +       DWC_DEBUGPL(DBG_HCDV, "  halt_pending: %d\n", hc->halt_pending);
23644 +       DWC_DEBUGPL(DBG_HCDV, "  halt_on_queue: %d\n", hc->halt_on_queue);
23645 +       DWC_DEBUGPL(DBG_HCDV, "  halt_status: %d\n", hc->halt_status);
23646 +
23647 +       return;
23648 +}
23649 +
23650 +/**
23651 + * Clears the transfer state for a host channel. This function is normally
23652 + * called after a transfer is done and the host channel is being released.
23653 + *
23654 + * @param core_if Programming view of DWC_otg controller.
23655 + * @param hc Identifies the host channel to clean up.
23656 + */
23657 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23658 +{
23659 +       dwc_otg_hc_regs_t *hc_regs;
23660 +
23661 +       hc->xfer_started = 0;
23662 +
23663 +       /*
23664 +        * Clear channel interrupt enables and any unhandled channel interrupt
23665 +        * conditions.
23666 +        */
23667 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23668 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);
23669 +       DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);
23670 +#ifdef DEBUG
23671 +       DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
23672 +#endif
23673 +}
23674 +
23675 +/**
23676 + * Sets the channel property that indicates in which frame a periodic transfer
23677 + * should occur. This is always set to the _next_ frame. This function has no
23678 + * effect on non-periodic transfers.
23679 + *
23680 + * @param core_if Programming view of DWC_otg controller.
23681 + * @param hc Identifies the host channel to set up and its properties.
23682 + * @param hcchar Current value of the HCCHAR register for the specified host
23683 + * channel.
23684 + */
23685 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
23686 +                                        dwc_hc_t * hc, hcchar_data_t * hcchar)
23687 +{
23688 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23689 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23690 +               hfnum_data_t hfnum;
23691 +               hfnum.d32 =
23692 +                   DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);
23693 +
23694 +               /* 1 if _next_ frame is odd, 0 if it's even */
23695 +               hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
23696 +#ifdef DEBUG
23697 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
23698 +                   && !hc->complete_split) {
23699 +                       switch (hfnum.b.frnum & 0x7) {
23700 +                       case 7:
23701 +                               core_if->hfnum_7_samples++;
23702 +                               core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
23703 +                               break;
23704 +                       case 0:
23705 +                               core_if->hfnum_0_samples++;
23706 +                               core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
23707 +                               break;
23708 +                       default:
23709 +                               core_if->hfnum_other_samples++;
23710 +                               core_if->hfnum_other_frrem_accum +=
23711 +                                   hfnum.b.frrem;
23712 +                               break;
23713 +                       }
23714 +               }
23715 +#endif
23716 +       }
23717 +}
23718 +
23719 +#ifdef DEBUG
23720 +void hc_xfer_timeout(void *ptr)
23721 +{
23722 +       hc_xfer_info_t *xfer_info = NULL;
23723 +       int hc_num = 0;
23724 +
23725 +       if (ptr)
23726 +               xfer_info = (hc_xfer_info_t *) ptr;
23727 +
23728 +       if (!xfer_info->hc) {
23729 +               DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);
23730 +               return;
23731 +       }
23732 +
23733 +       hc_num = xfer_info->hc->hc_num;
23734 +       DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
23735 +       DWC_WARN("      start_hcchar_val 0x%08x\n",
23736 +                xfer_info->core_if->start_hcchar_val[hc_num]);
23737 +}
23738 +#endif
23739 +
23740 +void ep_xfer_timeout(void *ptr)
23741 +{
23742 +       ep_xfer_info_t *xfer_info = NULL;
23743 +       int ep_num = 0;
23744 +       dctl_data_t dctl = {.d32 = 0 };
23745 +       gintsts_data_t gintsts = {.d32 = 0 };
23746 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23747 +
23748 +       if (ptr)
23749 +               xfer_info = (ep_xfer_info_t *) ptr;
23750 +
23751 +       if (!xfer_info->ep) {
23752 +               DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);
23753 +               return;
23754 +       }
23755 +
23756 +       ep_num = xfer_info->ep->num;
23757 +       DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);
23758 +       /* Put the sate to 2 as it was time outed */
23759 +       xfer_info->state = 2;
23760 +
23761 +       dctl.d32 =
23762 +           DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);
23763 +       gintsts.d32 =
23764 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);
23765 +       gintmsk.d32 =
23766 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);
23767 +
23768 +       if (!gintmsk.b.goutnakeff) {
23769 +               /* Unmask it */
23770 +               gintmsk.b.goutnakeff = 1;
23771 +               DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,
23772 +                               gintmsk.d32);
23773 +
23774 +       }
23775 +
23776 +       if (!gintsts.b.goutnakeff) {
23777 +               dctl.b.sgoutnak = 1;
23778 +       }
23779 +       DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,
23780 +                       dctl.d32);
23781 +
23782 +}
23783 +
23784 +void set_pid_isoc(dwc_hc_t * hc)
23785 +{
23786 +       /* Set up the initial PID for the transfer. */
23787 +       if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
23788 +               if (hc->ep_is_in) {
23789 +                       if (hc->multi_count == 1) {
23790 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23791 +                       } else if (hc->multi_count == 2) {
23792 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
23793 +                       } else {
23794 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
23795 +                       }
23796 +               } else {
23797 +                       if (hc->multi_count == 1) {
23798 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23799 +                       } else {
23800 +                               hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
23801 +                       }
23802 +               }
23803 +       } else {
23804 +               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23805 +       }
23806 +}
23807 +
23808 +/**
23809 + * This function does the setup for a data transfer for a host channel and
23810 + * starts the transfer. May be called in either Slave mode or DMA mode. In
23811 + * Slave mode, the caller must ensure that there is sufficient space in the
23812 + * request queue and Tx Data FIFO.
23813 + *
23814 + * For an OUT transfer in Slave mode, it loads a data packet into the
23815 + * appropriate FIFO. If necessary, additional data packets will be loaded in
23816 + * the Host ISR.
23817 + *
23818 + * For an IN transfer in Slave mode, a data packet is requested. The data
23819 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
23820 + * additional data packets are requested in the Host ISR.
23821 + *
23822 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
23823 + * register along with a packet count of 1 and the channel is enabled. This
23824 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
23825 + * simply set to 0 since no data transfer occurs in this case.
23826 + *
23827 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
23828 + * all the information required to perform the subsequent data transfer. In
23829 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
23830 + * controller performs the entire PING protocol, then starts the data
23831 + * transfer.
23832 + *
23833 + * @param core_if Programming view of DWC_otg controller.
23834 + * @param hc Information needed to initialize the host channel. The xfer_len
23835 + * value may be reduced to accommodate the max widths of the XferSize and
23836 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
23837 + * to reflect the final xfer_len value.
23838 + */
23839 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23840 +{
23841 +       hcchar_data_t hcchar;
23842 +       hctsiz_data_t hctsiz;
23843 +       uint16_t num_packets;
23844 +       uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
23845 +       uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
23846 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23847 +
23848 +       hctsiz.d32 = 0;
23849 +
23850 +       if (hc->do_ping) {
23851 +               if (!core_if->dma_enable) {
23852 +                       dwc_otg_hc_do_ping(core_if, hc);
23853 +                       hc->xfer_started = 1;
23854 +                       return;
23855 +               } else {
23856 +                       hctsiz.b.dopng = 1;
23857 +               }
23858 +       }
23859 +
23860 +       if (hc->do_split) {
23861 +               num_packets = 1;
23862 +
23863 +               if (hc->complete_split && !hc->ep_is_in) {
23864 +                       /* For CSPLIT OUT Transfer, set the size to 0 so the
23865 +                        * core doesn't expect any data written to the FIFO */
23866 +                       hc->xfer_len = 0;
23867 +               } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
23868 +                       hc->xfer_len = hc->max_packet;
23869 +               } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
23870 +                       hc->xfer_len = 188;
23871 +               }
23872 +
23873 +               hctsiz.b.xfersize = hc->xfer_len;
23874 +       } else {
23875 +               /*
23876 +                * Ensure that the transfer length and packet count will fit
23877 +                * in the widths allocated for them in the HCTSIZn register.
23878 +                */
23879 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23880 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23881 +                       /*
23882 +                        * Make sure the transfer size is no larger than one
23883 +                        * (micro)frame's worth of data. (A check was done
23884 +                        * when the periodic transfer was accepted to ensure
23885 +                        * that a (micro)frame's worth of data can be
23886 +                        * programmed into a channel.)
23887 +                        */
23888 +                       uint32_t max_periodic_len =
23889 +                           hc->multi_count * hc->max_packet;
23890 +                       if (hc->xfer_len > max_periodic_len) {
23891 +                               hc->xfer_len = max_periodic_len;
23892 +                       } else {
23893 +                       }
23894 +               } else if (hc->xfer_len > max_hc_xfer_size) {
23895 +                       /* Make sure that xfer_len is a multiple of max packet size. */
23896 +                       hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
23897 +               }
23898 +
23899 +               if (hc->xfer_len > 0) {
23900 +                       num_packets =
23901 +                           (hc->xfer_len + hc->max_packet -
23902 +                            1) / hc->max_packet;
23903 +                       if (num_packets > max_hc_pkt_count) {
23904 +                               num_packets = max_hc_pkt_count;
23905 +                               hc->xfer_len = num_packets * hc->max_packet;
23906 +                       }
23907 +               } else {
23908 +                       /* Need 1 packet for transfer length of 0. */
23909 +                       num_packets = 1;
23910 +               }
23911 +
23912 +               if (hc->ep_is_in) {
23913 +                       /* Always program an integral # of max packets for IN transfers. */
23914 +                       hc->xfer_len = num_packets * hc->max_packet;
23915 +               }
23916 +
23917 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23918 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23919 +                       /*
23920 +                        * Make sure that the multi_count field matches the
23921 +                        * actual transfer length.
23922 +                        */
23923 +                       hc->multi_count = num_packets;
23924 +               }
23925 +
23926 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23927 +                       set_pid_isoc(hc);
23928 +
23929 +               hctsiz.b.xfersize = hc->xfer_len;
23930 +       }
23931 +
23932 +       hc->start_pkt_count = num_packets;
23933 +       hctsiz.b.pktcnt = num_packets;
23934 +       hctsiz.b.pid = hc->data_pid_start;
23935 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23936 +
23937 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23938 +       DWC_DEBUGPL(DBG_HCDV, "  Xfer Size: %d\n", hctsiz.b.xfersize);
23939 +       DWC_DEBUGPL(DBG_HCDV, "  Num Pkts: %d\n", hctsiz.b.pktcnt);
23940 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
23941 +
23942 +       if (core_if->dma_enable) {
23943 +               dwc_dma_t dma_addr;
23944 +               if (hc->align_buff) {
23945 +                       dma_addr = hc->align_buff;
23946 +               } else {
23947 +                       dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);
23948 +               }
23949 +               DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);
23950 +       }
23951 +
23952 +       /* Start the split */
23953 +       if (hc->do_split) {
23954 +               hcsplt_data_t hcsplt;
23955 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
23956 +               hcsplt.b.spltena = 1;
23957 +               DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);
23958 +       }
23959 +
23960 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23961 +       hcchar.b.multicnt = hc->multi_count;
23962 +       hc_set_even_odd_frame(core_if, hc, &hcchar);
23963 +#ifdef DEBUG
23964 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23965 +       if (hcchar.b.chdis) {
23966 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23967 +                        __func__, hc->hc_num, hcchar.d32);
23968 +       }
23969 +#endif
23970 +
23971 +       /* Set host channel enable after all other setup is complete. */
23972 +       hcchar.b.chen = 1;
23973 +       hcchar.b.chdis = 0;
23974 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23975 +
23976 +       hc->xfer_started = 1;
23977 +       hc->requests++;
23978 +
23979 +       if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
23980 +               /* Load OUT packet into the appropriate Tx FIFO. */
23981 +               dwc_otg_hc_write_packet(core_if, hc);
23982 +       }
23983 +#ifdef DEBUG
23984 +       if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23985 +                DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
23986 +                            hc->hc_num, core_if);//GRAYG
23987 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23988 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
23989 +
23990 +               /* Start a timer for this transfer. */
23991 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23992 +       }
23993 +#endif
23994 +}
23995 +
23996 +/**
23997 + * This function does the setup for a data transfer for a host channel
23998 + * and starts the transfer in Descriptor DMA mode.
23999 + *
24000 + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
24001 + * Sets PID and NTD values. For periodic transfers
24002 + * initializes SCHED_INFO field with micro-frame bitmap.
24003 + *
24004 + * Initializes HCDMA register with descriptor list address and CTD value
24005 + * then starts the transfer via enabling the channel.
24006 + *
24007 + * @param core_if Programming view of DWC_otg controller.
24008 + * @param hc Information needed to initialize the host channel.
24009 + */
24010 +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24011 +{
24012 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24013 +       hcchar_data_t hcchar;
24014 +       hctsiz_data_t hctsiz;
24015 +       hcdma_data_t hcdma;
24016 +
24017 +       hctsiz.d32 = 0;
24018 +
24019 +       if (hc->do_ping)
24020 +               hctsiz.b_ddma.dopng = 1;
24021 +
24022 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
24023 +               set_pid_isoc(hc);
24024 +
24025 +       /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
24026 +       hctsiz.b_ddma.pid = hc->data_pid_start;
24027 +       hctsiz.b_ddma.ntd = hc->ntd - 1;        /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
24028 +       hctsiz.b_ddma.schinfo = hc->schinfo;    /* Non-zero only for high-speed interrupt endpoints */
24029 +
24030 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24031 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
24032 +       DWC_DEBUGPL(DBG_HCDV, "  NTD: %d\n", hctsiz.b_ddma.ntd);
24033 +
24034 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
24035 +
24036 +       hcdma.d32 = 0;
24037 +       hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;
24038 +
24039 +       /* Always start from first descriptor. */
24040 +       hcdma.b.ctd = 0;
24041 +       DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);
24042 +
24043 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24044 +       hcchar.b.multicnt = hc->multi_count;
24045 +
24046 +#ifdef DEBUG
24047 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
24048 +       if (hcchar.b.chdis) {
24049 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
24050 +                        __func__, hc->hc_num, hcchar.d32);
24051 +       }
24052 +#endif
24053 +
24054 +       /* Set host channel enable after all other setup is complete. */
24055 +       hcchar.b.chen = 1;
24056 +       hcchar.b.chdis = 0;
24057 +
24058 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24059 +
24060 +       hc->xfer_started = 1;
24061 +       hc->requests++;
24062 +
24063 +#ifdef DEBUG
24064 +       if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)
24065 +           && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
24066 +                DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
24067 +                            hc->hc_num, core_if);//GRAYG
24068 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
24069 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
24070 +               /* Start a timer for this transfer. */
24071 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
24072 +       }
24073 +#endif
24074 +
24075 +}
24076 +
24077 +/**
24078 + * This function continues a data transfer that was started by previous call
24079 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
24080 + * sufficient space in the request queue and Tx Data FIFO. This function
24081 + * should only be called in Slave mode. In DMA mode, the controller acts
24082 + * autonomously to complete transfers programmed to a host channel.
24083 + *
24084 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
24085 + * if there is any data remaining to be queued. For an IN transfer, another
24086 + * data packet is always requested. For the SETUP phase of a control transfer,
24087 + * this function does nothing.
24088 + *
24089 + * @return 1 if a new request is queued, 0 if no more requests are required
24090 + * for this transfer.
24091 + */
24092 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24093 +{
24094 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24095 +
24096 +       if (hc->do_split) {
24097 +               /* SPLITs always queue just once per channel */
24098 +               return 0;
24099 +       } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
24100 +               /* SETUPs are queued only once since they can't be NAKed. */
24101 +               return 0;
24102 +       } else if (hc->ep_is_in) {
24103 +               /*
24104 +                * Always queue another request for other IN transfers. If
24105 +                * back-to-back INs are issued and NAKs are received for both,
24106 +                * the driver may still be processing the first NAK when the
24107 +                * second NAK is received. When the interrupt handler clears
24108 +                * the NAK interrupt for the first NAK, the second NAK will
24109 +                * not be seen. So we can't depend on the NAK interrupt
24110 +                * handler to requeue a NAKed request. Instead, IN requests
24111 +                * are issued each time this function is called. When the
24112 +                * transfer completes, the extra requests for the channel will
24113 +                * be flushed.
24114 +                */
24115 +               hcchar_data_t hcchar;
24116 +               dwc_otg_hc_regs_t *hc_regs =
24117 +                   core_if->host_if->hc_regs[hc->hc_num];
24118 +
24119 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24120 +               hc_set_even_odd_frame(core_if, hc, &hcchar);
24121 +               hcchar.b.chen = 1;
24122 +               hcchar.b.chdis = 0;
24123 +               DWC_DEBUGPL(DBG_HCDV, "  IN xfer: hcchar = 0x%08x\n",
24124 +                           hcchar.d32);
24125 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24126 +               hc->requests++;
24127 +               return 1;
24128 +       } else {
24129 +               /* OUT transfers. */
24130 +               if (hc->xfer_count < hc->xfer_len) {
24131 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
24132 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
24133 +                               hcchar_data_t hcchar;
24134 +                               dwc_otg_hc_regs_t *hc_regs;
24135 +                               hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24136 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24137 +                               hc_set_even_odd_frame(core_if, hc, &hcchar);
24138 +                       }
24139 +
24140 +                       /* Load OUT packet into the appropriate Tx FIFO. */
24141 +                       dwc_otg_hc_write_packet(core_if, hc);
24142 +                       hc->requests++;
24143 +                       return 1;
24144 +               } else {
24145 +                       return 0;
24146 +               }
24147 +       }
24148 +}
24149 +
24150 +/**
24151 + * Starts a PING transfer. This function should only be called in Slave mode.
24152 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
24153 + */
24154 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24155 +{
24156 +       hcchar_data_t hcchar;
24157 +       hctsiz_data_t hctsiz;
24158 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24159 +
24160 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24161 +
24162 +       hctsiz.d32 = 0;
24163 +       hctsiz.b.dopng = 1;
24164 +       hctsiz.b.pktcnt = 1;
24165 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
24166 +
24167 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24168 +       hcchar.b.chen = 1;
24169 +       hcchar.b.chdis = 0;
24170 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24171 +}
24172 +
24173 +/*
24174 + * This function writes a packet into the Tx FIFO associated with the Host
24175 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
24176 + * Tx FIFO is written. For a channel associated with a periodic EP, the
24177 + * periodic Tx FIFO is written. This function should only be called in Slave
24178 + * mode.
24179 + *
24180 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
24181 + * then number of bytes written to the Tx FIFO.
24182 + */
24183 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24184 +{
24185 +       uint32_t i;
24186 +       uint32_t remaining_count;
24187 +       uint32_t byte_count;
24188 +       uint32_t dword_count;
24189 +
24190 +       uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
24191 +       uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
24192 +
24193 +       remaining_count = hc->xfer_len - hc->xfer_count;
24194 +       if (remaining_count > hc->max_packet) {
24195 +               byte_count = hc->max_packet;
24196 +       } else {
24197 +               byte_count = remaining_count;
24198 +       }
24199 +
24200 +       dword_count = (byte_count + 3) / 4;
24201 +
24202 +       if ((((unsigned long)data_buff) & 0x3) == 0) {
24203 +               /* xfer_buff is DWORD aligned. */
24204 +               for (i = 0; i < dword_count; i++, data_buff++) {
24205 +                       DWC_WRITE_REG32(data_fifo, *data_buff);
24206 +               }
24207 +       } else {
24208 +               /* xfer_buff is not DWORD aligned. */
24209 +               for (i = 0; i < dword_count; i++, data_buff++) {
24210 +                       uint32_t data;
24211 +                       data =
24212 +                           (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
24213 +                            16 | data_buff[3] << 24);
24214 +                       DWC_WRITE_REG32(data_fifo, data);
24215 +               }
24216 +       }
24217 +
24218 +       hc->xfer_count += byte_count;
24219 +       hc->xfer_buff += byte_count;
24220 +}
24221 +
24222 +/**
24223 + * Gets the current USB frame number. This is the frame number from the last
24224 + * SOF packet.
24225 + */
24226 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
24227 +{
24228 +       dsts_data_t dsts;
24229 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
24230 +
24231 +       /* read current frame/microframe number from DSTS register */
24232 +       return dsts.b.soffn;
24233 +}
24234 +
24235 +/**
24236 + * Calculates and gets the frame Interval value of HFIR register according PHY
24237 + * type and speed.The application can modify a value of HFIR register only after
24238 + * the Port Enable bit of the Host Port Control and Status register
24239 + * (HPRT.PrtEnaPort) has been set.
24240 +*/
24241 +
24242 +uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)
24243 +{
24244 +       gusbcfg_data_t usbcfg;
24245 +       hwcfg2_data_t hwcfg2;
24246 +       hprt0_data_t hprt0;
24247 +       int clock = 60;         // default value
24248 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
24249 +       hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
24250 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
24251 +       if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24252 +               clock = 60;
24253 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)
24254 +               clock = 48;
24255 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24256 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24257 +               clock = 30;
24258 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24259 +           !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24260 +               clock = 60;
24261 +       if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24262 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24263 +               clock = 48;
24264 +       if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)
24265 +               clock = 48;
24266 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)
24267 +               clock = 48;
24268 +       if (hprt0.b.prtspd == 0)
24269 +               /* High speed case */
24270 +               return 125 * clock;
24271 +       else
24272 +               /* FS/LS case */
24273 +               return 1000 * clock;
24274 +}
24275 +
24276 +/**
24277 + * This function reads a setup packet from the Rx FIFO into the destination
24278 + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
24279 + * Interrupt routine when a SETUP packet has been received in Slave mode.
24280 + *
24281 + * @param core_if Programming view of DWC_otg controller.
24282 + * @param dest Destination buffer for packet data.
24283 + */
24284 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
24285 +{
24286 +       device_grxsts_data_t status;
24287 +       /* Get the 8 bytes of a setup transaction data */
24288 +
24289 +       /* Pop 2 DWORDS off the receive data FIFO into memory */
24290 +       dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
24291 +       dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
24292 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
24293 +               status.d32 =
24294 +                   DWC_READ_REG32(&core_if->core_global_regs->grxstsp);
24295 +               DWC_DEBUGPL(DBG_ANY,
24296 +                           "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",
24297 +                           status.b.epnum, status.b.bcnt, status.b.pktsts,
24298 +                           status.b.fn, status.b.fn);
24299 +       }
24300 +}
24301 +
24302 +/**
24303 + * This function enables EP0 OUT to receive SETUP packets and configures EP0
24304 + * IN for transmitting packets. It is normally called when the
24305 + * "Enumeration Done" interrupt occurs.
24306 + *
24307 + * @param core_if Programming view of DWC_otg controller.
24308 + * @param ep The EP0 data.
24309 + */
24310 +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24311 +{
24312 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24313 +       dsts_data_t dsts;
24314 +       depctl_data_t diepctl;
24315 +       depctl_data_t doepctl;
24316 +       dctl_data_t dctl = {.d32 = 0 };
24317 +
24318 +       ep->stp_rollover = 0;
24319 +       /* Read the Device Status and Endpoint 0 Control registers */
24320 +       dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
24321 +       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
24322 +       doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
24323 +
24324 +       /* Set the MPS of the IN EP based on the enumeration speed */
24325 +       switch (dsts.b.enumspd) {
24326 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
24327 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
24328 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
24329 +               diepctl.b.mps = DWC_DEP0CTL_MPS_64;
24330 +               break;
24331 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
24332 +               diepctl.b.mps = DWC_DEP0CTL_MPS_8;
24333 +               break;
24334 +       }
24335 +
24336 +       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
24337 +
24338 +       /* Enable OUT EP for receive */
24339 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
24340 +       doepctl.b.epena = 1;
24341 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
24342 +       }
24343 +#ifdef VERBOSE
24344 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
24345 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
24346 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
24347 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
24348 +#endif
24349 +       dctl.b.cgnpinnak = 1;
24350 +
24351 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
24352 +       DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
24353 +                   DWC_READ_REG32(&dev_if->dev_global_regs->dctl));
24354 +
24355 +}
24356 +
24357 +/**
24358 + * This function activates an EP.  The Device EP control register for
24359 + * the EP is configured as defined in the ep structure. Note: This
24360 + * function is not used for EP0.
24361 + *
24362 + * @param core_if Programming view of DWC_otg controller.
24363 + * @param ep The EP to activate.
24364 + */
24365 +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24366 +{
24367 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24368 +       depctl_data_t depctl;
24369 +       volatile uint32_t *addr;
24370 +       daint_data_t daintmsk = {.d32 = 0 };
24371 +       dcfg_data_t dcfg;
24372 +       uint8_t i;
24373 +
24374 +       DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
24375 +                   (ep->is_in ? "IN" : "OUT"));
24376 +
24377 +#ifdef DWC_UTE_PER_IO
24378 +       ep->xiso_frame_num = 0xFFFFFFFF;
24379 +       ep->xiso_active_xfers = 0;
24380 +       ep->xiso_queued_xfers = 0;
24381 +#endif
24382 +       /* Read DEPCTLn register */
24383 +       if (ep->is_in == 1) {
24384 +               addr = &dev_if->in_ep_regs[ep->num]->diepctl;
24385 +               daintmsk.ep.in = 1 << ep->num;
24386 +       } else {
24387 +               addr = &dev_if->out_ep_regs[ep->num]->doepctl;
24388 +               daintmsk.ep.out = 1 << ep->num;
24389 +       }
24390 +
24391 +       /* If the EP is already active don't change the EP Control
24392 +        * register. */
24393 +       depctl.d32 = DWC_READ_REG32(addr);
24394 +       if (!depctl.b.usbactep) {
24395 +               depctl.b.mps = ep->maxpacket;
24396 +               depctl.b.eptype = ep->type;
24397 +               depctl.b.txfnum = ep->tx_fifo_num;
24398 +
24399 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24400 +                       depctl.b.setd0pid = 1;  // ???
24401 +               } else {
24402 +                       depctl.b.setd0pid = 1;
24403 +               }
24404 +               depctl.b.usbactep = 1;
24405 +
24406 +               /* Update nextep_seq array and EPMSCNT in DCFG*/
24407 +               if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) {       // NP IN EP
24408 +                       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24409 +                               if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
24410 +                               break;
24411 +                       }
24412 +                       core_if->nextep_seq[i] = ep->num;
24413 +                       core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
24414 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24415 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
24416 +                       dcfg.b.epmscnt++;
24417 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
24418 +
24419 +                       DWC_DEBUGPL(DBG_PCDV,
24420 +                                   "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24421 +                               __func__, core_if->first_in_nextep_seq);
24422 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24423 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n",
24424 +                                           core_if->nextep_seq[i]);
24425 +                       }
24426 +
24427 +               }
24428 +
24429 +
24430 +               DWC_WRITE_REG32(addr, depctl.d32);
24431 +               DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));
24432 +       }
24433 +
24434 +       /* Enable the Interrupt for this EP */
24435 +       if (core_if->multiproc_int_enable) {
24436 +               if (ep->is_in == 1) {
24437 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
24438 +                       diepmsk.b.xfercompl = 1;
24439 +                       diepmsk.b.timeout = 1;
24440 +                       diepmsk.b.epdisabled = 1;
24441 +                       diepmsk.b.ahberr = 1;
24442 +                       diepmsk.b.intknepmis = 1;
24443 +                       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
24444 +                               diepmsk.b.intknepmis = 0;
24445 +                       diepmsk.b.txfifoundrn = 1;      //?????
24446 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24447 +                               diepmsk.b.nak = 1;
24448 +                       }
24449 +
24450 +
24451 +
24452 +/*
24453 +                       if (core_if->dma_desc_enable) {
24454 +                               diepmsk.b.bna = 1;
24455 +                       }
24456 +*/
24457 +/*
24458 +                       if (core_if->dma_enable) {
24459 +                               doepmsk.b.nak = 1;
24460 +                       }
24461 +*/
24462 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24463 +                                       diepeachintmsk[ep->num], diepmsk.d32);
24464 +
24465 +               } else {
24466 +                       doepmsk_data_t doepmsk = {.d32 = 0 };
24467 +                       doepmsk.b.xfercompl = 1;
24468 +                       doepmsk.b.ahberr = 1;
24469 +                       doepmsk.b.epdisabled = 1;
24470 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24471 +                               doepmsk.b.outtknepdis = 1;
24472 +
24473 +/*
24474 +
24475 +                       if (core_if->dma_desc_enable) {
24476 +                               doepmsk.b.bna = 1;
24477 +                       }
24478 +*/
24479 +/*
24480 +                       doepmsk.b.babble = 1;
24481 +                       doepmsk.b.nyet = 1;
24482 +                       doepmsk.b.nak = 1;
24483 +*/
24484 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24485 +                                       doepeachintmsk[ep->num], doepmsk.d32);
24486 +               }
24487 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
24488 +                                0, daintmsk.d32);
24489 +       } else {
24490 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24491 +                       if (ep->is_in) {
24492 +                               diepmsk_data_t diepmsk = {.d32 = 0 };
24493 +                               diepmsk.b.nak = 1;
24494 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
24495 +                       } else {
24496 +                               doepmsk_data_t doepmsk = {.d32 = 0 };
24497 +                               doepmsk.b.outtknepdis = 1;
24498 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
24499 +                       }
24500 +               }
24501 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
24502 +                                0, daintmsk.d32);
24503 +       }
24504 +
24505 +       DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
24506 +                   DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));
24507 +
24508 +       ep->stall_clear_flag = 0;
24509 +
24510 +       return;
24511 +}
24512 +
24513 +/**
24514 + * This function deactivates an EP. This is done by clearing the USB Active
24515 + * EP bit in the Device EP control register. Note: This function is not used
24516 + * for EP0. EP0 cannot be deactivated.
24517 + *
24518 + * @param core_if Programming view of DWC_otg controller.
24519 + * @param ep The EP to deactivate.
24520 + */
24521 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24522 +{
24523 +       depctl_data_t depctl = {.d32 = 0 };
24524 +       volatile uint32_t *addr;
24525 +       daint_data_t daintmsk = {.d32 = 0 };
24526 +       dcfg_data_t dcfg;
24527 +       uint8_t i = 0;
24528 +
24529 +#ifdef DWC_UTE_PER_IO
24530 +       ep->xiso_frame_num = 0xFFFFFFFF;
24531 +       ep->xiso_active_xfers = 0;
24532 +       ep->xiso_queued_xfers = 0;
24533 +#endif
24534 +
24535 +       /* Read DEPCTLn register */
24536 +       if (ep->is_in == 1) {
24537 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
24538 +               daintmsk.ep.in = 1 << ep->num;
24539 +       } else {
24540 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
24541 +               daintmsk.ep.out = 1 << ep->num;
24542 +       }
24543 +
24544 +       depctl.d32 = DWC_READ_REG32(addr);
24545 +
24546 +       depctl.b.usbactep = 0;
24547 +
24548 +       /* Update nextep_seq array and EPMSCNT in DCFG*/
24549 +       if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN
24550 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24551 +                       if (core_if->nextep_seq[i] == ep->num)
24552 +                       break;
24553 +               }
24554 +               core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];
24555 +               if (core_if->first_in_nextep_seq == ep->num)
24556 +                       core_if->first_in_nextep_seq = i;
24557 +               core_if->nextep_seq[ep->num] = 0xff;
24558 +               depctl.b.nextep = 0;
24559 +               dcfg.d32 =
24560 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
24561 +               dcfg.b.epmscnt--;
24562 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
24563 +                               dcfg.d32);
24564 +
24565 +               DWC_DEBUGPL(DBG_PCDV,
24566 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24567 +                               __func__, core_if->first_in_nextep_seq);
24568 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24569 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
24570 +                       }
24571 +       }
24572 +
24573 +       if (ep->is_in == 1)
24574 +               depctl.b.txfnum = 0;
24575 +
24576 +       if (core_if->dma_desc_enable)
24577 +               depctl.b.epdis = 1;
24578 +
24579 +       DWC_WRITE_REG32(addr, depctl.d32);
24580 +       depctl.d32 = DWC_READ_REG32(addr);
24581 +       if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC
24582 +           && depctl.b.epena) {
24583 +               depctl_data_t depctl = {.d32 = 0};
24584 +               if (ep->is_in) {
24585 +                       diepint_data_t diepint = {.d32 = 0};
24586 +
24587 +                       depctl.b.snak = 1;
24588 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24589 +                                       diepctl, depctl.d32);
24590 +                       do {
24591 +                               dwc_udelay(10);
24592 +                               diepint.d32 =
24593 +                                   DWC_READ_REG32(&core_if->
24594 +                                                  dev_if->in_ep_regs[ep->num]->
24595 +                                                  diepint);
24596 +                       } while (!diepint.b.inepnakeff);
24597 +                       diepint.b.inepnakeff = 1;
24598 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24599 +                                       diepint, diepint.d32);
24600 +                       depctl.d32 = 0;
24601 +                       depctl.b.epdis = 1;
24602 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24603 +                                       diepctl, depctl.d32);
24604 +                       do {
24605 +                               dwc_udelay(10);
24606 +                               diepint.d32 =
24607 +                                   DWC_READ_REG32(&core_if->
24608 +                                                  dev_if->in_ep_regs[ep->num]->
24609 +                                                  diepint);
24610 +                       } while (!diepint.b.epdisabled);
24611 +                       diepint.b.epdisabled = 1;
24612 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24613 +                                       diepint, diepint.d32);
24614 +               } else {
24615 +                       dctl_data_t dctl = {.d32 = 0};
24616 +                       gintmsk_data_t gintsts = {.d32 = 0};
24617 +                       doepint_data_t doepint = {.d32 = 0};
24618 +                       dctl.b.sgoutnak = 1;
24619 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
24620 +                                        dctl, 0, dctl.d32);
24621 +                       do {
24622 +                               dwc_udelay(10);
24623 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
24624 +                       } while (!gintsts.b.goutnakeff);
24625 +                       gintsts.d32 = 0;
24626 +                       gintsts.b.goutnakeff = 1;
24627 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
24628 +
24629 +                       depctl.d32 = 0;
24630 +                       depctl.b.epdis = 1;
24631 +                       depctl.b.snak = 1;
24632 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
24633 +                       do
24634 +                       {
24635 +                               dwc_udelay(10);
24636 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
24637 +                                                                                       out_ep_regs[ep->num]->doepint);
24638 +                       } while (!doepint.b.epdisabled);
24639 +
24640 +                       doepint.b.epdisabled = 1;
24641 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
24642 +
24643 +                       dctl.d32 = 0;
24644 +                       dctl.b.cgoutnak = 1;
24645 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
24646 +               }
24647 +       }
24648 +
24649 +       /* Disable the Interrupt for this EP */
24650 +       if (core_if->multiproc_int_enable) {
24651 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
24652 +                                daintmsk.d32, 0);
24653 +
24654 +               if (ep->is_in == 1) {
24655 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24656 +                                       diepeachintmsk[ep->num], 0);
24657 +               } else {
24658 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24659 +                                       doepeachintmsk[ep->num], 0);
24660 +               }
24661 +       } else {
24662 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,
24663 +                                daintmsk.d32, 0);
24664 +       }
24665 +
24666 +}
24667 +
24668 +/**
24669 + * This function initializes dma descriptor chain.
24670 + *
24671 + * @param core_if Programming view of DWC_otg controller.
24672 + * @param ep The EP to start the transfer on.
24673 + */
24674 +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24675 +{
24676 +       dwc_otg_dev_dma_desc_t *dma_desc;
24677 +       uint32_t offset;
24678 +       uint32_t xfer_est;
24679 +       int i;
24680 +       unsigned maxxfer_local, total_len;
24681 +
24682 +       if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&
24683 +                                       (ep->maxpacket%4)) {
24684 +               maxxfer_local = ep->maxpacket;
24685 +               total_len = ep->xfer_len;
24686 +       } else {
24687 +               maxxfer_local = ep->maxxfer;
24688 +               total_len = ep->total_len;
24689 +       }
24690 +
24691 +       ep->desc_cnt = (total_len / maxxfer_local) +
24692 +            ((total_len % maxxfer_local) ? 1 : 0);
24693 +
24694 +       if (!ep->desc_cnt)
24695 +               ep->desc_cnt = 1;
24696 +
24697 +       if (ep->desc_cnt > MAX_DMA_DESC_CNT)
24698 +               ep->desc_cnt = MAX_DMA_DESC_CNT;
24699 +
24700 +       dma_desc = ep->desc_addr;
24701 +       if (maxxfer_local == ep->maxpacket) {
24702 +               if ((total_len % maxxfer_local) &&
24703 +                               (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
24704 +                       xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
24705 +                                       (total_len % maxxfer_local);
24706 +               } else
24707 +                       xfer_est = ep->desc_cnt * maxxfer_local;
24708 +       } else
24709 +               xfer_est = total_len;
24710 +       offset = 0;
24711 +       for (i = 0; i < ep->desc_cnt; ++i) {
24712 +               /** DMA Descriptor Setup */
24713 +               if (xfer_est > maxxfer_local) {
24714 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24715 +                       dma_desc->status.b.l = 0;
24716 +                       dma_desc->status.b.ioc = 0;
24717 +                       dma_desc->status.b.sp = 0;
24718 +                       dma_desc->status.b.bytes = maxxfer_local;
24719 +                       dma_desc->buf = ep->dma_addr + offset;
24720 +                       dma_desc->status.b.sts = 0;
24721 +                       dma_desc->status.b.bs = BS_HOST_READY;
24722 +
24723 +                       xfer_est -= maxxfer_local;
24724 +                       offset += maxxfer_local;
24725 +               } else {
24726 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24727 +                       dma_desc->status.b.l = 1;
24728 +                       dma_desc->status.b.ioc = 1;
24729 +                       if (ep->is_in) {
24730 +                               dma_desc->status.b.sp =
24731 +                                   (xfer_est %
24732 +                                    ep->maxpacket) ? 1 : ((ep->
24733 +                                                           sent_zlp) ? 1 : 0);
24734 +                               dma_desc->status.b.bytes = xfer_est;
24735 +                       } else {
24736 +                               if (maxxfer_local == ep->maxpacket)
24737 +                                       dma_desc->status.b.bytes = xfer_est;
24738 +                               else
24739 +                                       dma_desc->status.b.bytes =
24740 +                                               xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
24741 +                       }
24742 +
24743 +                       dma_desc->buf = ep->dma_addr + offset;
24744 +                       dma_desc->status.b.sts = 0;
24745 +                       dma_desc->status.b.bs = BS_HOST_READY;
24746 +               }
24747 +               dma_desc++;
24748 +       }
24749 +}
24750 +/**
24751 + * This function is called when to write ISOC data into appropriate dedicated
24752 + * periodic FIFO.
24753 + */
24754 +static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
24755 +{
24756 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24757 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
24758 +       dtxfsts_data_t txstatus = {.d32 = 0 };
24759 +       uint32_t len = 0;
24760 +       int epnum = dwc_ep->num;
24761 +       int dwords;
24762 +
24763 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
24764 +
24765 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
24766 +
24767 +       len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24768 +
24769 +       if (len > dwc_ep->maxpacket) {
24770 +               len = dwc_ep->maxpacket;
24771 +       }
24772 +
24773 +       dwords = (len + 3) / 4;
24774 +
24775 +       /* While there is space in the queue and space in the FIFO and
24776 +        * More data to tranfer, Write packets to the Tx FIFO */
24777 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24778 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
24779 +
24780 +       while (txstatus.b.txfspcavail > dwords &&
24781 +              dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {
24782 +               /* Write the FIFO */
24783 +               dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
24784 +
24785 +               len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24786 +               if (len > dwc_ep->maxpacket) {
24787 +                       len = dwc_ep->maxpacket;
24788 +               }
24789 +
24790 +               dwords = (len + 3) / 4;
24791 +               txstatus.d32 =
24792 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24793 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
24794 +                           txstatus.d32);
24795 +       }
24796 +
24797 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
24798 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
24799 +
24800 +       return 1;
24801 +}
24802 +/**
24803 + * This function does the setup for a data transfer for an EP and
24804 + * starts the transfer. For an IN transfer, the packets will be
24805 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
24806 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
24807 + *
24808 + * @param core_if Programming view of DWC_otg controller.
24809 + * @param ep The EP to start the transfer on.
24810 + */
24811 +
24812 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24813 +{
24814 +       depctl_data_t depctl;
24815 +       deptsiz_data_t deptsiz;
24816 +       gintmsk_data_t intr_mask = {.d32 = 0 };
24817 +
24818 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24819 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
24820 +                   "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
24821 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
24822 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
24823 +                   ep->total_len);
24824 +       /* IN endpoint */
24825 +       if (ep->is_in == 1) {
24826 +               dwc_otg_dev_in_ep_regs_t *in_regs =
24827 +                   core_if->dev_if->in_ep_regs[ep->num];
24828 +
24829 +               gnptxsts_data_t gtxstatus;
24830 +
24831 +               gtxstatus.d32 =
24832 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
24833 +
24834 +               if (core_if->en_multiple_tx_fifo == 0
24835 +                   && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {
24836 +#ifdef DEBUG
24837 +                       DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
24838 +#endif
24839 +                       return;
24840 +               }
24841 +
24842 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
24843 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
24844 +
24845 +               if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24846 +                       ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24847 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24848 +               else
24849 +                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
24850 +                                MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24851 +
24852 +
24853 +               /* Zero Length Packet? */
24854 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24855 +                       deptsiz.b.xfersize = 0;
24856 +                       deptsiz.b.pktcnt = 1;
24857 +               } else {
24858 +                       /* Program the transfer size and packet count
24859 +                        *      as follows: xfersize = N * maxpacket +
24860 +                        *      short_packet pktcnt = N + (short_packet
24861 +                        *      exist ? 1 : 0)
24862 +                        */
24863 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24864 +                       deptsiz.b.pktcnt =
24865 +                           (ep->xfer_len - ep->xfer_count - 1 +
24866 +                            ep->maxpacket) / ep->maxpacket;
24867 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24868 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24869 +                               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
24870 +                       }
24871 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24872 +                               deptsiz.b.mc = deptsiz.b.pktcnt;
24873 +               }
24874 +
24875 +               /* Write the DMA register */
24876 +               if (core_if->dma_enable) {
24877 +                       if (core_if->dma_desc_enable == 0) {
24878 +                               if (ep->type != DWC_OTG_EP_TYPE_ISOC)
24879 +                                       deptsiz.b.mc = 1;
24880 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
24881 +                                               deptsiz.d32);
24882 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
24883 +                                               (uint32_t) ep->dma_addr);
24884 +                       } else {
24885 +#ifdef DWC_UTE_CFI
24886 +                               /* The descriptor chain should be already initialized by now */
24887 +                               if (ep->buff_mode != BM_STANDARD) {
24888 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24889 +                                                       ep->descs_dma_addr);
24890 +                               } else {
24891 +#endif
24892 +                                       init_dma_desc_chain(core_if, ep);
24893 +                               /** DIEPDMAn Register write */
24894 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24895 +                                                       ep->dma_desc_addr);
24896 +#ifdef DWC_UTE_CFI
24897 +                               }
24898 +#endif
24899 +                       }
24900 +               } else {
24901 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
24902 +                       if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
24903 +                               /**
24904 +                                * Enable the Non-Periodic Tx FIFO empty interrupt,
24905 +                                * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
24906 +                                * the data will be written into the fifo by the ISR.
24907 +                                */
24908 +                               if (core_if->en_multiple_tx_fifo == 0) {
24909 +                                       intr_mask.b.nptxfempty = 1;
24910 +                                       DWC_MODIFY_REG32
24911 +                                           (&core_if->core_global_regs->gintmsk,
24912 +                                            intr_mask.d32, intr_mask.d32);
24913 +                               } else {
24914 +                                       /* Enable the Tx FIFO Empty Interrupt for this EP */
24915 +                                       if (ep->xfer_len > 0) {
24916 +                                               uint32_t fifoemptymsk = 0;
24917 +                                               fifoemptymsk = 1 << ep->num;
24918 +                                               DWC_MODIFY_REG32
24919 +                                                   (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
24920 +                                                    0, fifoemptymsk);
24921 +
24922 +                                       }
24923 +                               }
24924 +                       }  else {
24925 +                                        write_isoc_tx_fifo(core_if, ep);
24926 +                       }
24927 +               }
24928 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
24929 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24930 +
24931 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24932 +                       dsts_data_t dsts = {.d32 = 0};
24933 +                       if (ep->bInterval == 1) {
24934 +                               dsts.d32 =
24935 +                                   DWC_READ_REG32(&core_if->dev_if->
24936 +                                                  dev_global_regs->dsts);
24937 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
24938 +                               if (ep->frame_num > 0x3FFF) {
24939 +                                       ep->frm_overrun = 1;
24940 +                                       ep->frame_num &= 0x3FFF;
24941 +                               } else
24942 +                                       ep->frm_overrun = 0;
24943 +                               if (ep->frame_num & 0x1) {
24944 +                                       depctl.b.setd1pid = 1;
24945 +                               } else {
24946 +                                       depctl.b.setd0pid = 1;
24947 +                               }
24948 +                       }
24949 +               }
24950 +               /* EP enable, IN data in FIFO */
24951 +               depctl.b.cnak = 1;
24952 +               depctl.b.epena = 1;
24953 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
24954 +
24955 +       } else {
24956 +               /* OUT endpoint */
24957 +               dwc_otg_dev_out_ep_regs_t *out_regs =
24958 +                   core_if->dev_if->out_ep_regs[ep->num];
24959 +
24960 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
24961 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
24962 +
24963 +               if (!core_if->dma_desc_enable) {
24964 +                       if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24965 +                               ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24966 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24967 +                else
24968 +                                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len
24969 +                                       - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24970 +               }
24971 +
24972 +               /* Program the transfer size and packet count as follows:
24973 +                *
24974 +                *      pktcnt = N
24975 +                *      xfersize = N * maxpacket
24976 +                */
24977 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24978 +                       /* Zero Length Packet */
24979 +                       deptsiz.b.xfersize = ep->maxpacket;
24980 +                       deptsiz.b.pktcnt = 1;
24981 +               } else {
24982 +                       deptsiz.b.pktcnt =
24983 +                           (ep->xfer_len - ep->xfer_count +
24984 +                            (ep->maxpacket - 1)) / ep->maxpacket;
24985 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24986 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24987 +                       }
24988 +                       if (!core_if->dma_desc_enable) {
24989 +                               ep->xfer_len =
24990 +                                       deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
24991 +                       }
24992 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24993 +               }
24994 +
24995 +               DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
24996 +                           ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
24997 +
24998 +               if (core_if->dma_enable) {
24999 +                       if (!core_if->dma_desc_enable) {
25000 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25001 +                                               deptsiz.d32);
25002 +
25003 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25004 +                                               (uint32_t) ep->dma_addr);
25005 +                       } else {
25006 +#ifdef DWC_UTE_CFI
25007 +                               /* The descriptor chain should be already initialized by now */
25008 +                               if (ep->buff_mode != BM_STANDARD) {
25009 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
25010 +                                                       ep->descs_dma_addr);
25011 +                               } else {
25012 +#endif
25013 +                                       /** This is used for interrupt out transfers*/
25014 +                                       if (!ep->xfer_len)
25015 +                                               ep->xfer_len = ep->total_len;
25016 +                                       init_dma_desc_chain(core_if, ep);
25017 +
25018 +                                       if (core_if->core_params->dev_out_nak) {
25019 +                                               if (ep->type == DWC_OTG_EP_TYPE_BULK) {
25020 +                                                       deptsiz.b.pktcnt = (ep->total_len +
25021 +                                                               (ep->maxpacket - 1)) / ep->maxpacket;
25022 +                                                       deptsiz.b.xfersize = ep->total_len;
25023 +                                                       /* Remember initial value of doeptsiz */
25024 +                                                       core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
25025 +                                                       DWC_WRITE_REG32(&out_regs->doeptsiz,
25026 +                                                               deptsiz.d32);
25027 +                                               }
25028 +                                       }
25029 +                               /** DOEPDMAn Register write */
25030 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
25031 +                                                       ep->dma_desc_addr);
25032 +#ifdef DWC_UTE_CFI
25033 +                               }
25034 +#endif
25035 +                       }
25036 +               } else {
25037 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25038 +               }
25039 +
25040 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
25041 +                       dsts_data_t dsts = {.d32 = 0};
25042 +                       if (ep->bInterval == 1) {
25043 +                               dsts.d32 =
25044 +                                   DWC_READ_REG32(&core_if->dev_if->
25045 +                                                  dev_global_regs->dsts);
25046 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
25047 +                               if (ep->frame_num > 0x3FFF) {
25048 +                                       ep->frm_overrun = 1;
25049 +                                       ep->frame_num &= 0x3FFF;
25050 +                               } else
25051 +                                       ep->frm_overrun = 0;
25052 +
25053 +                               if (ep->frame_num & 0x1) {
25054 +                                       depctl.b.setd1pid = 1;
25055 +                               } else {
25056 +                                       depctl.b.setd0pid = 1;
25057 +                               }
25058 +                       }
25059 +               }
25060 +
25061 +               /* EP enable */
25062 +               depctl.b.cnak = 1;
25063 +               depctl.b.epena = 1;
25064 +
25065 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25066 +
25067 +               DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
25068 +                           DWC_READ_REG32(&out_regs->doepctl),
25069 +                           DWC_READ_REG32(&out_regs->doeptsiz));
25070 +               DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
25071 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
25072 +                                          daintmsk),
25073 +                           DWC_READ_REG32(&core_if->core_global_regs->
25074 +                                          gintmsk));
25075 +
25076 +               /* Timer is scheduling only for out bulk transfers for
25077 +                * "Device DDMA OUT NAK Enhancement" feature to inform user
25078 +                * about received data payload in case of timeout
25079 +                */
25080 +               if (core_if->core_params->dev_out_nak) {
25081 +                       if (ep->type == DWC_OTG_EP_TYPE_BULK) {
25082 +                               core_if->ep_xfer_info[ep->num].core_if = core_if;
25083 +                               core_if->ep_xfer_info[ep->num].ep = ep;
25084 +                               core_if->ep_xfer_info[ep->num].state = 1;
25085 +
25086 +                               /* Start a timer for this transfer. */
25087 +                               DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);
25088 +                       }
25089 +               }
25090 +       }
25091 +}
25092 +
25093 +/**
25094 + * This function setup a zero length transfer in Buffer DMA and
25095 + * Slave modes for usb requests with zero field set
25096 + *
25097 + * @param core_if Programming view of DWC_otg controller.
25098 + * @param ep The EP to start the transfer on.
25099 + *
25100 + */
25101 +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25102 +{
25103 +
25104 +       depctl_data_t depctl;
25105 +       deptsiz_data_t deptsiz;
25106 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25107 +
25108 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
25109 +       DWC_PRINTF("zero length transfer is called\n");
25110 +
25111 +       /* IN endpoint */
25112 +       if (ep->is_in == 1) {
25113 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25114 +                   core_if->dev_if->in_ep_regs[ep->num];
25115 +
25116 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
25117 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
25118 +
25119 +               deptsiz.b.xfersize = 0;
25120 +               deptsiz.b.pktcnt = 1;
25121 +
25122 +               /* Write the DMA register */
25123 +               if (core_if->dma_enable) {
25124 +                       if (core_if->dma_desc_enable == 0) {
25125 +                               deptsiz.b.mc = 1;
25126 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25127 +                                               deptsiz.d32);
25128 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25129 +                                               (uint32_t) ep->dma_addr);
25130 +                       }
25131 +               } else {
25132 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25133 +                       /**
25134 +                        * Enable the Non-Periodic Tx FIFO empty interrupt,
25135 +                        * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
25136 +                        * the data will be written into the fifo by the ISR.
25137 +                        */
25138 +                       if (core_if->en_multiple_tx_fifo == 0) {
25139 +                               intr_mask.b.nptxfempty = 1;
25140 +                               DWC_MODIFY_REG32(&core_if->
25141 +                                                core_global_regs->gintmsk,
25142 +                                                intr_mask.d32, intr_mask.d32);
25143 +                       } else {
25144 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25145 +                               if (ep->xfer_len > 0) {
25146 +                                       uint32_t fifoemptymsk = 0;
25147 +                                       fifoemptymsk = 1 << ep->num;
25148 +                                       DWC_MODIFY_REG32(&core_if->
25149 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25150 +                                                        0, fifoemptymsk);
25151 +                               }
25152 +                       }
25153 +               }
25154 +
25155 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25156 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25157 +               /* EP enable, IN data in FIFO */
25158 +               depctl.b.cnak = 1;
25159 +               depctl.b.epena = 1;
25160 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25161 +
25162 +       } else {
25163 +               /* OUT endpoint */
25164 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25165 +                   core_if->dev_if->out_ep_regs[ep->num];
25166 +
25167 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
25168 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
25169 +
25170 +               /* Zero Length Packet */
25171 +               deptsiz.b.xfersize = ep->maxpacket;
25172 +               deptsiz.b.pktcnt = 1;
25173 +
25174 +               if (core_if->dma_enable) {
25175 +                       if (!core_if->dma_desc_enable) {
25176 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25177 +                                               deptsiz.d32);
25178 +
25179 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25180 +                                               (uint32_t) ep->dma_addr);
25181 +                       }
25182 +               } else {
25183 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25184 +               }
25185 +
25186 +               /* EP enable */
25187 +               depctl.b.cnak = 1;
25188 +               depctl.b.epena = 1;
25189 +
25190 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25191 +
25192 +       }
25193 +}
25194 +
25195 +/**
25196 + * This function does the setup for a data transfer for EP0 and starts
25197 + * the transfer.  For an IN transfer, the packets will be loaded into
25198 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
25199 + * unloaded from the Rx FIFO in the ISR.
25200 + *
25201 + * @param core_if Programming view of DWC_otg controller.
25202 + * @param ep The EP0 data.
25203 + */
25204 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25205 +{
25206 +       depctl_data_t depctl;
25207 +       deptsiz0_data_t deptsiz;
25208 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25209 +       dwc_otg_dev_dma_desc_t *dma_desc;
25210 +
25211 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
25212 +                   "xfer_buff=%p start_xfer_buff=%p \n",
25213 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
25214 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
25215 +
25216 +       ep->total_len = ep->xfer_len;
25217 +
25218 +       /* IN endpoint */
25219 +       if (ep->is_in == 1) {
25220 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25221 +                   core_if->dev_if->in_ep_regs[0];
25222 +
25223 +               gnptxsts_data_t gtxstatus;
25224 +
25225 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25226 +                       depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25227 +                       if (depctl.b.epena)
25228 +                               return;
25229 +               }
25230 +
25231 +               gtxstatus.d32 =
25232 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25233 +
25234 +               /* If dedicated FIFO every time flush fifo before enable ep*/
25235 +               if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)
25236 +                       dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
25237 +
25238 +               if (core_if->en_multiple_tx_fifo == 0
25239 +                   && gtxstatus.b.nptxqspcavail == 0
25240 +                   && !core_if->dma_enable) {
25241 +#ifdef DEBUG
25242 +                       deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25243 +                       DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
25244 +                                   DWC_READ_REG32(&in_regs->diepctl));
25245 +                       DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
25246 +                                   deptsiz.d32,
25247 +                                   deptsiz.b.xfersize, deptsiz.b.pktcnt);
25248 +                       DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
25249 +                                  gtxstatus.d32);
25250 +#endif
25251 +                       return;
25252 +               }
25253 +
25254 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25255 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25256 +
25257 +               /* Zero Length Packet? */
25258 +               if (ep->xfer_len == 0) {
25259 +                       deptsiz.b.xfersize = 0;
25260 +                       deptsiz.b.pktcnt = 1;
25261 +               } else {
25262 +                       /* Program the transfer size and packet count
25263 +                        *      as follows: xfersize = N * maxpacket +
25264 +                        *      short_packet pktcnt = N + (short_packet
25265 +                        *      exist ? 1 : 0)
25266 +                        */
25267 +                       if (ep->xfer_len > ep->maxpacket) {
25268 +                               ep->xfer_len = ep->maxpacket;
25269 +                               deptsiz.b.xfersize = ep->maxpacket;
25270 +                       } else {
25271 +                               deptsiz.b.xfersize = ep->xfer_len;
25272 +                       }
25273 +                       deptsiz.b.pktcnt = 1;
25274 +
25275 +               }
25276 +               DWC_DEBUGPL(DBG_PCDV,
25277 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25278 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25279 +                           deptsiz.d32);
25280 +
25281 +               /* Write the DMA register */
25282 +               if (core_if->dma_enable) {
25283 +                       if (core_if->dma_desc_enable == 0) {
25284 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25285 +                                               deptsiz.d32);
25286 +
25287 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25288 +                                               (uint32_t) ep->dma_addr);
25289 +                       } else {
25290 +                               dma_desc = core_if->dev_if->in_desc_addr;
25291 +
25292 +                               /** DMA Descriptor Setup */
25293 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25294 +                               dma_desc->status.b.l = 1;
25295 +                               dma_desc->status.b.ioc = 1;
25296 +                               dma_desc->status.b.sp =
25297 +                                   (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25298 +                               dma_desc->status.b.bytes = ep->xfer_len;
25299 +                               dma_desc->buf = ep->dma_addr;
25300 +                               dma_desc->status.b.sts = 0;
25301 +                               dma_desc->status.b.bs = BS_HOST_READY;
25302 +
25303 +                               /** DIEPDMA0 Register write */
25304 +                               DWC_WRITE_REG32(&in_regs->diepdma,
25305 +                                               core_if->
25306 +                                               dev_if->dma_in_desc_addr);
25307 +                       }
25308 +               } else {
25309 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25310 +               }
25311 +
25312 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25313 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25314 +               /* EP enable, IN data in FIFO */
25315 +               depctl.b.cnak = 1;
25316 +               depctl.b.epena = 1;
25317 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25318 +
25319 +               /**
25320 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25321 +                * data will be written into the fifo by the ISR.
25322 +                */
25323 +               if (!core_if->dma_enable) {
25324 +                       if (core_if->en_multiple_tx_fifo == 0) {
25325 +                               intr_mask.b.nptxfempty = 1;
25326 +                               DWC_MODIFY_REG32(&core_if->
25327 +                                                core_global_regs->gintmsk,
25328 +                                                intr_mask.d32, intr_mask.d32);
25329 +                       } else {
25330 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25331 +                               if (ep->xfer_len > 0) {
25332 +                                       uint32_t fifoemptymsk = 0;
25333 +                                       fifoemptymsk |= 1 << ep->num;
25334 +                                       DWC_MODIFY_REG32(&core_if->
25335 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25336 +                                                        0, fifoemptymsk);
25337 +                               }
25338 +                       }
25339 +               }
25340 +       } else {
25341 +               /* OUT endpoint */
25342 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25343 +                   core_if->dev_if->out_ep_regs[0];
25344 +
25345 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25346 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25347 +
25348 +               /* Program the transfer size and packet count as follows:
25349 +                *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))
25350 +                *      pktcnt = N                                                                                      */
25351 +               /* Zero Length Packet */
25352 +               deptsiz.b.xfersize = ep->maxpacket;
25353 +               deptsiz.b.pktcnt = 1;
25354 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
25355 +                       deptsiz.b.supcnt = 3;
25356 +
25357 +               DWC_DEBUGPL(DBG_PCDV, "len=%d  xfersize=%d pktcnt=%d\n",
25358 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
25359 +
25360 +               if (core_if->dma_enable) {
25361 +                       if (!core_if->dma_desc_enable) {
25362 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25363 +                                               deptsiz.d32);
25364 +
25365 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25366 +                                               (uint32_t) ep->dma_addr);
25367 +                       } else {
25368 +                               dma_desc = core_if->dev_if->out_desc_addr;
25369 +
25370 +                               /** DMA Descriptor Setup */
25371 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25372 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25373 +                                       dma_desc->status.b.mtrf = 0;
25374 +                                       dma_desc->status.b.sr = 0;
25375 +                               }
25376 +                               dma_desc->status.b.l = 1;
25377 +                               dma_desc->status.b.ioc = 1;
25378 +                               dma_desc->status.b.bytes = ep->maxpacket;
25379 +                               dma_desc->buf = ep->dma_addr;
25380 +                               dma_desc->status.b.sts = 0;
25381 +                               dma_desc->status.b.bs = BS_HOST_READY;
25382 +
25383 +                               /** DOEPDMA0 Register write */
25384 +                               DWC_WRITE_REG32(&out_regs->doepdma,
25385 +                                               core_if->dev_if->
25386 +                                               dma_out_desc_addr);
25387 +                       }
25388 +               } else {
25389 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25390 +               }
25391 +
25392 +               /* EP enable */
25393 +               depctl.b.cnak = 1;
25394 +               depctl.b.epena = 1;
25395 +               DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
25396 +       }
25397 +}
25398 +
25399 +/**
25400 + * This function continues control IN transfers started by
25401 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
25402 + * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
25403 + * bit for the packet count.
25404 + *
25405 + * @param core_if Programming view of DWC_otg controller.
25406 + * @param ep The EP0 data.
25407 + */
25408 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25409 +{
25410 +       depctl_data_t depctl;
25411 +       deptsiz0_data_t deptsiz;
25412 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25413 +       dwc_otg_dev_dma_desc_t *dma_desc;
25414 +
25415 +       if (ep->is_in == 1) {
25416 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25417 +                   core_if->dev_if->in_ep_regs[0];
25418 +               gnptxsts_data_t tx_status = {.d32 = 0 };
25419 +
25420 +               tx_status.d32 =
25421 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25422 +               /** @todo Should there be check for room in the Tx
25423 +                * Status Queue.  If not remove the code above this comment. */
25424 +
25425 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25426 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25427 +
25428 +               /* Program the transfer size and packet count
25429 +                *      as follows: xfersize = N * maxpacket +
25430 +                *      short_packet pktcnt = N + (short_packet
25431 +                *      exist ? 1 : 0)
25432 +                */
25433 +
25434 +               if (core_if->dma_desc_enable == 0) {
25435 +                       deptsiz.b.xfersize =
25436 +                           (ep->total_len - ep->xfer_count) >
25437 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25438 +                                                            ep->xfer_count);
25439 +                       deptsiz.b.pktcnt = 1;
25440 +                       if (core_if->dma_enable == 0) {
25441 +                               ep->xfer_len += deptsiz.b.xfersize;
25442 +                       } else {
25443 +                               ep->xfer_len = deptsiz.b.xfersize;
25444 +                       }
25445 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25446 +               } else {
25447 +                       ep->xfer_len =
25448 +                           (ep->total_len - ep->xfer_count) >
25449 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25450 +                                                            ep->xfer_count);
25451 +
25452 +                       dma_desc = core_if->dev_if->in_desc_addr;
25453 +
25454 +                       /** DMA Descriptor Setup */
25455 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25456 +                       dma_desc->status.b.l = 1;
25457 +                       dma_desc->status.b.ioc = 1;
25458 +                       dma_desc->status.b.sp =
25459 +                           (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25460 +                       dma_desc->status.b.bytes = ep->xfer_len;
25461 +                       dma_desc->buf = ep->dma_addr;
25462 +                       dma_desc->status.b.sts = 0;
25463 +                       dma_desc->status.b.bs = BS_HOST_READY;
25464 +
25465 +                       /** DIEPDMA0 Register write */
25466 +                       DWC_WRITE_REG32(&in_regs->diepdma,
25467 +                                       core_if->dev_if->dma_in_desc_addr);
25468 +               }
25469 +
25470 +               DWC_DEBUGPL(DBG_PCDV,
25471 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25472 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25473 +                           deptsiz.d32);
25474 +
25475 +               /* Write the DMA register */
25476 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25477 +                       if (core_if->dma_desc_enable == 0)
25478 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25479 +                                               (uint32_t) ep->dma_addr);
25480 +               }
25481 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25482 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25483 +               /* EP enable, IN data in FIFO */
25484 +               depctl.b.cnak = 1;
25485 +               depctl.b.epena = 1;
25486 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25487 +
25488 +               /**
25489 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25490 +                * data will be written into the fifo by the ISR.
25491 +                */
25492 +               if (!core_if->dma_enable) {
25493 +                       if (core_if->en_multiple_tx_fifo == 0) {
25494 +                               /* First clear it from GINTSTS */
25495 +                               intr_mask.b.nptxfempty = 1;
25496 +                               DWC_MODIFY_REG32(&core_if->
25497 +                                                core_global_regs->gintmsk,
25498 +                                                intr_mask.d32, intr_mask.d32);
25499 +
25500 +                       } else {
25501 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25502 +                               if (ep->xfer_len > 0) {
25503 +                                       uint32_t fifoemptymsk = 0;
25504 +                                       fifoemptymsk |= 1 << ep->num;
25505 +                                       DWC_MODIFY_REG32(&core_if->
25506 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25507 +                                                        0, fifoemptymsk);
25508 +                               }
25509 +                       }
25510 +               }
25511 +       } else {
25512 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25513 +                   core_if->dev_if->out_ep_regs[0];
25514 +
25515 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25516 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25517 +
25518 +               /* Program the transfer size and packet count
25519 +                *      as follows: xfersize = N * maxpacket +
25520 +                *      short_packet pktcnt = N + (short_packet
25521 +                *      exist ? 1 : 0)
25522 +                */
25523 +               deptsiz.b.xfersize = ep->maxpacket;
25524 +               deptsiz.b.pktcnt = 1;
25525 +
25526 +               if (core_if->dma_desc_enable == 0) {
25527 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25528 +               } else {
25529 +                       dma_desc = core_if->dev_if->out_desc_addr;
25530 +
25531 +                       /** DMA Descriptor Setup */
25532 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25533 +                       dma_desc->status.b.l = 1;
25534 +                       dma_desc->status.b.ioc = 1;
25535 +                       dma_desc->status.b.bytes = ep->maxpacket;
25536 +                       dma_desc->buf = ep->dma_addr;
25537 +                       dma_desc->status.b.sts = 0;
25538 +                       dma_desc->status.b.bs = BS_HOST_READY;
25539 +
25540 +                       /** DOEPDMA0 Register write */
25541 +                       DWC_WRITE_REG32(&out_regs->doepdma,
25542 +                                       core_if->dev_if->dma_out_desc_addr);
25543 +               }
25544 +
25545 +               DWC_DEBUGPL(DBG_PCDV,
25546 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25547 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25548 +                           deptsiz.d32);
25549 +
25550 +               /* Write the DMA register */
25551 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25552 +                       if (core_if->dma_desc_enable == 0)
25553 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25554 +                                               (uint32_t) ep->dma_addr);
25555 +
25556 +               }
25557 +
25558 +               /* EP enable, IN data in FIFO */
25559 +               depctl.b.cnak = 1;
25560 +               depctl.b.epena = 1;
25561 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25562 +
25563 +       }
25564 +}
25565 +
25566 +#ifdef DEBUG
25567 +void dump_msg(const u8 * buf, unsigned int length)
25568 +{
25569 +       unsigned int start, num, i;
25570 +       char line[52], *p;
25571 +
25572 +       if (length >= 512)
25573 +               return;
25574 +       start = 0;
25575 +       while (length > 0) {
25576 +               num = length < 16u ? length : 16u;
25577 +               p = line;
25578 +               for (i = 0; i < num; ++i) {
25579 +                       if (i == 8)
25580 +                               *p++ = ' ';
25581 +                       DWC_SPRINTF(p, " %02x", buf[i]);
25582 +                       p += 3;
25583 +               }
25584 +               *p = 0;
25585 +               DWC_PRINTF("%6x: %s\n", start, line);
25586 +               buf += num;
25587 +               start += num;
25588 +               length -= num;
25589 +       }
25590 +}
25591 +#else
25592 +static inline void dump_msg(const u8 * buf, unsigned int length)
25593 +{
25594 +}
25595 +#endif
25596 +
25597 +/**
25598 + * This function writes a packet into the Tx FIFO associated with the
25599 + * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For
25600 + * periodic EPs the periodic Tx FIFO associated with the EP is written
25601 + * with all packets for the next micro-frame.
25602 + *
25603 + * @param core_if Programming view of DWC_otg controller.
25604 + * @param ep The EP to write packet for.
25605 + * @param dma Indicates if DMA is being used.
25606 + */
25607 +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
25608 +                            int dma)
25609 +{
25610 +       /**
25611 +        * The buffer is padded to DWORD on a per packet basis in
25612 +        * slave/dma mode if the MPS is not DWORD aligned. The last
25613 +        * packet, if short, is also padded to a multiple of DWORD.
25614 +        *
25615 +        * ep->xfer_buff always starts DWORD aligned in memory and is a
25616 +        * multiple of DWORD in length
25617 +        *
25618 +        * ep->xfer_len can be any number of bytes
25619 +        *
25620 +        * ep->xfer_count is a multiple of ep->maxpacket until the last
25621 +        *      packet
25622 +        *
25623 +        * FIFO access is DWORD */
25624 +
25625 +       uint32_t i;
25626 +       uint32_t byte_count;
25627 +       uint32_t dword_count;
25628 +       uint32_t *fifo;
25629 +       uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
25630 +
25631 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
25632 +                   ep);
25633 +       if (ep->xfer_count >= ep->xfer_len) {
25634 +               DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
25635 +               return;
25636 +       }
25637 +
25638 +       /* Find the byte length of the packet either short packet or MPS */
25639 +       if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
25640 +               byte_count = ep->xfer_len - ep->xfer_count;
25641 +       } else {
25642 +               byte_count = ep->maxpacket;
25643 +       }
25644 +
25645 +       /* Find the DWORD length, padded by extra bytes as neccessary if MPS
25646 +        * is not a multiple of DWORD */
25647 +       dword_count = (byte_count + 3) / 4;
25648 +
25649 +#ifdef VERBOSE
25650 +       dump_msg(ep->xfer_buff, byte_count);
25651 +#endif
25652 +
25653 +       /**@todo NGS Where are the Periodic Tx FIFO addresses
25654 +        * intialized?  What should this be? */
25655 +
25656 +       fifo = core_if->data_fifo[ep->num];
25657 +
25658 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
25659 +                   fifo, data_buff, *data_buff, byte_count);
25660 +
25661 +       if (!dma) {
25662 +               for (i = 0; i < dword_count; i++, data_buff++) {
25663 +                       DWC_WRITE_REG32(fifo, *data_buff);
25664 +               }
25665 +       }
25666 +
25667 +       ep->xfer_count += byte_count;
25668 +       ep->xfer_buff += byte_count;
25669 +       ep->dma_addr += byte_count;
25670 +}
25671 +
25672 +/**
25673 + * Set the EP STALL.
25674 + *
25675 + * @param core_if Programming view of DWC_otg controller.
25676 + * @param ep The EP to set the stall on.
25677 + */
25678 +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25679 +{
25680 +       depctl_data_t depctl;
25681 +       volatile uint32_t *depctl_addr;
25682 +
25683 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25684 +                   (ep->is_in ? "IN" : "OUT"));
25685 +
25686 +       if (ep->is_in == 1) {
25687 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25688 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25689 +
25690 +               /* set the disable and stall bits */
25691 +               if (depctl.b.epena) {
25692 +                       depctl.b.epdis = 1;
25693 +               }
25694 +               depctl.b.stall = 1;
25695 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25696 +       } else {
25697 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25698 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25699 +
25700 +               /* set the stall bit */
25701 +               depctl.b.stall = 1;
25702 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25703 +       }
25704 +
25705 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25706 +
25707 +       return;
25708 +}
25709 +
25710 +/**
25711 + * Clear the EP STALL.
25712 + *
25713 + * @param core_if Programming view of DWC_otg controller.
25714 + * @param ep The EP to clear stall from.
25715 + */
25716 +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25717 +{
25718 +       depctl_data_t depctl;
25719 +       volatile uint32_t *depctl_addr;
25720 +
25721 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25722 +                   (ep->is_in ? "IN" : "OUT"));
25723 +
25724 +       if (ep->is_in == 1) {
25725 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25726 +       } else {
25727 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25728 +       }
25729 +
25730 +       depctl.d32 = DWC_READ_REG32(depctl_addr);
25731 +
25732 +       /* clear the stall bits */
25733 +       depctl.b.stall = 0;
25734 +
25735 +       /*
25736 +        * USB Spec 9.4.5: For endpoints using data toggle, regardless
25737 +        * of whether an endpoint has the Halt feature set, a
25738 +        * ClearFeature(ENDPOINT_HALT) request always results in the
25739 +        * data toggle being reinitialized to DATA0.
25740 +        */
25741 +       if (ep->type == DWC_OTG_EP_TYPE_INTR ||
25742 +           ep->type == DWC_OTG_EP_TYPE_BULK) {
25743 +               depctl.b.setd0pid = 1;  /* DATA0 */
25744 +       }
25745 +
25746 +       DWC_WRITE_REG32(depctl_addr, depctl.d32);
25747 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25748 +       return;
25749 +}
25750 +
25751 +/**
25752 + * This function reads a packet from the Rx FIFO into the destination
25753 + * buffer. To read SETUP data use dwc_otg_read_setup_packet.
25754 + *
25755 + * @param core_if Programming view of DWC_otg controller.
25756 + * @param dest   Destination buffer for the packet.
25757 + * @param bytes  Number of bytes to copy to the destination.
25758 + */
25759 +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
25760 +                        uint8_t * dest, uint16_t bytes)
25761 +{
25762 +       int i;
25763 +       int word_count = (bytes + 3) / 4;
25764 +
25765 +       volatile uint32_t *fifo = core_if->data_fifo[0];
25766 +       uint32_t *data_buff = (uint32_t *) dest;
25767 +
25768 +       /**
25769 +        * @todo Account for the case where _dest is not dword aligned. This
25770 +        * requires reading data from the FIFO into a uint32_t temp buffer,
25771 +        * then moving it into the data buffer.
25772 +        */
25773 +
25774 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
25775 +                   core_if, dest, bytes);
25776 +
25777 +       for (i = 0; i < word_count; i++, data_buff++) {
25778 +               *data_buff = DWC_READ_REG32(fifo);
25779 +       }
25780 +
25781 +       return;
25782 +}
25783 +
25784 +/**
25785 + * This functions reads the device registers and prints them
25786 + *
25787 + * @param core_if Programming view of DWC_otg controller.
25788 + */
25789 +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
25790 +{
25791 +       int i;
25792 +       volatile uint32_t *addr;
25793 +
25794 +       DWC_PRINTF("Device Global Registers\n");
25795 +       addr = &core_if->dev_if->dev_global_regs->dcfg;
25796 +       DWC_PRINTF("DCFG                 @0x%08lX : 0x%08X\n",
25797 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25798 +       addr = &core_if->dev_if->dev_global_regs->dctl;
25799 +       DWC_PRINTF("DCTL                 @0x%08lX : 0x%08X\n",
25800 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25801 +       addr = &core_if->dev_if->dev_global_regs->dsts;
25802 +       DWC_PRINTF("DSTS                 @0x%08lX : 0x%08X\n",
25803 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25804 +       addr = &core_if->dev_if->dev_global_regs->diepmsk;
25805 +       DWC_PRINTF("DIEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25806 +                  DWC_READ_REG32(addr));
25807 +       addr = &core_if->dev_if->dev_global_regs->doepmsk;
25808 +       DWC_PRINTF("DOEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25809 +                  DWC_READ_REG32(addr));
25810 +       addr = &core_if->dev_if->dev_global_regs->daint;
25811 +       DWC_PRINTF("DAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25812 +                  DWC_READ_REG32(addr));
25813 +       addr = &core_if->dev_if->dev_global_regs->daintmsk;
25814 +       DWC_PRINTF("DAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25815 +                  DWC_READ_REG32(addr));
25816 +       addr = &core_if->dev_if->dev_global_regs->dtknqr1;
25817 +       DWC_PRINTF("DTKNQR1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25818 +                  DWC_READ_REG32(addr));
25819 +       if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
25820 +               addr = &core_if->dev_if->dev_global_regs->dtknqr2;
25821 +               DWC_PRINTF("DTKNQR2      @0x%08lX : 0x%08X\n",
25822 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25823 +       }
25824 +
25825 +       addr = &core_if->dev_if->dev_global_regs->dvbusdis;
25826 +       DWC_PRINTF("DVBUSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25827 +                  DWC_READ_REG32(addr));
25828 +
25829 +       addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
25830 +       DWC_PRINTF("DVBUSPULSE  @0x%08lX : 0x%08X\n",
25831 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25832 +
25833 +       addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
25834 +       DWC_PRINTF("DTKNQR3_DTHRCTL      @0x%08lX : 0x%08X\n",
25835 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25836 +
25837 +       if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
25838 +               addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25839 +               DWC_PRINTF("DTKNQR4      @0x%08lX : 0x%08X\n",
25840 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25841 +       }
25842 +
25843 +       addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25844 +       DWC_PRINTF("FIFOEMPMSK   @0x%08lX : 0x%08X\n", (unsigned long)addr,
25845 +                  DWC_READ_REG32(addr));
25846 +
25847 +       if (core_if->hwcfg2.b.multi_proc_int) {
25848 +
25849 +               addr = &core_if->dev_if->dev_global_regs->deachint;
25850 +               DWC_PRINTF("DEACHINT     @0x%08lX : 0x%08X\n",
25851 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25852 +               addr = &core_if->dev_if->dev_global_regs->deachintmsk;
25853 +               DWC_PRINTF("DEACHINTMSK  @0x%08lX : 0x%08X\n",
25854 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25855 +
25856 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25857 +                       addr =
25858 +                           &core_if->dev_if->
25859 +                           dev_global_regs->diepeachintmsk[i];
25860 +                       DWC_PRINTF("DIEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25861 +                                  i, (unsigned long)addr,
25862 +                                  DWC_READ_REG32(addr));
25863 +               }
25864 +
25865 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25866 +                       addr =
25867 +                           &core_if->dev_if->
25868 +                           dev_global_regs->doepeachintmsk[i];
25869 +                       DWC_PRINTF("DOEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25870 +                                  i, (unsigned long)addr,
25871 +                                  DWC_READ_REG32(addr));
25872 +               }
25873 +       }
25874 +
25875 +       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25876 +               DWC_PRINTF("Device IN EP %d Registers\n", i);
25877 +               addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
25878 +               DWC_PRINTF("DIEPCTL      @0x%08lX : 0x%08X\n",
25879 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25880 +               addr = &core_if->dev_if->in_ep_regs[i]->diepint;
25881 +               DWC_PRINTF("DIEPINT      @0x%08lX : 0x%08X\n",
25882 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25883 +               addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
25884 +               DWC_PRINTF("DIETSIZ      @0x%08lX : 0x%08X\n",
25885 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25886 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
25887 +               DWC_PRINTF("DIEPDMA      @0x%08lX : 0x%08X\n",
25888 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25889 +               addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
25890 +               DWC_PRINTF("DTXFSTS      @0x%08lX : 0x%08X\n",
25891 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25892 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
25893 +               DWC_PRINTF("DIEPDMAB     @0x%08lX : 0x%08X\n",
25894 +                          (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );
25895 +       }
25896 +
25897 +       for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25898 +               DWC_PRINTF("Device OUT EP %d Registers\n", i);
25899 +               addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
25900 +               DWC_PRINTF("DOEPCTL      @0x%08lX : 0x%08X\n",
25901 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25902 +               addr = &core_if->dev_if->out_ep_regs[i]->doepint;
25903 +               DWC_PRINTF("DOEPINT      @0x%08lX : 0x%08X\n",
25904 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25905 +               addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
25906 +               DWC_PRINTF("DOETSIZ      @0x%08lX : 0x%08X\n",
25907 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25908 +               addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
25909 +               DWC_PRINTF("DOEPDMA      @0x%08lX : 0x%08X\n",
25910 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25911 +               if (core_if->dma_enable) {      /* Don't access this register in SLAVE mode */
25912 +                       addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
25913 +                       DWC_PRINTF("DOEPDMAB     @0x%08lX : 0x%08X\n",
25914 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
25915 +               }
25916 +
25917 +       }
25918 +}
25919 +
25920 +/**
25921 + * This functions reads the SPRAM and prints its content
25922 + *
25923 + * @param core_if Programming view of DWC_otg controller.
25924 + */
25925 +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
25926 +{
25927 +       volatile uint8_t *addr, *start_addr, *end_addr;
25928 +
25929 +       DWC_PRINTF("SPRAM Data:\n");
25930 +       start_addr = (void *)core_if->core_global_regs;
25931 +       DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);
25932 +       start_addr += 0x00028000;
25933 +       end_addr = (void *)core_if->core_global_regs;
25934 +       end_addr += 0x000280e0;
25935 +
25936 +       for (addr = start_addr; addr < end_addr; addr += 16) {
25937 +               DWC_PRINTF
25938 +                   ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
25939 +                    (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],
25940 +                    addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
25941 +                    addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
25942 +                   );
25943 +       }
25944 +
25945 +       return;
25946 +}
25947 +
25948 +/**
25949 + * This function reads the host registers and prints them
25950 + *
25951 + * @param core_if Programming view of DWC_otg controller.
25952 + */
25953 +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
25954 +{
25955 +       int i;
25956 +       volatile uint32_t *addr;
25957 +
25958 +       DWC_PRINTF("Host Global Registers\n");
25959 +       addr = &core_if->host_if->host_global_regs->hcfg;
25960 +       DWC_PRINTF("HCFG                 @0x%08lX : 0x%08X\n",
25961 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25962 +       addr = &core_if->host_if->host_global_regs->hfir;
25963 +       DWC_PRINTF("HFIR                 @0x%08lX : 0x%08X\n",
25964 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25965 +       addr = &core_if->host_if->host_global_regs->hfnum;
25966 +       DWC_PRINTF("HFNUM        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25967 +                  DWC_READ_REG32(addr));
25968 +       addr = &core_if->host_if->host_global_regs->hptxsts;
25969 +       DWC_PRINTF("HPTXSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25970 +                  DWC_READ_REG32(addr));
25971 +       addr = &core_if->host_if->host_global_regs->haint;
25972 +       DWC_PRINTF("HAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25973 +                  DWC_READ_REG32(addr));
25974 +       addr = &core_if->host_if->host_global_regs->haintmsk;
25975 +       DWC_PRINTF("HAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25976 +                  DWC_READ_REG32(addr));
25977 +       if (core_if->dma_desc_enable) {
25978 +               addr = &core_if->host_if->host_global_regs->hflbaddr;
25979 +               DWC_PRINTF("HFLBADDR     @0x%08lX : 0x%08X\n",
25980 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25981 +       }
25982 +
25983 +       addr = core_if->host_if->hprt0;
25984 +       DWC_PRINTF("HPRT0        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25985 +                  DWC_READ_REG32(addr));
25986 +
25987 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
25988 +               DWC_PRINTF("Host Channel %d Specific Registers\n", i);
25989 +               addr = &core_if->host_if->hc_regs[i]->hcchar;
25990 +               DWC_PRINTF("HCCHAR       @0x%08lX : 0x%08X\n",
25991 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25992 +               addr = &core_if->host_if->hc_regs[i]->hcsplt;
25993 +               DWC_PRINTF("HCSPLT       @0x%08lX : 0x%08X\n",
25994 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25995 +               addr = &core_if->host_if->hc_regs[i]->hcint;
25996 +               DWC_PRINTF("HCINT        @0x%08lX : 0x%08X\n",
25997 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25998 +               addr = &core_if->host_if->hc_regs[i]->hcintmsk;
25999 +               DWC_PRINTF("HCINTMSK     @0x%08lX : 0x%08X\n",
26000 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26001 +               addr = &core_if->host_if->hc_regs[i]->hctsiz;
26002 +               DWC_PRINTF("HCTSIZ       @0x%08lX : 0x%08X\n",
26003 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26004 +               addr = &core_if->host_if->hc_regs[i]->hcdma;
26005 +               DWC_PRINTF("HCDMA        @0x%08lX : 0x%08X\n",
26006 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26007 +               if (core_if->dma_desc_enable) {
26008 +                       addr = &core_if->host_if->hc_regs[i]->hcdmab;
26009 +                       DWC_PRINTF("HCDMAB       @0x%08lX : 0x%08X\n",
26010 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
26011 +               }
26012 +
26013 +       }
26014 +       return;
26015 +}
26016 +
26017 +/**
26018 + * This function reads the core global registers and prints them
26019 + *
26020 + * @param core_if Programming view of DWC_otg controller.
26021 + */
26022 +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
26023 +{
26024 +       int i, ep_num;
26025 +       volatile uint32_t *addr;
26026 +       char *txfsiz;
26027 +
26028 +       DWC_PRINTF("Core Global Registers\n");
26029 +       addr = &core_if->core_global_regs->gotgctl;
26030 +       DWC_PRINTF("GOTGCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26031 +                  DWC_READ_REG32(addr));
26032 +       addr = &core_if->core_global_regs->gotgint;
26033 +       DWC_PRINTF("GOTGINT      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26034 +                  DWC_READ_REG32(addr));
26035 +       addr = &core_if->core_global_regs->gahbcfg;
26036 +       DWC_PRINTF("GAHBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26037 +                  DWC_READ_REG32(addr));
26038 +       addr = &core_if->core_global_regs->gusbcfg;
26039 +       DWC_PRINTF("GUSBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26040 +                  DWC_READ_REG32(addr));
26041 +       addr = &core_if->core_global_regs->grstctl;
26042 +       DWC_PRINTF("GRSTCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26043 +                  DWC_READ_REG32(addr));
26044 +       addr = &core_if->core_global_regs->gintsts;
26045 +       DWC_PRINTF("GINTSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26046 +                  DWC_READ_REG32(addr));
26047 +       addr = &core_if->core_global_regs->gintmsk;
26048 +       DWC_PRINTF("GINTMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26049 +                  DWC_READ_REG32(addr));
26050 +       addr = &core_if->core_global_regs->grxstsr;
26051 +       DWC_PRINTF("GRXSTSR      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26052 +                  DWC_READ_REG32(addr));
26053 +       addr = &core_if->core_global_regs->grxfsiz;
26054 +       DWC_PRINTF("GRXFSIZ      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26055 +                  DWC_READ_REG32(addr));
26056 +       addr = &core_if->core_global_regs->gnptxfsiz;
26057 +       DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
26058 +                  DWC_READ_REG32(addr));
26059 +       addr = &core_if->core_global_regs->gnptxsts;
26060 +       DWC_PRINTF("GNPTXSTS     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26061 +                  DWC_READ_REG32(addr));
26062 +       addr = &core_if->core_global_regs->gi2cctl;
26063 +       DWC_PRINTF("GI2CCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26064 +                  DWC_READ_REG32(addr));
26065 +       addr = &core_if->core_global_regs->gpvndctl;
26066 +       DWC_PRINTF("GPVNDCTL     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26067 +                  DWC_READ_REG32(addr));
26068 +       addr = &core_if->core_global_regs->ggpio;
26069 +       DWC_PRINTF("GGPIO        @0x%08lX : 0x%08X\n", (unsigned long)addr,
26070 +                  DWC_READ_REG32(addr));
26071 +       addr = &core_if->core_global_regs->guid;
26072 +       DWC_PRINTF("GUID                 @0x%08lX : 0x%08X\n",
26073 +                  (unsigned long)addr, DWC_READ_REG32(addr));
26074 +       addr = &core_if->core_global_regs->gsnpsid;
26075 +       DWC_PRINTF("GSNPSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26076 +                  DWC_READ_REG32(addr));
26077 +       addr = &core_if->core_global_regs->ghwcfg1;
26078 +       DWC_PRINTF("GHWCFG1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26079 +                  DWC_READ_REG32(addr));
26080 +       addr = &core_if->core_global_regs->ghwcfg2;
26081 +       DWC_PRINTF("GHWCFG2      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26082 +                  DWC_READ_REG32(addr));
26083 +       addr = &core_if->core_global_regs->ghwcfg3;
26084 +       DWC_PRINTF("GHWCFG3      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26085 +                  DWC_READ_REG32(addr));
26086 +       addr = &core_if->core_global_regs->ghwcfg4;
26087 +       DWC_PRINTF("GHWCFG4      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26088 +                  DWC_READ_REG32(addr));
26089 +       addr = &core_if->core_global_regs->glpmcfg;
26090 +       DWC_PRINTF("GLPMCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26091 +                  DWC_READ_REG32(addr));
26092 +       addr = &core_if->core_global_regs->gpwrdn;
26093 +       DWC_PRINTF("GPWRDN       @0x%08lX : 0x%08X\n", (unsigned long)addr,
26094 +                  DWC_READ_REG32(addr));
26095 +       addr = &core_if->core_global_regs->gdfifocfg;
26096 +       DWC_PRINTF("GDFIFOCFG    @0x%08lX : 0x%08X\n", (unsigned long)addr,
26097 +                  DWC_READ_REG32(addr));
26098 +       addr = &core_if->core_global_regs->adpctl;
26099 +       DWC_PRINTF("ADPCTL       @0x%08lX : 0x%08X\n", (unsigned long)addr,
26100 +                  dwc_otg_adp_read_reg(core_if));
26101 +       addr = &core_if->core_global_regs->hptxfsiz;
26102 +       DWC_PRINTF("HPTXFSIZ     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26103 +                  DWC_READ_REG32(addr));
26104 +
26105 +       if (core_if->en_multiple_tx_fifo == 0) {
26106 +               ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;
26107 +               txfsiz = "DPTXFSIZ";
26108 +       } else {
26109 +               ep_num = core_if->hwcfg4.b.num_in_eps;
26110 +               txfsiz = "DIENPTXF";
26111 +       }
26112 +       for (i = 0; i < ep_num; i++) {
26113 +               addr = &core_if->core_global_regs->dtxfsiz[i];
26114 +               DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
26115 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26116 +       }
26117 +       addr = core_if->pcgcctl;
26118 +       DWC_PRINTF("PCGCCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26119 +                  DWC_READ_REG32(addr));
26120 +}
26121 +
26122 +/**
26123 + * Flush a Tx FIFO.
26124 + *
26125 + * @param core_if Programming view of DWC_otg controller.
26126 + * @param num Tx FIFO to flush.
26127 + */
26128 +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
26129 +{
26130 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26131 +       volatile grstctl_t greset = {.d32 = 0 };
26132 +       int count = 0;
26133 +
26134 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
26135 +
26136 +       greset.b.txfflsh = 1;
26137 +       greset.b.txfnum = num;
26138 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26139 +
26140 +       do {
26141 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26142 +               if (++count > 10000) {
26143 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
26144 +                                __func__, greset.d32,
26145 +                                DWC_READ_REG32(&global_regs->gnptxsts));
26146 +                       break;
26147 +               }
26148 +               dwc_udelay(1);
26149 +       } while (greset.b.txfflsh == 1);
26150 +
26151 +       /* Wait for 3 PHY Clocks */
26152 +       dwc_udelay(1);
26153 +}
26154 +
26155 +/**
26156 + * Flush Rx FIFO.
26157 + *
26158 + * @param core_if Programming view of DWC_otg controller.
26159 + */
26160 +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
26161 +{
26162 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26163 +       volatile grstctl_t greset = {.d32 = 0 };
26164 +       int count = 0;
26165 +
26166 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
26167 +       /*
26168 +        *
26169 +        */
26170 +       greset.b.rxfflsh = 1;
26171 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26172 +
26173 +       do {
26174 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26175 +               if (++count > 10000) {
26176 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
26177 +                                greset.d32);
26178 +                       break;
26179 +               }
26180 +               dwc_udelay(1);
26181 +       } while (greset.b.rxfflsh == 1);
26182 +
26183 +       /* Wait for 3 PHY Clocks */
26184 +       dwc_udelay(1);
26185 +}
26186 +
26187 +/**
26188 + * Do core a soft reset of the core.  Be careful with this because it
26189 + * resets all the internal state machines of the core.
26190 + */
26191 +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
26192 +{
26193 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26194 +       volatile grstctl_t greset = {.d32 = 0 };
26195 +       int count = 0;
26196 +
26197 +       DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
26198 +       /* Wait for AHB master IDLE state. */
26199 +       do {
26200 +               dwc_udelay(10);
26201 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26202 +               if (++count > 100000) {
26203 +                       DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
26204 +                                greset.d32);
26205 +                       return;
26206 +               }
26207 +       }
26208 +       while (greset.b.ahbidle == 0);
26209 +
26210 +       /* Core Soft Reset */
26211 +       count = 0;
26212 +       greset.b.csftrst = 1;
26213 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26214 +       do {
26215 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26216 +               if (++count > 10000) {
26217 +                       DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
26218 +                                __func__, greset.d32);
26219 +                       break;
26220 +               }
26221 +               dwc_udelay(1);
26222 +       }
26223 +       while (greset.b.csftrst == 1);
26224 +
26225 +       /* Wait for 3 PHY Clocks */
26226 +       dwc_mdelay(100);
26227 +}
26228 +
26229 +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
26230 +{
26231 +       return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
26232 +}
26233 +
26234 +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
26235 +{
26236 +       return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
26237 +}
26238 +
26239 +/**
26240 + * Register HCD callbacks. The callbacks are used to start and stop
26241 + * the HCD for interrupt processing.
26242 + *
26243 + * @param core_if Programming view of DWC_otg controller.
26244 + * @param cb the HCD callback structure.
26245 + * @param p pointer to be passed to callback function (usb_hcd*).
26246 + */
26247 +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
26248 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26249 +{
26250 +       core_if->hcd_cb = cb;
26251 +       cb->p = p;
26252 +}
26253 +
26254 +/**
26255 + * Register PCD callbacks. The callbacks are used to start and stop
26256 + * the PCD for interrupt processing.
26257 + *
26258 + * @param core_if Programming view of DWC_otg controller.
26259 + * @param cb the PCD callback structure.
26260 + * @param p pointer to be passed to callback function (pcd*).
26261 + */
26262 +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
26263 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26264 +{
26265 +       core_if->pcd_cb = cb;
26266 +       cb->p = p;
26267 +}
26268 +
26269 +#ifdef DWC_EN_ISOC
26270 +
26271 +/**
26272 + * This function writes isoc data per 1 (micro)frame into tx fifo
26273 + *
26274 + * @param core_if Programming view of DWC_otg controller.
26275 + * @param ep The EP to start the transfer on.
26276 + *
26277 + */
26278 +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
26279 +{
26280 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
26281 +       dtxfsts_data_t txstatus = {.d32 = 0 };
26282 +       uint32_t len = 0;
26283 +       uint32_t dwords;
26284 +
26285 +       ep->xfer_len = ep->data_per_frame;
26286 +       ep->xfer_count = 0;
26287 +
26288 +       ep_regs = core_if->dev_if->in_ep_regs[ep->num];
26289 +
26290 +       len = ep->xfer_len - ep->xfer_count;
26291 +
26292 +       if (len > ep->maxpacket) {
26293 +               len = ep->maxpacket;
26294 +       }
26295 +
26296 +       dwords = (len + 3) / 4;
26297 +
26298 +       /* While there is space in the queue and space in the FIFO and
26299 +        * More data to tranfer, Write packets to the Tx FIFO */
26300 +       txstatus.d32 =
26301 +           DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
26302 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
26303 +
26304 +       while (txstatus.b.txfspcavail > dwords &&
26305 +              ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
26306 +               /* Write the FIFO */
26307 +               dwc_otg_ep_write_packet(core_if, ep, 0);
26308 +
26309 +               len = ep->xfer_len - ep->xfer_count;
26310 +               if (len > ep->maxpacket) {
26311 +                       len = ep->maxpacket;
26312 +               }
26313 +
26314 +               dwords = (len + 3) / 4;
26315 +               txstatus.d32 =
26316 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
26317 +                                  dtxfsts);
26318 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
26319 +                           txstatus.d32);
26320 +       }
26321 +}
26322 +
26323 +/**
26324 + * This function initializes a descriptor chain for Isochronous transfer
26325 + *
26326 + * @param core_if Programming view of DWC_otg controller.
26327 + * @param ep The EP to start the transfer on.
26328 + *
26329 + */
26330 +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
26331 +                                      dwc_ep_t * ep)
26332 +{
26333 +       deptsiz_data_t deptsiz = {.d32 = 0 };
26334 +       depctl_data_t depctl = {.d32 = 0 };
26335 +       dsts_data_t dsts = {.d32 = 0 };
26336 +       volatile uint32_t *addr;
26337 +
26338 +       if (ep->is_in) {
26339 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
26340 +       } else {
26341 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
26342 +       }
26343 +
26344 +       ep->xfer_len = ep->data_per_frame;
26345 +       ep->xfer_count = 0;
26346 +       ep->xfer_buff = ep->cur_pkt_addr;
26347 +       ep->dma_addr = ep->cur_pkt_dma_addr;
26348 +
26349 +       if (ep->is_in) {
26350 +               /* Program the transfer size and packet count
26351 +                *      as follows: xfersize = N * maxpacket +
26352 +                *      short_packet pktcnt = N + (short_packet
26353 +                *      exist ? 1 : 0)
26354 +                */
26355 +               deptsiz.b.xfersize = ep->xfer_len;
26356 +               deptsiz.b.pktcnt =
26357 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
26358 +               deptsiz.b.mc = deptsiz.b.pktcnt;
26359 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
26360 +                               deptsiz.d32);
26361 +
26362 +               /* Write the DMA register */
26363 +               if (core_if->dma_enable) {
26364 +                       DWC_WRITE_REG32(&
26365 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
26366 +                                        diepdma), (uint32_t) ep->dma_addr);
26367 +               }
26368 +       } else {
26369 +               deptsiz.b.pktcnt =
26370 +                   (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
26371 +               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
26372 +
26373 +               DWC_WRITE_REG32(&core_if->dev_if->
26374 +                               out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);
26375 +
26376 +               if (core_if->dma_enable) {
26377 +                       DWC_WRITE_REG32(&
26378 +                                       (core_if->dev_if->
26379 +                                        out_ep_regs[ep->num]->doepdma),
26380 +                                       (uint32_t) ep->dma_addr);
26381 +               }
26382 +       }
26383 +
26384 +       /** Enable endpoint, clear nak  */
26385 +
26386 +       depctl.d32 = 0;
26387 +       if (ep->bInterval == 1) {
26388 +               dsts.d32 =
26389 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
26390 +               ep->next_frame = dsts.b.soffn + ep->bInterval;
26391 +
26392 +               if (ep->next_frame & 0x1) {
26393 +                       depctl.b.setd1pid = 1;
26394 +               } else {
26395 +                       depctl.b.setd0pid = 1;
26396 +               }
26397 +       } else {
26398 +               ep->next_frame += ep->bInterval;
26399 +
26400 +               if (ep->next_frame & 0x1) {
26401 +                       depctl.b.setd1pid = 1;
26402 +               } else {
26403 +                       depctl.b.setd0pid = 1;
26404 +               }
26405 +       }
26406 +       depctl.b.epena = 1;
26407 +       depctl.b.cnak = 1;
26408 +
26409 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
26410 +       depctl.d32 = DWC_READ_REG32(addr);
26411 +
26412 +       if (ep->is_in && core_if->dma_enable == 0) {
26413 +               write_isoc_frame_data(core_if, ep);
26414 +       }
26415 +
26416 +}
26417 +#endif /* DWC_EN_ISOC */
26418 +
26419 +static void dwc_otg_set_uninitialized(int32_t * p, int size)
26420 +{
26421 +       int i;
26422 +       for (i = 0; i < size; i++) {
26423 +               p[i] = -1;
26424 +       }
26425 +}
26426 +
26427 +static int dwc_otg_param_initialized(int32_t val)
26428 +{
26429 +       return val != -1;
26430 +}
26431 +
26432 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
26433 +{
26434 +       int i;
26435 +       core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
26436 +       if (!core_if->core_params) {
26437 +               return -DWC_E_NO_MEMORY;
26438 +       }
26439 +       dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
26440 +                                 sizeof(*core_if->core_params) /
26441 +                                 sizeof(int32_t));
26442 +       DWC_PRINTF("Setting default values for core params\n");
26443 +       dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
26444 +       dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
26445 +       dwc_otg_set_param_dma_desc_enable(core_if,
26446 +                                         dwc_param_dma_desc_enable_default);
26447 +       dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
26448 +       dwc_otg_set_param_dma_burst_size(core_if,
26449 +                                        dwc_param_dma_burst_size_default);
26450 +       dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
26451 +                                                      dwc_param_host_support_fs_ls_low_power_default);
26452 +       dwc_otg_set_param_enable_dynamic_fifo(core_if,
26453 +                                             dwc_param_enable_dynamic_fifo_default);
26454 +       dwc_otg_set_param_data_fifo_size(core_if,
26455 +                                        dwc_param_data_fifo_size_default);
26456 +       dwc_otg_set_param_dev_rx_fifo_size(core_if,
26457 +                                          dwc_param_dev_rx_fifo_size_default);
26458 +       dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
26459 +                                                 dwc_param_dev_nperio_tx_fifo_size_default);
26460 +       dwc_otg_set_param_host_rx_fifo_size(core_if,
26461 +                                           dwc_param_host_rx_fifo_size_default);
26462 +       dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
26463 +                                                  dwc_param_host_nperio_tx_fifo_size_default);
26464 +       dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
26465 +                                                 dwc_param_host_perio_tx_fifo_size_default);
26466 +       dwc_otg_set_param_max_transfer_size(core_if,
26467 +                                           dwc_param_max_transfer_size_default);
26468 +       dwc_otg_set_param_max_packet_count(core_if,
26469 +                                          dwc_param_max_packet_count_default);
26470 +       dwc_otg_set_param_host_channels(core_if,
26471 +                                       dwc_param_host_channels_default);
26472 +       dwc_otg_set_param_dev_endpoints(core_if,
26473 +                                       dwc_param_dev_endpoints_default);
26474 +       dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
26475 +       dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
26476 +       dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
26477 +                                                   dwc_param_host_ls_low_power_phy_clk_default);
26478 +       dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
26479 +       dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
26480 +                                           dwc_param_phy_ulpi_ext_vbus_default);
26481 +       dwc_otg_set_param_phy_utmi_width(core_if,
26482 +                                        dwc_param_phy_utmi_width_default);
26483 +       dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
26484 +       dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
26485 +       dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
26486 +       dwc_otg_set_param_en_multiple_tx_fifo(core_if,
26487 +                                             dwc_param_en_multiple_tx_fifo_default);
26488 +       for (i = 0; i < 15; i++) {
26489 +               dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
26490 +                                                        dwc_param_dev_perio_tx_fifo_size_default,
26491 +                                                        i);
26492 +       }
26493 +
26494 +       for (i = 0; i < 15; i++) {
26495 +               dwc_otg_set_param_dev_tx_fifo_size(core_if,
26496 +                                                  dwc_param_dev_tx_fifo_size_default,
26497 +                                                  i);
26498 +       }
26499 +       dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
26500 +       dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
26501 +       dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
26502 +       dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
26503 +       dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
26504 +       dwc_otg_set_param_tx_thr_length(core_if,
26505 +                                       dwc_param_tx_thr_length_default);
26506 +       dwc_otg_set_param_rx_thr_length(core_if,
26507 +                                       dwc_param_rx_thr_length_default);
26508 +       dwc_otg_set_param_ahb_thr_ratio(core_if,
26509 +                                       dwc_param_ahb_thr_ratio_default);
26510 +       dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
26511 +       dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
26512 +       dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
26513 +       dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
26514 +       dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
26515 +       dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
26516 +       dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
26517 +       DWC_PRINTF("Finished setting default values for core params\n");
26518 +
26519 +       return 0;
26520 +}
26521 +
26522 +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
26523 +{
26524 +       return core_if->dma_enable;
26525 +}
26526 +
26527 +/* Checks if the parameter is outside of its valid range of values */
26528 +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
26529 +               (((_param_) < (_low_)) || \
26530 +               ((_param_) > (_high_)))
26531 +
26532 +/* Parameter access functions */
26533 +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
26534 +{
26535 +       int valid;
26536 +       int retval = 0;
26537 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26538 +               DWC_WARN("Wrong value for otg_cap parameter\n");
26539 +               DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
26540 +               retval = -DWC_E_INVALID;
26541 +               goto out;
26542 +       }
26543 +
26544 +       valid = 1;
26545 +       switch (val) {
26546 +       case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
26547 +               if (core_if->hwcfg2.b.op_mode !=
26548 +                   DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26549 +                       valid = 0;
26550 +               break;
26551 +       case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
26552 +               if ((core_if->hwcfg2.b.op_mode !=
26553 +                    DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26554 +                   && (core_if->hwcfg2.b.op_mode !=
26555 +                       DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26556 +                   && (core_if->hwcfg2.b.op_mode !=
26557 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26558 +                   && (core_if->hwcfg2.b.op_mode !=
26559 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
26560 +                       valid = 0;
26561 +               }
26562 +               break;
26563 +       case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
26564 +               /* always valid */
26565 +               break;
26566 +       }
26567 +       if (!valid) {
26568 +               if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
26569 +                       DWC_ERROR
26570 +                           ("%d invalid for otg_cap paremter. Check HW configuration.\n",
26571 +                            val);
26572 +               }
26573 +               val =
26574 +                   (((core_if->hwcfg2.b.op_mode ==
26575 +                      DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26576 +                     || (core_if->hwcfg2.b.op_mode ==
26577 +                         DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26578 +                     || (core_if->hwcfg2.b.op_mode ==
26579 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26580 +                     || (core_if->hwcfg2.b.op_mode ==
26581 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
26582 +                    DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
26583 +                    DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
26584 +               retval = -DWC_E_INVALID;
26585 +       }
26586 +
26587 +       core_if->core_params->otg_cap = val;
26588 +out:
26589 +       return retval;
26590 +}
26591 +
26592 +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
26593 +{
26594 +       return core_if->core_params->otg_cap;
26595 +}
26596 +
26597 +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
26598 +{
26599 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26600 +               DWC_WARN("Wrong value for opt parameter\n");
26601 +               return -DWC_E_INVALID;
26602 +       }
26603 +       core_if->core_params->opt = val;
26604 +       return 0;
26605 +}
26606 +
26607 +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
26608 +{
26609 +       return core_if->core_params->opt;
26610 +}
26611 +
26612 +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
26613 +{
26614 +       int retval = 0;
26615 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26616 +               DWC_WARN("Wrong value for dma enable\n");
26617 +               return -DWC_E_INVALID;
26618 +       }
26619 +
26620 +       if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
26621 +               if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
26622 +                       DWC_ERROR
26623 +                           ("%d invalid for dma_enable paremter. Check HW configuration.\n",
26624 +                            val);
26625 +               }
26626 +               val = 0;
26627 +               retval = -DWC_E_INVALID;
26628 +       }
26629 +
26630 +       core_if->core_params->dma_enable = val;
26631 +       if (val == 0) {
26632 +               dwc_otg_set_param_dma_desc_enable(core_if, 0);
26633 +       }
26634 +       return retval;
26635 +}
26636 +
26637 +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
26638 +{
26639 +       return core_if->core_params->dma_enable;
26640 +}
26641 +
26642 +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
26643 +{
26644 +       int retval = 0;
26645 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26646 +               DWC_WARN("Wrong value for dma_enable\n");
26647 +               DWC_WARN("dma_desc_enable must be 0 or 1\n");
26648 +               return -DWC_E_INVALID;
26649 +       }
26650 +
26651 +       if ((val == 1)
26652 +           && ((dwc_otg_get_param_dma_enable(core_if) == 0)
26653 +               || (core_if->hwcfg4.b.desc_dma == 0))) {
26654 +               if (dwc_otg_param_initialized
26655 +                   (core_if->core_params->dma_desc_enable)) {
26656 +                       DWC_ERROR
26657 +                           ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
26658 +                            val);
26659 +               }
26660 +               val = 0;
26661 +               retval = -DWC_E_INVALID;
26662 +       }
26663 +       core_if->core_params->dma_desc_enable = val;
26664 +       return retval;
26665 +}
26666 +
26667 +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
26668 +{
26669 +       return core_if->core_params->dma_desc_enable;
26670 +}
26671 +
26672 +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
26673 +                                                  int32_t val)
26674 +{
26675 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26676 +               DWC_WARN("Wrong value for host_support_fs_low_power\n");
26677 +               DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
26678 +               return -DWC_E_INVALID;
26679 +       }
26680 +       core_if->core_params->host_support_fs_ls_low_power = val;
26681 +       return 0;
26682 +}
26683 +
26684 +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
26685 +                                                      core_if)
26686 +{
26687 +       return core_if->core_params->host_support_fs_ls_low_power;
26688 +}
26689 +
26690 +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
26691 +                                         int32_t val)
26692 +{
26693 +       int retval = 0;
26694 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26695 +               DWC_WARN("Wrong value for enable_dynamic_fifo\n");
26696 +               DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
26697 +               return -DWC_E_INVALID;
26698 +       }
26699 +
26700 +       if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
26701 +               if (dwc_otg_param_initialized
26702 +                   (core_if->core_params->enable_dynamic_fifo)) {
26703 +                       DWC_ERROR
26704 +                           ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
26705 +                            val);
26706 +               }
26707 +               val = 0;
26708 +               retval = -DWC_E_INVALID;
26709 +       }
26710 +       core_if->core_params->enable_dynamic_fifo = val;
26711 +       return retval;
26712 +}
26713 +
26714 +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
26715 +{
26716 +       return core_if->core_params->enable_dynamic_fifo;
26717 +}
26718 +
26719 +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26720 +{
26721 +       int retval = 0;
26722 +       if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
26723 +               DWC_WARN("Wrong value for data_fifo_size\n");
26724 +               DWC_WARN("data_fifo_size must be 32-32768\n");
26725 +               return -DWC_E_INVALID;
26726 +       }
26727 +
26728 +       if (val > core_if->hwcfg3.b.dfifo_depth) {
26729 +               if (dwc_otg_param_initialized
26730 +                   (core_if->core_params->data_fifo_size)) {
26731 +                       DWC_ERROR
26732 +                           ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
26733 +                            val);
26734 +               }
26735 +               val = core_if->hwcfg3.b.dfifo_depth;
26736 +               retval = -DWC_E_INVALID;
26737 +       }
26738 +
26739 +       core_if->core_params->data_fifo_size = val;
26740 +       return retval;
26741 +}
26742 +
26743 +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
26744 +{
26745 +       return core_if->core_params->data_fifo_size;
26746 +}
26747 +
26748 +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26749 +{
26750 +       int retval = 0;
26751 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26752 +               DWC_WARN("Wrong value for dev_rx_fifo_size\n");
26753 +               DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
26754 +               return -DWC_E_INVALID;
26755 +       }
26756 +
26757 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26758 +               if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
26759 +               DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
26760 +               }
26761 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26762 +               retval = -DWC_E_INVALID;
26763 +       }
26764 +
26765 +       core_if->core_params->dev_rx_fifo_size = val;
26766 +       return retval;
26767 +}
26768 +
26769 +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
26770 +{
26771 +       return core_if->core_params->dev_rx_fifo_size;
26772 +}
26773 +
26774 +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26775 +                                             int32_t val)
26776 +{
26777 +       int retval = 0;
26778 +
26779 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26780 +               DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
26781 +               DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
26782 +               return -DWC_E_INVALID;
26783 +       }
26784 +
26785 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26786 +               if (dwc_otg_param_initialized
26787 +                   (core_if->core_params->dev_nperio_tx_fifo_size)) {
26788 +                       DWC_ERROR
26789 +                           ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
26790 +                            val);
26791 +               }
26792 +               val =
26793 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26794 +                    16);
26795 +               retval = -DWC_E_INVALID;
26796 +       }
26797 +
26798 +       core_if->core_params->dev_nperio_tx_fifo_size = val;
26799 +       return retval;
26800 +}
26801 +
26802 +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26803 +{
26804 +       return core_if->core_params->dev_nperio_tx_fifo_size;
26805 +}
26806 +
26807 +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
26808 +                                       int32_t val)
26809 +{
26810 +       int retval = 0;
26811 +
26812 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26813 +               DWC_WARN("Wrong value for host_rx_fifo_size\n");
26814 +               DWC_WARN("host_rx_fifo_size must be 16-32768\n");
26815 +               return -DWC_E_INVALID;
26816 +       }
26817 +
26818 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26819 +               if (dwc_otg_param_initialized
26820 +                   (core_if->core_params->host_rx_fifo_size)) {
26821 +                       DWC_ERROR
26822 +                           ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
26823 +                            val);
26824 +               }
26825 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26826 +               retval = -DWC_E_INVALID;
26827 +       }
26828 +
26829 +       core_if->core_params->host_rx_fifo_size = val;
26830 +       return retval;
26831 +
26832 +}
26833 +
26834 +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
26835 +{
26836 +       return core_if->core_params->host_rx_fifo_size;
26837 +}
26838 +
26839 +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26840 +                                              int32_t val)
26841 +{
26842 +       int retval = 0;
26843 +
26844 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26845 +               DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
26846 +               DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
26847 +               return -DWC_E_INVALID;
26848 +       }
26849 +
26850 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26851 +               if (dwc_otg_param_initialized
26852 +                   (core_if->core_params->host_nperio_tx_fifo_size)) {
26853 +                       DWC_ERROR
26854 +                           ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
26855 +                            val);
26856 +               }
26857 +               val =
26858 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26859 +                    16);
26860 +               retval = -DWC_E_INVALID;
26861 +       }
26862 +
26863 +       core_if->core_params->host_nperio_tx_fifo_size = val;
26864 +       return retval;
26865 +}
26866 +
26867 +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26868 +{
26869 +       return core_if->core_params->host_nperio_tx_fifo_size;
26870 +}
26871 +
26872 +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26873 +                                             int32_t val)
26874 +{
26875 +       int retval = 0;
26876 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26877 +               DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
26878 +               DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
26879 +               return -DWC_E_INVALID;
26880 +       }
26881 +
26882 +       if (val > ((core_if->hptxfsiz.d32) >> 16)) {
26883 +               if (dwc_otg_param_initialized
26884 +                   (core_if->core_params->host_perio_tx_fifo_size)) {
26885 +                       DWC_ERROR
26886 +                           ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
26887 +                            val);
26888 +               }
26889 +               val = (core_if->hptxfsiz.d32) >> 16;
26890 +               retval = -DWC_E_INVALID;
26891 +       }
26892 +
26893 +       core_if->core_params->host_perio_tx_fifo_size = val;
26894 +       return retval;
26895 +}
26896 +
26897 +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26898 +{
26899 +       return core_if->core_params->host_perio_tx_fifo_size;
26900 +}
26901 +
26902 +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
26903 +                                       int32_t val)
26904 +{
26905 +       int retval = 0;
26906 +
26907 +       if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
26908 +               DWC_WARN("Wrong value for max_transfer_size\n");
26909 +               DWC_WARN("max_transfer_size must be 2047-524288\n");
26910 +               return -DWC_E_INVALID;
26911 +       }
26912 +
26913 +       if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
26914 +               if (dwc_otg_param_initialized
26915 +                   (core_if->core_params->max_transfer_size)) {
26916 +                       DWC_ERROR
26917 +                           ("%d invalid for max_transfer_size. Check HW configuration.\n",
26918 +                            val);
26919 +               }
26920 +               val =
26921 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
26922 +                    1);
26923 +               retval = -DWC_E_INVALID;
26924 +       }
26925 +
26926 +       core_if->core_params->max_transfer_size = val;
26927 +       return retval;
26928 +}
26929 +
26930 +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
26931 +{
26932 +       return core_if->core_params->max_transfer_size;
26933 +}
26934 +
26935 +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
26936 +{
26937 +       int retval = 0;
26938 +
26939 +       if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
26940 +               DWC_WARN("Wrong value for max_packet_count\n");
26941 +               DWC_WARN("max_packet_count must be 15-511\n");
26942 +               return -DWC_E_INVALID;
26943 +       }
26944 +
26945 +       if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
26946 +               if (dwc_otg_param_initialized
26947 +                   (core_if->core_params->max_packet_count)) {
26948 +                       DWC_ERROR
26949 +                           ("%d invalid for max_packet_count. Check HW configuration.\n",
26950 +                            val);
26951 +               }
26952 +               val =
26953 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
26954 +               retval = -DWC_E_INVALID;
26955 +       }
26956 +
26957 +       core_if->core_params->max_packet_count = val;
26958 +       return retval;
26959 +}
26960 +
26961 +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
26962 +{
26963 +       return core_if->core_params->max_packet_count;
26964 +}
26965 +
26966 +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
26967 +{
26968 +       int retval = 0;
26969 +
26970 +       if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
26971 +               DWC_WARN("Wrong value for host_channels\n");
26972 +               DWC_WARN("host_channels must be 1-16\n");
26973 +               return -DWC_E_INVALID;
26974 +       }
26975 +
26976 +       if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
26977 +               if (dwc_otg_param_initialized
26978 +                   (core_if->core_params->host_channels)) {
26979 +                       DWC_ERROR
26980 +                           ("%d invalid for host_channels. Check HW configurations.\n",
26981 +                            val);
26982 +               }
26983 +               val = (core_if->hwcfg2.b.num_host_chan + 1);
26984 +               retval = -DWC_E_INVALID;
26985 +       }
26986 +
26987 +       core_if->core_params->host_channels = val;
26988 +       return retval;
26989 +}
26990 +
26991 +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
26992 +{
26993 +       return core_if->core_params->host_channels;
26994 +}
26995 +
26996 +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
26997 +{
26998 +       int retval = 0;
26999 +
27000 +       if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
27001 +               DWC_WARN("Wrong value for dev_endpoints\n");
27002 +               DWC_WARN("dev_endpoints must be 1-15\n");
27003 +               return -DWC_E_INVALID;
27004 +       }
27005 +
27006 +       if (val > (core_if->hwcfg2.b.num_dev_ep)) {
27007 +               if (dwc_otg_param_initialized
27008 +                   (core_if->core_params->dev_endpoints)) {
27009 +                       DWC_ERROR
27010 +                           ("%d invalid for dev_endpoints. Check HW configurations.\n",
27011 +                            val);
27012 +               }
27013 +               val = core_if->hwcfg2.b.num_dev_ep;
27014 +               retval = -DWC_E_INVALID;
27015 +       }
27016 +
27017 +       core_if->core_params->dev_endpoints = val;
27018 +       return retval;
27019 +}
27020 +
27021 +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
27022 +{
27023 +       return core_if->core_params->dev_endpoints;
27024 +}
27025 +
27026 +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
27027 +{
27028 +       int retval = 0;
27029 +       int valid = 0;
27030 +
27031 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
27032 +               DWC_WARN("Wrong value for phy_type\n");
27033 +               DWC_WARN("phy_type must be 0,1 or 2\n");
27034 +               return -DWC_E_INVALID;
27035 +       }
27036 +#ifndef NO_FS_PHY_HW_CHECKS
27037 +       if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
27038 +           ((core_if->hwcfg2.b.hs_phy_type == 1) ||
27039 +            (core_if->hwcfg2.b.hs_phy_type == 3))) {
27040 +               valid = 1;
27041 +       } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
27042 +                  ((core_if->hwcfg2.b.hs_phy_type == 2) ||
27043 +                   (core_if->hwcfg2.b.hs_phy_type == 3))) {
27044 +               valid = 1;
27045 +       } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
27046 +                  (core_if->hwcfg2.b.fs_phy_type == 1)) {
27047 +               valid = 1;
27048 +       }
27049 +       if (!valid) {
27050 +               if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
27051 +                       DWC_ERROR
27052 +                           ("%d invalid for phy_type. Check HW configurations.\n",
27053 +                            val);
27054 +               }
27055 +               if (core_if->hwcfg2.b.hs_phy_type) {
27056 +                       if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
27057 +                           (core_if->hwcfg2.b.hs_phy_type == 1)) {
27058 +                               val = DWC_PHY_TYPE_PARAM_UTMI;
27059 +                       } else {
27060 +                               val = DWC_PHY_TYPE_PARAM_ULPI;
27061 +                       }
27062 +               }
27063 +               retval = -DWC_E_INVALID;
27064 +       }
27065 +#endif
27066 +       core_if->core_params->phy_type = val;
27067 +       return retval;
27068 +}
27069 +
27070 +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
27071 +{
27072 +       return core_if->core_params->phy_type;
27073 +}
27074 +
27075 +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
27076 +{
27077 +       int retval = 0;
27078 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27079 +               DWC_WARN("Wrong value for speed parameter\n");
27080 +               DWC_WARN("max_speed parameter must be 0 or 1\n");
27081 +               return -DWC_E_INVALID;
27082 +       }
27083 +       if ((val == 0)
27084 +           && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
27085 +               if (dwc_otg_param_initialized(core_if->core_params->speed)) {
27086 +                       DWC_ERROR
27087 +                           ("%d invalid for speed paremter. Check HW configuration.\n",
27088 +                            val);
27089 +               }
27090 +               val =
27091 +                   (dwc_otg_get_param_phy_type(core_if) ==
27092 +                    DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
27093 +               retval = -DWC_E_INVALID;
27094 +       }
27095 +       core_if->core_params->speed = val;
27096 +       return retval;
27097 +}
27098 +
27099 +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
27100 +{
27101 +       return core_if->core_params->speed;
27102 +}
27103 +
27104 +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
27105 +                                               int32_t val)
27106 +{
27107 +       int retval = 0;
27108 +
27109 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27110 +               DWC_WARN
27111 +                   ("Wrong value for host_ls_low_power_phy_clk parameter\n");
27112 +               DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
27113 +               return -DWC_E_INVALID;
27114 +       }
27115 +
27116 +       if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
27117 +           && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
27118 +               if (dwc_otg_param_initialized
27119 +                   (core_if->core_params->host_ls_low_power_phy_clk)) {
27120 +                       DWC_ERROR
27121 +                           ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
27122 +                            val);
27123 +               }
27124 +               val =
27125 +                   (dwc_otg_get_param_phy_type(core_if) ==
27126 +                    DWC_PHY_TYPE_PARAM_FS) ?
27127 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
27128 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
27129 +               retval = -DWC_E_INVALID;
27130 +       }
27131 +
27132 +       core_if->core_params->host_ls_low_power_phy_clk = val;
27133 +       return retval;
27134 +}
27135 +
27136 +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
27137 +{
27138 +       return core_if->core_params->host_ls_low_power_phy_clk;
27139 +}
27140 +
27141 +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
27142 +{
27143 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27144 +               DWC_WARN("Wrong value for phy_ulpi_ddr\n");
27145 +               DWC_WARN("phy_upli_ddr must be 0 or 1\n");
27146 +               return -DWC_E_INVALID;
27147 +       }
27148 +
27149 +       core_if->core_params->phy_ulpi_ddr = val;
27150 +       return 0;
27151 +}
27152 +
27153 +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
27154 +{
27155 +       return core_if->core_params->phy_ulpi_ddr;
27156 +}
27157 +
27158 +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
27159 +                                       int32_t val)
27160 +{
27161 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27162 +               DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
27163 +               DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
27164 +               return -DWC_E_INVALID;
27165 +       }
27166 +
27167 +       core_if->core_params->phy_ulpi_ext_vbus = val;
27168 +       return 0;
27169 +}
27170 +
27171 +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
27172 +{
27173 +       return core_if->core_params->phy_ulpi_ext_vbus;
27174 +}
27175 +
27176 +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
27177 +{
27178 +       if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
27179 +               DWC_WARN("Wrong valaue for phy_utmi_width\n");
27180 +               DWC_WARN("phy_utmi_width must be 8 or 16\n");
27181 +               return -DWC_E_INVALID;
27182 +       }
27183 +
27184 +       core_if->core_params->phy_utmi_width = val;
27185 +       return 0;
27186 +}
27187 +
27188 +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
27189 +{
27190 +       return core_if->core_params->phy_utmi_width;
27191 +}
27192 +
27193 +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
27194 +{
27195 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27196 +               DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
27197 +               DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
27198 +               return -DWC_E_INVALID;
27199 +       }
27200 +
27201 +       core_if->core_params->ulpi_fs_ls = val;
27202 +       return 0;
27203 +}
27204 +
27205 +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
27206 +{
27207 +       return core_if->core_params->ulpi_fs_ls;
27208 +}
27209 +
27210 +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
27211 +{
27212 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27213 +               DWC_WARN("Wrong valaue for ts_dline\n");
27214 +               DWC_WARN("ts_dline must be 0 or 1\n");
27215 +               return -DWC_E_INVALID;
27216 +       }
27217 +
27218 +       core_if->core_params->ts_dline = val;
27219 +       return 0;
27220 +}
27221 +
27222 +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
27223 +{
27224 +       return core_if->core_params->ts_dline;
27225 +}
27226 +
27227 +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
27228 +{
27229 +       int retval = 0;
27230 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27231 +               DWC_WARN("Wrong valaue for i2c_enable\n");
27232 +               DWC_WARN("i2c_enable must be 0 or 1\n");
27233 +               return -DWC_E_INVALID;
27234 +       }
27235 +#ifndef NO_FS_PHY_HW_CHECK
27236 +       if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
27237 +               if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
27238 +                       DWC_ERROR
27239 +                           ("%d invalid for i2c_enable. Check HW configuration.\n",
27240 +                            val);
27241 +               }
27242 +               val = 0;
27243 +               retval = -DWC_E_INVALID;
27244 +       }
27245 +#endif
27246 +
27247 +       core_if->core_params->i2c_enable = val;
27248 +       return retval;
27249 +}
27250 +
27251 +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
27252 +{
27253 +       return core_if->core_params->i2c_enable;
27254 +}
27255 +
27256 +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27257 +                                            int32_t val, int fifo_num)
27258 +{
27259 +       int retval = 0;
27260 +
27261 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27262 +               DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
27263 +               DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
27264 +               return -DWC_E_INVALID;
27265 +       }
27266 +
27267 +       if (val >
27268 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27269 +               if (dwc_otg_param_initialized
27270 +                   (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
27271 +                       DWC_ERROR
27272 +                           ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
27273 +                            val, fifo_num);
27274 +               }
27275 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27276 +               retval = -DWC_E_INVALID;
27277 +       }
27278 +
27279 +       core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
27280 +       return retval;
27281 +}
27282 +
27283 +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27284 +                                                int fifo_num)
27285 +{
27286 +       return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
27287 +}
27288 +
27289 +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
27290 +                                         int32_t val)
27291 +{
27292 +       int retval = 0;
27293 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27294 +               DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
27295 +               DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
27296 +               return -DWC_E_INVALID;
27297 +       }
27298 +
27299 +       if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
27300 +               if (dwc_otg_param_initialized
27301 +                   (core_if->core_params->en_multiple_tx_fifo)) {
27302 +                       DWC_ERROR
27303 +                           ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
27304 +                            val);
27305 +               }
27306 +               val = 0;
27307 +               retval = -DWC_E_INVALID;
27308 +       }
27309 +
27310 +       core_if->core_params->en_multiple_tx_fifo = val;
27311 +       return retval;
27312 +}
27313 +
27314 +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
27315 +{
27316 +       return core_if->core_params->en_multiple_tx_fifo;
27317 +}
27318 +
27319 +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
27320 +                                      int fifo_num)
27321 +{
27322 +       int retval = 0;
27323 +
27324 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27325 +               DWC_WARN("Wrong value for dev_tx_fifo_size\n");
27326 +               DWC_WARN("dev_tx_fifo_size must be 4-768\n");
27327 +               return -DWC_E_INVALID;
27328 +       }
27329 +
27330 +       if (val >
27331 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27332 +               if (dwc_otg_param_initialized
27333 +                   (core_if->core_params->dev_tx_fifo_size[fifo_num])) {
27334 +                       DWC_ERROR
27335 +                           ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
27336 +                            val, fifo_num);
27337 +               }
27338 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27339 +               retval = -DWC_E_INVALID;
27340 +       }
27341 +
27342 +       core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
27343 +       return retval;
27344 +}
27345 +
27346 +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
27347 +                                          int fifo_num)
27348 +{
27349 +       return core_if->core_params->dev_tx_fifo_size[fifo_num];
27350 +}
27351 +
27352 +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27353 +{
27354 +       int retval = 0;
27355 +
27356 +       if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
27357 +               DWC_WARN("Wrong value for thr_ctl\n");
27358 +               DWC_WARN("thr_ctl must be 0-7\n");
27359 +               return -DWC_E_INVALID;
27360 +       }
27361 +
27362 +       if ((val != 0) &&
27363 +           (!dwc_otg_get_param_dma_enable(core_if) ||
27364 +            !core_if->hwcfg4.b.ded_fifo_en)) {
27365 +               if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
27366 +                       DWC_ERROR
27367 +                           ("%d invalid for parameter thr_ctl. Check HW configuration.\n",
27368 +                            val);
27369 +               }
27370 +               val = 0;
27371 +               retval = -DWC_E_INVALID;
27372 +       }
27373 +
27374 +       core_if->core_params->thr_ctl = val;
27375 +       return retval;
27376 +}
27377 +
27378 +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
27379 +{
27380 +       return core_if->core_params->thr_ctl;
27381 +}
27382 +
27383 +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
27384 +{
27385 +       int retval = 0;
27386 +
27387 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27388 +               DWC_WARN("Wrong value for lpm_enable\n");
27389 +               DWC_WARN("lpm_enable must be 0 or 1\n");
27390 +               return -DWC_E_INVALID;
27391 +       }
27392 +
27393 +       if (val && !core_if->hwcfg3.b.otg_lpm_en) {
27394 +               if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
27395 +                       DWC_ERROR
27396 +                           ("%d invalid for parameter lpm_enable. Check HW configuration.\n",
27397 +                            val);
27398 +               }
27399 +               val = 0;
27400 +               retval = -DWC_E_INVALID;
27401 +       }
27402 +
27403 +       core_if->core_params->lpm_enable = val;
27404 +       return retval;
27405 +}
27406 +
27407 +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
27408 +{
27409 +       return core_if->core_params->lpm_enable;
27410 +}
27411 +
27412 +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27413 +{
27414 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27415 +               DWC_WARN("Wrong valaue for tx_thr_length\n");
27416 +               DWC_WARN("tx_thr_length must be 8 - 128\n");
27417 +               return -DWC_E_INVALID;
27418 +       }
27419 +
27420 +       core_if->core_params->tx_thr_length = val;
27421 +       return 0;
27422 +}
27423 +
27424 +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
27425 +{
27426 +       return core_if->core_params->tx_thr_length;
27427 +}
27428 +
27429 +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27430 +{
27431 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27432 +               DWC_WARN("Wrong valaue for rx_thr_length\n");
27433 +               DWC_WARN("rx_thr_length must be 8 - 128\n");
27434 +               return -DWC_E_INVALID;
27435 +       }
27436 +
27437 +       core_if->core_params->rx_thr_length = val;
27438 +       return 0;
27439 +}
27440 +
27441 +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
27442 +{
27443 +       return core_if->core_params->rx_thr_length;
27444 +}
27445 +
27446 +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
27447 +{
27448 +       if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
27449 +           DWC_OTG_PARAM_TEST(val, 4, 4) &&
27450 +           DWC_OTG_PARAM_TEST(val, 8, 8) &&
27451 +           DWC_OTG_PARAM_TEST(val, 16, 16) &&
27452 +           DWC_OTG_PARAM_TEST(val, 32, 32) &&
27453 +           DWC_OTG_PARAM_TEST(val, 64, 64) &&
27454 +           DWC_OTG_PARAM_TEST(val, 128, 128) &&
27455 +           DWC_OTG_PARAM_TEST(val, 256, 256)) {
27456 +               DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
27457 +               return -DWC_E_INVALID;
27458 +       }
27459 +       core_if->core_params->dma_burst_size = val;
27460 +       return 0;
27461 +}
27462 +
27463 +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
27464 +{
27465 +       return core_if->core_params->dma_burst_size;
27466 +}
27467 +
27468 +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
27469 +{
27470 +       int retval = 0;
27471 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27472 +               DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
27473 +               return -DWC_E_INVALID;
27474 +       }
27475 +       if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
27476 +               if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
27477 +                       DWC_ERROR
27478 +                           ("%d invalid for parameter pti_enable. Check HW configuration.\n",
27479 +                            val);
27480 +               }
27481 +               retval = -DWC_E_INVALID;
27482 +               val = 0;
27483 +       }
27484 +       core_if->core_params->pti_enable = val;
27485 +       return retval;
27486 +}
27487 +
27488 +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
27489 +{
27490 +       return core_if->core_params->pti_enable;
27491 +}
27492 +
27493 +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
27494 +{
27495 +       int retval = 0;
27496 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27497 +               DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
27498 +               return -DWC_E_INVALID;
27499 +       }
27500 +       if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
27501 +               if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
27502 +                       DWC_ERROR
27503 +                           ("%d invalid for parameter mpi_enable. Check HW configuration.\n",
27504 +                            val);
27505 +               }
27506 +               retval = -DWC_E_INVALID;
27507 +               val = 0;
27508 +       }
27509 +       core_if->core_params->mpi_enable = val;
27510 +       return retval;
27511 +}
27512 +
27513 +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
27514 +{
27515 +       return core_if->core_params->mpi_enable;
27516 +}
27517 +
27518 +int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)
27519 +{
27520 +       int retval = 0;
27521 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27522 +               DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);
27523 +               return -DWC_E_INVALID;
27524 +       }
27525 +       if (val && (core_if->hwcfg3.b.adp_supp == 0)) {
27526 +               if (dwc_otg_param_initialized
27527 +                   (core_if->core_params->adp_supp_enable)) {
27528 +                       DWC_ERROR
27529 +                           ("%d invalid for parameter adp_enable. Check HW configuration.\n",
27530 +                            val);
27531 +               }
27532 +               retval = -DWC_E_INVALID;
27533 +               val = 0;
27534 +       }
27535 +       core_if->core_params->adp_supp_enable = val;
27536 +       /*Set OTG version 2.0 in case of enabling ADP*/
27537 +       if (val)
27538 +               dwc_otg_set_param_otg_ver(core_if, 1);
27539 +
27540 +       return retval;
27541 +}
27542 +
27543 +int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)
27544 +{
27545 +       return core_if->core_params->adp_supp_enable;
27546 +}
27547 +
27548 +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)
27549 +{
27550 +       int retval = 0;
27551 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27552 +               DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
27553 +               DWC_WARN("ic_usb_cap must be 0 or 1\n");
27554 +               return -DWC_E_INVALID;
27555 +       }
27556 +
27557 +       if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {
27558 +               if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
27559 +                       DWC_ERROR
27560 +                           ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
27561 +                            val);
27562 +               }
27563 +               retval = -DWC_E_INVALID;
27564 +               val = 0;
27565 +       }
27566 +       core_if->core_params->ic_usb_cap = val;
27567 +       return retval;
27568 +}
27569 +
27570 +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
27571 +{
27572 +       return core_if->core_params->ic_usb_cap;
27573 +}
27574 +
27575 +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
27576 +{
27577 +       int retval = 0;
27578 +       int valid = 1;
27579 +
27580 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27581 +               DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
27582 +               DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
27583 +               return -DWC_E_INVALID;
27584 +       }
27585 +
27586 +       if (val
27587 +           && (core_if->snpsid < OTG_CORE_REV_2_81a
27588 +               || !dwc_otg_get_param_thr_ctl(core_if))) {
27589 +               valid = 0;
27590 +       } else if (val
27591 +                  && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <
27592 +                      4)) {
27593 +               valid = 0;
27594 +       }
27595 +       if (valid == 0) {
27596 +               if (dwc_otg_param_initialized
27597 +                   (core_if->core_params->ahb_thr_ratio)) {
27598 +                       DWC_ERROR
27599 +                           ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",
27600 +                            val);
27601 +               }
27602 +               retval = -DWC_E_INVALID;
27603 +               val = 0;
27604 +       }
27605 +
27606 +       core_if->core_params->ahb_thr_ratio = val;
27607 +       return retval;
27608 +}
27609 +
27610 +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
27611 +{
27612 +       return core_if->core_params->ahb_thr_ratio;
27613 +}
27614 +
27615 +int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)
27616 +{
27617 +       int retval = 0;
27618 +       int valid = 1;
27619 +       hwcfg4_data_t hwcfg4 = {.d32 = 0 };
27620 +       hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
27621 +
27622 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27623 +               DWC_WARN("`%d' invalid for parameter `power_down'\n", val);
27624 +               DWC_WARN("power_down must be 0 - 2\n");
27625 +               return -DWC_E_INVALID;
27626 +       }
27627 +
27628 +       if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {
27629 +               valid = 0;
27630 +       }
27631 +       if ((val == 3)
27632 +           && ((core_if->snpsid < OTG_CORE_REV_3_00a)
27633 +               || (hwcfg4.b.xhiber == 0))) {
27634 +               valid = 0;
27635 +       }
27636 +       if (valid == 0) {
27637 +               if (dwc_otg_param_initialized(core_if->core_params->power_down)) {
27638 +                       DWC_ERROR
27639 +                           ("%d invalid for parameter power_down. Check HW configuration.\n",
27640 +                            val);
27641 +               }
27642 +               retval = -DWC_E_INVALID;
27643 +               val = 0;
27644 +       }
27645 +       core_if->core_params->power_down = val;
27646 +       return retval;
27647 +}
27648 +
27649 +int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)
27650 +{
27651 +       return core_if->core_params->power_down;
27652 +}
27653 +
27654 +int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27655 +{
27656 +       int retval = 0;
27657 +       int valid = 1;
27658 +
27659 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27660 +               DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);
27661 +               DWC_WARN("reload_ctl must be 0 or 1\n");
27662 +               return -DWC_E_INVALID;
27663 +       }
27664 +
27665 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {
27666 +               valid = 0;
27667 +       }
27668 +       if (valid == 0) {
27669 +               if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {
27670 +                       DWC_ERROR("%d invalid for parameter reload_ctl."
27671 +                                 "Check HW configuration.\n", val);
27672 +               }
27673 +               retval = -DWC_E_INVALID;
27674 +               val = 0;
27675 +       }
27676 +       core_if->core_params->reload_ctl = val;
27677 +       return retval;
27678 +}
27679 +
27680 +int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)
27681 +{
27682 +       return core_if->core_params->reload_ctl;
27683 +}
27684 +
27685 +int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)
27686 +{
27687 +       int retval = 0;
27688 +       int valid = 1;
27689 +
27690 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27691 +               DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);
27692 +               DWC_WARN("dev_out_nak must be 0 or 1\n");
27693 +               return -DWC_E_INVALID;
27694 +       }
27695 +
27696 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||
27697 +               !(core_if->core_params->dma_desc_enable))) {
27698 +               valid = 0;
27699 +       }
27700 +       if (valid == 0) {
27701 +               if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {
27702 +                       DWC_ERROR("%d invalid for parameter dev_out_nak."
27703 +                               "Check HW configuration.\n", val);
27704 +               }
27705 +               retval = -DWC_E_INVALID;
27706 +               val = 0;
27707 +       }
27708 +       core_if->core_params->dev_out_nak = val;
27709 +       return retval;
27710 +}
27711 +
27712 +int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)
27713 +{
27714 +       return core_if->core_params->dev_out_nak;
27715 +}
27716 +
27717 +int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
27718 +{
27719 +       int retval = 0;
27720 +       int valid = 1;
27721 +
27722 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27723 +               DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
27724 +               DWC_WARN("cont_on_bna must be 0 or 1\n");
27725 +               return -DWC_E_INVALID;
27726 +       }
27727 +
27728 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
27729 +               !(core_if->core_params->dma_desc_enable))) {
27730 +                       valid = 0;
27731 +       }
27732 +       if (valid == 0) {
27733 +               if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
27734 +                       DWC_ERROR("%d invalid for parameter cont_on_bna."
27735 +                               "Check HW configuration.\n", val);
27736 +               }
27737 +               retval = -DWC_E_INVALID;
27738 +               val = 0;
27739 +       }
27740 +       core_if->core_params->cont_on_bna = val;
27741 +       return retval;
27742 +}
27743 +
27744 +int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
27745 +{
27746 +       return core_if->core_params->cont_on_bna;
27747 +}
27748 +
27749 +int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
27750 +{
27751 +       int retval = 0;
27752 +       int valid = 1;
27753 +
27754 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27755 +               DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
27756 +               DWC_WARN("ahb_single must be 0 or 1\n");
27757 +               return -DWC_E_INVALID;
27758 +       }
27759 +
27760 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
27761 +                       valid = 0;
27762 +       }
27763 +       if (valid == 0) {
27764 +               if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
27765 +                       DWC_ERROR("%d invalid for parameter ahb_single."
27766 +                               "Check HW configuration.\n", val);
27767 +               }
27768 +               retval = -DWC_E_INVALID;
27769 +               val = 0;
27770 +       }
27771 +       core_if->core_params->ahb_single = val;
27772 +       return retval;
27773 +}
27774 +
27775 +int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
27776 +{
27777 +       return core_if->core_params->ahb_single;
27778 +}
27779 +
27780 +int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
27781 +{
27782 +       int retval = 0;
27783 +
27784 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27785 +               DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);
27786 +               DWC_WARN
27787 +                   ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");
27788 +               return -DWC_E_INVALID;
27789 +       }
27790 +
27791 +       core_if->core_params->otg_ver = val;
27792 +       return retval;
27793 +}
27794 +
27795 +int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)
27796 +{
27797 +       return core_if->core_params->otg_ver;
27798 +}
27799 +
27800 +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
27801 +{
27802 +       gotgctl_data_t otgctl;
27803 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27804 +       return otgctl.b.hstnegscs;
27805 +}
27806 +
27807 +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
27808 +{
27809 +       gotgctl_data_t otgctl;
27810 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27811 +       return otgctl.b.sesreqscs;
27812 +}
27813 +
27814 +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
27815 +{
27816 +       if(core_if->otg_ver == 0) {
27817 +               gotgctl_data_t otgctl;
27818 +               otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27819 +               otgctl.b.hnpreq = val;
27820 +               DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);
27821 +       } else {
27822 +               core_if->otg_sts = val;
27823 +       }
27824 +}
27825 +
27826 +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
27827 +{
27828 +       return core_if->snpsid;
27829 +}
27830 +
27831 +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
27832 +{
27833 +       gintsts_data_t gintsts;
27834 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
27835 +       return gintsts.b.curmode;
27836 +}
27837 +
27838 +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
27839 +{
27840 +       gusbcfg_data_t usbcfg;
27841 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27842 +       return usbcfg.b.hnpcap;
27843 +}
27844 +
27845 +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27846 +{
27847 +       gusbcfg_data_t usbcfg;
27848 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27849 +       usbcfg.b.hnpcap = val;
27850 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27851 +}
27852 +
27853 +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
27854 +{
27855 +       gusbcfg_data_t usbcfg;
27856 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27857 +       return usbcfg.b.srpcap;
27858 +}
27859 +
27860 +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27861 +{
27862 +       gusbcfg_data_t usbcfg;
27863 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27864 +       usbcfg.b.srpcap = val;
27865 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27866 +}
27867 +
27868 +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
27869 +{
27870 +       dcfg_data_t dcfg;
27871 +       /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */
27872 +
27873 +        dcfg.d32 = -1; //GRAYG
27874 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
27875 +        if (NULL == core_if)
27876 +                DWC_ERROR("reg request with NULL core_if\n");
27877 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
27878 +                    core_if, core_if->dev_if);
27879 +        if (NULL == core_if->dev_if)
27880 +                DWC_ERROR("reg request with NULL dev_if\n");
27881 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
27882 +                    "dev_global_regs(%p)\n", __func__,
27883 +                    core_if, core_if->dev_if,
27884 +                    core_if->dev_if->dev_global_regs);
27885 +        if (NULL == core_if->dev_if->dev_global_regs)
27886 +                DWC_ERROR("reg request with NULL dev_global_regs\n");
27887 +        else {
27888 +                DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
27889 +                            "dev_global_regs(%p)->dcfg = %p\n", __func__,
27890 +                            core_if, core_if->dev_if,
27891 +                            core_if->dev_if->dev_global_regs,
27892 +                            &core_if->dev_if->dev_global_regs->dcfg);
27893 +               dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27894 +        }
27895 +       return dcfg.b.devspd;
27896 +}
27897 +
27898 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
27899 +{
27900 +       dcfg_data_t dcfg;
27901 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27902 +       dcfg.b.devspd = val;
27903 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
27904 +}
27905 +
27906 +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
27907 +{
27908 +       hprt0_data_t hprt0;
27909 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27910 +       return hprt0.b.prtconnsts;
27911 +}
27912 +
27913 +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
27914 +{
27915 +       dsts_data_t dsts;
27916 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
27917 +       return dsts.b.enumspd;
27918 +}
27919 +
27920 +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
27921 +{
27922 +       hprt0_data_t hprt0;
27923 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27924 +       return hprt0.b.prtpwr;
27925 +
27926 +}
27927 +
27928 +uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)
27929 +{
27930 +       return core_if->hibernation_suspend;
27931 +}
27932 +
27933 +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
27934 +{
27935 +       hprt0_data_t hprt0;
27936 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27937 +       hprt0.b.prtpwr = val;
27938 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27939 +}
27940 +
27941 +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
27942 +{
27943 +       hprt0_data_t hprt0;
27944 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27945 +       return hprt0.b.prtsusp;
27946 +
27947 +}
27948 +
27949 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
27950 +{
27951 +       hprt0_data_t hprt0;
27952 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27953 +       hprt0.b.prtsusp = val;
27954 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27955 +}
27956 +
27957 +uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)
27958 +{
27959 +       hfir_data_t hfir;
27960 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27961 +       return hfir.b.frint;
27962 +
27963 +}
27964 +
27965 +void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)
27966 +{
27967 +       hfir_data_t hfir;
27968 +       uint32_t fram_int;
27969 +       fram_int = calc_frame_interval(core_if);
27970 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27971 +       if (!core_if->core_params->reload_ctl) {
27972 +               DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"
27973 +                        "not set to 1.\nShould load driver with reload_ctl=1"
27974 +                        " module parameter\n");
27975 +               return;
27976 +       }
27977 +       switch (fram_int) {
27978 +       case 3750:
27979 +               if ((val < 3350) || (val > 4150)) {
27980 +                       DWC_WARN("HFIR interval for HS core and 30 MHz"
27981 +                                "clock freq should be from 3350 to 4150\n");
27982 +                       return;
27983 +               }
27984 +               break;
27985 +       case 30000:
27986 +               if ((val < 26820) || (val > 33180)) {
27987 +                       DWC_WARN("HFIR interval for FS/LS core and 30 MHz"
27988 +                                "clock freq should be from 26820 to 33180\n");
27989 +                       return;
27990 +               }
27991 +               break;
27992 +       case 6000:
27993 +               if ((val < 5360) || (val > 6640)) {
27994 +                       DWC_WARN("HFIR interval for HS core and 48 MHz"
27995 +                                "clock freq should be from 5360 to 6640\n");
27996 +                       return;
27997 +               }
27998 +               break;
27999 +       case 48000:
28000 +               if ((val < 42912) || (val > 53088)) {
28001 +                       DWC_WARN("HFIR interval for FS/LS core and 48 MHz"
28002 +                                "clock freq should be from 42912 to 53088\n");
28003 +                       return;
28004 +               }
28005 +               break;
28006 +       case 7500:
28007 +               if ((val < 6700) || (val > 8300)) {
28008 +                       DWC_WARN("HFIR interval for HS core and 60 MHz"
28009 +                                "clock freq should be from 6700 to 8300\n");
28010 +                       return;
28011 +               }
28012 +               break;
28013 +       case 60000:
28014 +               if ((val < 53640) || (val > 65536)) {
28015 +                       DWC_WARN("HFIR interval for FS/LS core and 60 MHz"
28016 +                                "clock freq should be from 53640 to 65536\n");
28017 +                       return;
28018 +               }
28019 +               break;
28020 +       default:
28021 +               DWC_WARN("Unknown frame interval\n");
28022 +               return;
28023 +               break;
28024 +
28025 +       }
28026 +       hfir.b.frint = val;
28027 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);
28028 +}
28029 +
28030 +uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)
28031 +{
28032 +       hcfg_data_t hcfg;
28033 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
28034 +       return hcfg.b.modechtimen;
28035 +
28036 +}
28037 +
28038 +void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)
28039 +{
28040 +       hcfg_data_t hcfg;
28041 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
28042 +       hcfg.b.modechtimen = val;
28043 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
28044 +}
28045 +
28046 +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
28047 +{
28048 +       hprt0_data_t hprt0;
28049 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
28050 +       hprt0.b.prtres = val;
28051 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
28052 +}
28053 +
28054 +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
28055 +{
28056 +       dctl_data_t dctl;
28057 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
28058 +       return dctl.b.rmtwkupsig;
28059 +}
28060 +
28061 +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
28062 +{
28063 +       glpmcfg_data_t lpmcfg;
28064 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28065 +
28066 +       DWC_ASSERT(!
28067 +                  ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
28068 +                  "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
28069 +                  core_if->lx_state, lpmcfg.b.prt_sleep_sts);
28070 +
28071 +       return lpmcfg.b.prt_sleep_sts;
28072 +}
28073 +
28074 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
28075 +{
28076 +       glpmcfg_data_t lpmcfg;
28077 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28078 +       return lpmcfg.b.rem_wkup_en;
28079 +}
28080 +
28081 +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
28082 +{
28083 +       glpmcfg_data_t lpmcfg;
28084 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28085 +       return lpmcfg.b.appl_resp;
28086 +}
28087 +
28088 +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
28089 +{
28090 +       glpmcfg_data_t lpmcfg;
28091 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28092 +       lpmcfg.b.appl_resp = val;
28093 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28094 +}
28095 +
28096 +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
28097 +{
28098 +       glpmcfg_data_t lpmcfg;
28099 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28100 +       return lpmcfg.b.hsic_connect;
28101 +}
28102 +
28103 +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
28104 +{
28105 +       glpmcfg_data_t lpmcfg;
28106 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28107 +       lpmcfg.b.hsic_connect = val;
28108 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28109 +}
28110 +
28111 +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
28112 +{
28113 +       glpmcfg_data_t lpmcfg;
28114 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28115 +       return lpmcfg.b.inv_sel_hsic;
28116 +
28117 +}
28118 +
28119 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
28120 +{
28121 +       glpmcfg_data_t lpmcfg;
28122 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28123 +       lpmcfg.b.inv_sel_hsic = val;
28124 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28125 +}
28126 +
28127 +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
28128 +{
28129 +       return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
28130 +}
28131 +
28132 +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
28133 +{
28134 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);
28135 +}
28136 +
28137 +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
28138 +{
28139 +       return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
28140 +}
28141 +
28142 +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
28143 +{
28144 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);
28145 +}
28146 +
28147 +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
28148 +{
28149 +       return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
28150 +}
28151 +
28152 +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28153 +{
28154 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);
28155 +}
28156 +
28157 +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
28158 +{
28159 +       return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
28160 +}
28161 +
28162 +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28163 +{
28164 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);
28165 +}
28166 +
28167 +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
28168 +{
28169 +       return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);
28170 +}
28171 +
28172 +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
28173 +{
28174 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);
28175 +}
28176 +
28177 +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
28178 +{
28179 +       return DWC_READ_REG32(&core_if->core_global_regs->ggpio);
28180 +}
28181 +
28182 +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
28183 +{
28184 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);
28185 +}
28186 +
28187 +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
28188 +{
28189 +       return DWC_READ_REG32(core_if->host_if->hprt0);
28190 +
28191 +}
28192 +
28193 +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
28194 +{
28195 +       DWC_WRITE_REG32(core_if->host_if->hprt0, val);
28196 +}
28197 +
28198 +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
28199 +{
28200 +       return DWC_READ_REG32(&core_if->core_global_regs->guid);
28201 +}
28202 +
28203 +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
28204 +{
28205 +       DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);
28206 +}
28207 +
28208 +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
28209 +{
28210 +       return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
28211 +}
28212 +
28213 +uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)
28214 +{
28215 +       return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);
28216 +}
28217 +
28218 +/**
28219 + * Start the SRP timer to detect when the SRP does not complete within
28220 + * 6 seconds.
28221 + *
28222 + * @param core_if the pointer to core_if strucure.
28223 + */
28224 +void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)
28225 +{
28226 +       core_if->srp_timer_started = 1;
28227 +       DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );
28228 +}
28229 +
28230 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)
28231 +{
28232 +       uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);
28233 +       gotgctl_data_t mem;
28234 +       gotgctl_data_t val;
28235 +
28236 +       val.d32 = DWC_READ_REG32(addr);
28237 +       if (val.b.sesreq) {
28238 +               DWC_ERROR("Session Request Already active!\n");
28239 +               return;
28240 +       }
28241 +
28242 +       DWC_INFO("Session Request Initated\n"); //NOTICE
28243 +       mem.d32 = DWC_READ_REG32(addr);
28244 +       mem.b.sesreq = 1;
28245 +       DWC_WRITE_REG32(addr, mem.d32);
28246 +
28247 +       /* Start the SRP timer */
28248 +       dwc_otg_pcd_start_srp_timer(core_if);
28249 +       return;
28250 +}
28251 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
28252 new file mode 100644
28253 index 0000000..79dbf83
28254 --- /dev/null
28255 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
28256 @@ -0,0 +1,1464 @@
28257 +/* ==========================================================================
28258 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
28259 + * $Revision: #123 $
28260 + * $Date: 2012/08/10 $
28261 + * $Change: 2047372 $
28262 + *
28263 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
28264 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
28265 + * otherwise expressly agreed to in writing between Synopsys and you.
28266 + *
28267 + * The Software IS NOT an item of Licensed Software or Licensed Product under
28268 + * any End User Software License Agreement or Agreement for Licensed Product
28269 + * with Synopsys or any supplement thereto. You are permitted to use and
28270 + * redistribute this Software in source and binary forms, with or without
28271 + * modification, provided that redistributions of source code must retain this
28272 + * notice. You may not view, use, disclose, copy or distribute this file or
28273 + * any information contained herein except pursuant to this license grant from
28274 + * Synopsys. If you do not agree with this notice, including the disclaimer
28275 + * below, then you are not authorized to use the Software.
28276 + *
28277 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
28278 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28279 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28280 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
28281 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28282 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28283 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28284 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28285 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28286 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28287 + * DAMAGE.
28288 + * ========================================================================== */
28289 +
28290 +#if !defined(__DWC_CIL_H__)
28291 +#define __DWC_CIL_H__
28292 +
28293 +#include "dwc_list.h"
28294 +#include "dwc_otg_dbg.h"
28295 +#include "dwc_otg_regs.h"
28296 +
28297 +#include "dwc_otg_core_if.h"
28298 +#include "dwc_otg_adp.h"
28299 +
28300 +/**
28301 + * @file
28302 + * This file contains the interface to the Core Interface Layer.
28303 + */
28304 +
28305 +#ifdef DWC_UTE_CFI
28306 +
28307 +#define MAX_DMA_DESCS_PER_EP   256
28308 +
28309 +/**
28310 + * Enumeration for the data buffer mode
28311 + */
28312 +typedef enum _data_buffer_mode {
28313 +       BM_STANDARD = 0,        /* data buffer is in normal mode */
28314 +       BM_SG = 1,              /* data buffer uses the scatter/gather mode */
28315 +       BM_CONCAT = 2,          /* data buffer uses the concatenation mode */
28316 +       BM_CIRCULAR = 3,        /* data buffer uses the circular DMA mode */
28317 +       BM_ALIGN = 4            /* data buffer is in buffer alignment mode */
28318 +} data_buffer_mode_e;
28319 +#endif //DWC_UTE_CFI
28320 +
28321 +/** Macros defined for DWC OTG HW Release version */
28322 +
28323 +#define OTG_CORE_REV_2_60a     0x4F54260A
28324 +#define OTG_CORE_REV_2_71a     0x4F54271A
28325 +#define OTG_CORE_REV_2_72a     0x4F54272A
28326 +#define OTG_CORE_REV_2_80a     0x4F54280A
28327 +#define OTG_CORE_REV_2_81a     0x4F54281A
28328 +#define OTG_CORE_REV_2_90a     0x4F54290A
28329 +#define OTG_CORE_REV_2_91a     0x4F54291A
28330 +#define OTG_CORE_REV_2_92a     0x4F54292A
28331 +#define OTG_CORE_REV_2_93a     0x4F54293A
28332 +#define OTG_CORE_REV_2_94a     0x4F54294A
28333 +#define OTG_CORE_REV_3_00a     0x4F54300A
28334 +
28335 +/**
28336 + * Information for each ISOC packet.
28337 + */
28338 +typedef struct iso_pkt_info {
28339 +       uint32_t offset;
28340 +       uint32_t length;
28341 +       int32_t status;
28342 +} iso_pkt_info_t;
28343 +
28344 +/**
28345 + * The <code>dwc_ep</code> structure represents the state of a single
28346 + * endpoint when acting in device mode. It contains the data items
28347 + * needed for an endpoint to be activated and transfer packets.
28348 + */
28349 +typedef struct dwc_ep {
28350 +       /** EP number used for register address lookup */
28351 +       uint8_t num;
28352 +       /** EP direction 0 = OUT */
28353 +       unsigned is_in:1;
28354 +       /** EP active. */
28355 +       unsigned active:1;
28356 +
28357 +       /**
28358 +        * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
28359 +        * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
28360 +       unsigned tx_fifo_num:4;
28361 +       /** EP type: 0 - Control, 1 - ISOC,      2 - BULK,      3 - INTR */
28362 +       unsigned type:2;
28363 +#define DWC_OTG_EP_TYPE_CONTROL           0
28364 +#define DWC_OTG_EP_TYPE_ISOC      1
28365 +#define DWC_OTG_EP_TYPE_BULK      2
28366 +#define DWC_OTG_EP_TYPE_INTR      3
28367 +
28368 +       /** DATA start PID for INTR and BULK EP */
28369 +       unsigned data_pid_start:1;
28370 +       /** Frame (even/odd) for ISOC EP */
28371 +       unsigned even_odd_frame:1;
28372 +       /** Max Packet bytes */
28373 +       unsigned maxpacket:11;
28374 +
28375 +       /** Max Transfer size */
28376 +       uint32_t maxxfer;
28377 +
28378 +       /** @name Transfer state */
28379 +       /** @{ */
28380 +
28381 +       /**
28382 +        * Pointer to the beginning of the transfer buffer -- do not modify
28383 +        * during transfer.
28384 +        */
28385 +
28386 +       dwc_dma_t dma_addr;
28387 +
28388 +       dwc_dma_t dma_desc_addr;
28389 +       dwc_otg_dev_dma_desc_t *desc_addr;
28390 +
28391 +       uint8_t *start_xfer_buff;
28392 +       /** pointer to the transfer buffer */
28393 +       uint8_t *xfer_buff;
28394 +       /** Number of bytes to transfer */
28395 +       unsigned xfer_len:19;
28396 +       /** Number of bytes transferred. */
28397 +       unsigned xfer_count:19;
28398 +       /** Sent ZLP */
28399 +       unsigned sent_zlp:1;
28400 +       /** Total len for control transfer */
28401 +       unsigned total_len:19;
28402 +
28403 +       /** stall clear flag */
28404 +       unsigned stall_clear_flag:1;
28405 +
28406 +       /** SETUP pkt cnt rollover flag for EP0 out*/
28407 +       unsigned stp_rollover;
28408 +
28409 +#ifdef DWC_UTE_CFI
28410 +       /* The buffer mode */
28411 +       data_buffer_mode_e buff_mode;
28412 +
28413 +       /* The chain of DMA descriptors.
28414 +        * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
28415 +        */
28416 +       dwc_otg_dma_desc_t *descs;
28417 +
28418 +       /* The DMA address of the descriptors chain start */
28419 +       dma_addr_t descs_dma_addr;
28420 +       /** This variable stores the length of the last enqueued request */
28421 +       uint32_t cfi_req_len;
28422 +#endif                         //DWC_UTE_CFI
28423 +
28424 +/** Max DMA Descriptor count for any EP */
28425 +#define MAX_DMA_DESC_CNT 256
28426 +       /** Allocated DMA Desc count */
28427 +       uint32_t desc_cnt;
28428 +
28429 +       /** bInterval */
28430 +       uint32_t bInterval;
28431 +       /** Next frame num to setup next ISOC transfer */
28432 +       uint32_t frame_num;
28433 +       /** Indicates SOF number overrun in DSTS */
28434 +       uint8_t frm_overrun;
28435 +
28436 +#ifdef DWC_UTE_PER_IO
28437 +       /** Next frame num for which will be setup DMA Desc */
28438 +       uint32_t xiso_frame_num;
28439 +       /** bInterval */
28440 +       uint32_t xiso_bInterval;
28441 +       /** Count of currently active transfers - shall be either 0 or 1 */
28442 +       int xiso_active_xfers;
28443 +       int xiso_queued_xfers;
28444 +#endif
28445 +#ifdef DWC_EN_ISOC
28446 +       /**
28447 +        * Variables specific for ISOC EPs
28448 +        *
28449 +        */
28450 +       /** DMA addresses of ISOC buffers */
28451 +       dwc_dma_t dma_addr0;
28452 +       dwc_dma_t dma_addr1;
28453 +
28454 +       dwc_dma_t iso_dma_desc_addr;
28455 +       dwc_otg_dev_dma_desc_t *iso_desc_addr;
28456 +
28457 +       /** pointer to the transfer buffers */
28458 +       uint8_t *xfer_buff0;
28459 +       uint8_t *xfer_buff1;
28460 +
28461 +       /** number of ISOC Buffer is processing */
28462 +       uint32_t proc_buf_num;
28463 +       /** Interval of ISOC Buffer processing */
28464 +       uint32_t buf_proc_intrvl;
28465 +       /** Data size for regular frame */
28466 +       uint32_t data_per_frame;
28467 +
28468 +       /* todo - pattern data support is to be implemented in the future */
28469 +       /** Data size for pattern frame */
28470 +       uint32_t data_pattern_frame;
28471 +       /** Frame number of pattern data */
28472 +       uint32_t sync_frame;
28473 +
28474 +       /** bInterval */
28475 +       uint32_t bInterval;
28476 +       /** ISO Packet number per frame */
28477 +       uint32_t pkt_per_frm;
28478 +       /** Next frame num for which will be setup DMA Desc */
28479 +       uint32_t next_frame;
28480 +       /** Number of packets per buffer processing */
28481 +       uint32_t pkt_cnt;
28482 +       /** Info for all isoc packets */
28483 +       iso_pkt_info_t *pkt_info;
28484 +       /** current pkt number */
28485 +       uint32_t cur_pkt;
28486 +       /** current pkt number */
28487 +       uint8_t *cur_pkt_addr;
28488 +       /** current pkt number */
28489 +       uint32_t cur_pkt_dma_addr;
28490 +#endif                         /* DWC_EN_ISOC */
28491 +
28492 +/** @} */
28493 +} dwc_ep_t;
28494 +
28495 +/*
28496 + * Reasons for halting a host channel.
28497 + */
28498 +typedef enum dwc_otg_halt_status {
28499 +       DWC_OTG_HC_XFER_NO_HALT_STATUS,
28500 +       DWC_OTG_HC_XFER_COMPLETE,
28501 +       DWC_OTG_HC_XFER_URB_COMPLETE,
28502 +       DWC_OTG_HC_XFER_ACK,
28503 +       DWC_OTG_HC_XFER_NAK,
28504 +       DWC_OTG_HC_XFER_NYET,
28505 +       DWC_OTG_HC_XFER_STALL,
28506 +       DWC_OTG_HC_XFER_XACT_ERR,
28507 +       DWC_OTG_HC_XFER_FRAME_OVERRUN,
28508 +       DWC_OTG_HC_XFER_BABBLE_ERR,
28509 +       DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
28510 +       DWC_OTG_HC_XFER_AHB_ERR,
28511 +       DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
28512 +       DWC_OTG_HC_XFER_URB_DEQUEUE
28513 +} dwc_otg_halt_status_e;
28514 +
28515 +/**
28516 + * Host channel descriptor. This structure represents the state of a single
28517 + * host channel when acting in host mode. It contains the data items needed to
28518 + * transfer packets to an endpoint via a host channel.
28519 + */
28520 +typedef struct dwc_hc {
28521 +       /** Host channel number used for register address lookup */
28522 +       uint8_t hc_num;
28523 +
28524 +       /** Device to access */
28525 +       unsigned dev_addr:7;
28526 +
28527 +       /** EP to access */
28528 +       unsigned ep_num:4;
28529 +
28530 +       /** EP direction. 0: OUT, 1: IN */
28531 +       unsigned ep_is_in:1;
28532 +
28533 +       /**
28534 +        * EP speed.
28535 +        * One of the following values:
28536 +        *      - DWC_OTG_EP_SPEED_LOW
28537 +        *      - DWC_OTG_EP_SPEED_FULL
28538 +        *      - DWC_OTG_EP_SPEED_HIGH
28539 +        */
28540 +       unsigned speed:2;
28541 +#define DWC_OTG_EP_SPEED_LOW   0
28542 +#define DWC_OTG_EP_SPEED_FULL  1
28543 +#define DWC_OTG_EP_SPEED_HIGH  2
28544 +
28545 +       /**
28546 +        * Endpoint type.
28547 +        * One of the following values:
28548 +        *      - DWC_OTG_EP_TYPE_CONTROL: 0
28549 +        *      - DWC_OTG_EP_TYPE_ISOC: 1
28550 +        *      - DWC_OTG_EP_TYPE_BULK: 2
28551 +        *      - DWC_OTG_EP_TYPE_INTR: 3
28552 +        */
28553 +       unsigned ep_type:2;
28554 +
28555 +       /** Max packet size in bytes */
28556 +       unsigned max_packet:11;
28557 +
28558 +       /**
28559 +        * PID for initial transaction.
28560 +        * 0: DATA0,<br>
28561 +        * 1: DATA2,<br>
28562 +        * 2: DATA1,<br>
28563 +        * 3: MDATA (non-Control EP),
28564 +        *        SETUP (Control EP)
28565 +        */
28566 +       unsigned data_pid_start:2;
28567 +#define DWC_OTG_HC_PID_DATA0 0
28568 +#define DWC_OTG_HC_PID_DATA2 1
28569 +#define DWC_OTG_HC_PID_DATA1 2
28570 +#define DWC_OTG_HC_PID_MDATA 3
28571 +#define DWC_OTG_HC_PID_SETUP 3
28572 +
28573 +       /** Number of periodic transactions per (micro)frame */
28574 +       unsigned multi_count:2;
28575 +
28576 +       /** @name Transfer State */
28577 +       /** @{ */
28578 +
28579 +       /** Pointer to the current transfer buffer position. */
28580 +       uint8_t *xfer_buff;
28581 +       /**
28582 +        * In Buffer DMA mode this buffer will be used
28583 +        * if xfer_buff is not DWORD aligned.
28584 +        */
28585 +       dwc_dma_t align_buff;
28586 +       /** Total number of bytes to transfer. */
28587 +       uint32_t xfer_len;
28588 +       /** Number of bytes transferred so far. */
28589 +       uint32_t xfer_count;
28590 +       /** Packet count at start of transfer.*/
28591 +       uint16_t start_pkt_count;
28592 +
28593 +       /**
28594 +        * Flag to indicate whether the transfer has been started. Set to 1 if
28595 +        * it has been started, 0 otherwise.
28596 +        */
28597 +       uint8_t xfer_started;
28598 +
28599 +       /**
28600 +        * Set to 1 to indicate that a PING request should be issued on this
28601 +        * channel. If 0, process normally.
28602 +        */
28603 +       uint8_t do_ping;
28604 +
28605 +       /**
28606 +        * Set to 1 to indicate that the error count for this transaction is
28607 +        * non-zero. Set to 0 if the error count is 0.
28608 +        */
28609 +       uint8_t error_state;
28610 +
28611 +       /**
28612 +        * Set to 1 to indicate that this channel should be halted the next
28613 +        * time a request is queued for the channel. This is necessary in
28614 +        * slave mode if no request queue space is available when an attempt
28615 +        * is made to halt the channel.
28616 +        */
28617 +       uint8_t halt_on_queue;
28618 +
28619 +       /**
28620 +        * Set to 1 if the host channel has been halted, but the core is not
28621 +        * finished flushing queued requests. Otherwise 0.
28622 +        */
28623 +       uint8_t halt_pending;
28624 +
28625 +       /**
28626 +        * Reason for halting the host channel.
28627 +        */
28628 +       dwc_otg_halt_status_e halt_status;
28629 +
28630 +       /*
28631 +        * Split settings for the host channel
28632 +        */
28633 +       uint8_t do_split;                  /**< Enable split for the channel */
28634 +       uint8_t complete_split;    /**< Enable complete split */
28635 +       uint8_t hub_addr;                  /**< Address of high speed hub */
28636 +
28637 +       uint8_t port_addr;                 /**< Port of the low/full speed device */
28638 +       /** Split transaction position
28639 +        * One of the following values:
28640 +        *        - DWC_HCSPLIT_XACTPOS_MID
28641 +        *        - DWC_HCSPLIT_XACTPOS_BEGIN
28642 +        *        - DWC_HCSPLIT_XACTPOS_END
28643 +        *        - DWC_HCSPLIT_XACTPOS_ALL */
28644 +       uint8_t xact_pos;
28645 +
28646 +       /** Set when the host channel does a short read. */
28647 +       uint8_t short_read;
28648 +
28649 +       /**
28650 +        * Number of requests issued for this channel since it was assigned to
28651 +        * the current transfer (not counting PINGs).
28652 +        */
28653 +       uint8_t requests;
28654 +
28655 +       /**
28656 +        * Queue Head for the transfer being processed by this channel.
28657 +        */
28658 +       struct dwc_otg_qh *qh;
28659 +
28660 +       /** @} */
28661 +
28662 +       /** Entry in list of host channels. */
28663 +        DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
28664 +
28665 +       /** @name Descriptor DMA support */
28666 +       /** @{ */
28667 +
28668 +       /** Number of Transfer Descriptors */
28669 +       uint16_t ntd;
28670 +
28671 +       /** Descriptor List DMA address */
28672 +       dwc_dma_t desc_list_addr;
28673 +
28674 +       /** Scheduling micro-frame bitmap. */
28675 +       uint8_t schinfo;
28676 +
28677 +       /** @} */
28678 +} dwc_hc_t;
28679 +
28680 +/**
28681 + * The following parameters may be specified when starting the module. These
28682 + * parameters define how the DWC_otg controller should be configured.
28683 + */
28684 +typedef struct dwc_otg_core_params {
28685 +       int32_t opt;
28686 +
28687 +       /**
28688 +        * Specifies the OTG capabilities. The driver will automatically
28689 +        * detect the value for this parameter if none is specified.
28690 +        * 0 - HNP and SRP capable (default)
28691 +        * 1 - SRP Only capable
28692 +        * 2 - No HNP/SRP capable
28693 +        */
28694 +       int32_t otg_cap;
28695 +
28696 +       /**
28697 +        * Specifies whether to use slave or DMA mode for accessing the data
28698 +        * FIFOs. The driver will automatically detect the value for this
28699 +        * parameter if none is specified.
28700 +        * 0 - Slave
28701 +        * 1 - DMA (default, if available)
28702 +        */
28703 +       int32_t dma_enable;
28704 +
28705 +       /**
28706 +        * When DMA mode is enabled specifies whether to use address DMA or DMA
28707 +        * Descriptor mode for accessing the data FIFOs in device mode. The driver
28708 +        * will automatically detect the value for this if none is specified.
28709 +        * 0 - address DMA
28710 +        * 1 - DMA Descriptor(default, if available)
28711 +        */
28712 +       int32_t dma_desc_enable;
28713 +       /** The DMA Burst size (applicable only for External DMA
28714 +        * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
28715 +        */
28716 +       int32_t dma_burst_size; /* Translate this to GAHBCFG values */
28717 +
28718 +       /**
28719 +        * Specifies the maximum speed of operation in host and device mode.
28720 +        * The actual speed depends on the speed of the attached device and
28721 +        * the value of phy_type. The actual speed depends on the speed of the
28722 +        * attached device.
28723 +        * 0 - High Speed (default)
28724 +        * 1 - Full Speed
28725 +        */
28726 +       int32_t speed;
28727 +       /** Specifies whether low power mode is supported when attached
28728 +        *      to a Full Speed or Low Speed device in host mode.
28729 +        * 0 - Don't support low power mode (default)
28730 +        * 1 - Support low power mode
28731 +        */
28732 +       int32_t host_support_fs_ls_low_power;
28733 +
28734 +       /** Specifies the PHY clock rate in low power mode when connected to a
28735 +        * Low Speed device in host mode. This parameter is applicable only if
28736 +        * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
28737 +        * then defaults to 6 MHZ otherwise 48 MHZ.
28738 +        *
28739 +        * 0 - 48 MHz
28740 +        * 1 - 6 MHz
28741 +        */
28742 +       int32_t host_ls_low_power_phy_clk;
28743 +
28744 +       /**
28745 +        * 0 - Use cC FIFO size parameters
28746 +        * 1 - Allow dynamic FIFO sizing (default)
28747 +        */
28748 +       int32_t enable_dynamic_fifo;
28749 +
28750 +       /** Total number of 4-byte words in the data FIFO memory. This
28751 +        * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
28752 +        * Tx FIFOs.
28753 +        * 32 to 32768 (default 8192)
28754 +        * Note: The total FIFO memory depth in the FPGA configuration is 8192.
28755 +        */
28756 +       int32_t data_fifo_size;
28757 +
28758 +       /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
28759 +        * FIFO sizing is enabled.
28760 +        * 16 to 32768 (default 1064)
28761 +        */
28762 +       int32_t dev_rx_fifo_size;
28763 +
28764 +       /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
28765 +        * when dynamic FIFO sizing is enabled.
28766 +        * 16 to 32768 (default 1024)
28767 +        */
28768 +       int32_t dev_nperio_tx_fifo_size;
28769 +
28770 +       /** Number of 4-byte words in each of the periodic Tx FIFOs in device
28771 +        * mode when dynamic FIFO sizing is enabled.
28772 +        * 4 to 768 (default 256)
28773 +        */
28774 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
28775 +
28776 +       /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
28777 +        * FIFO sizing is enabled.
28778 +        * 16 to 32768 (default 1024)
28779 +        */
28780 +       int32_t host_rx_fifo_size;
28781 +
28782 +       /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
28783 +        * when Dynamic FIFO sizing is enabled in the core.
28784 +        * 16 to 32768 (default 1024)
28785 +        */
28786 +       int32_t host_nperio_tx_fifo_size;
28787 +
28788 +       /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
28789 +        * FIFO sizing is enabled.
28790 +        * 16 to 32768 (default 1024)
28791 +        */
28792 +       int32_t host_perio_tx_fifo_size;
28793 +
28794 +       /** The maximum transfer size supported in bytes.
28795 +        * 2047 to 65,535  (default 65,535)
28796 +        */
28797 +       int32_t max_transfer_size;
28798 +
28799 +       /** The maximum number of packets in a transfer.
28800 +        * 15 to 511  (default 511)
28801 +        */
28802 +       int32_t max_packet_count;
28803 +
28804 +       /** The number of host channel registers to use.
28805 +        * 1 to 16 (default 12)
28806 +        * Note: The FPGA configuration supports a maximum of 12 host channels.
28807 +        */
28808 +       int32_t host_channels;
28809 +
28810 +       /** The number of endpoints in addition to EP0 available for device
28811 +        * mode operations.
28812 +        * 1 to 15 (default 6 IN and OUT)
28813 +        * Note: The FPGA configuration supports a maximum of 6 IN and OUT
28814 +        * endpoints in addition to EP0.
28815 +        */
28816 +       int32_t dev_endpoints;
28817 +
28818 +               /**
28819 +                * Specifies the type of PHY interface to use. By default, the driver
28820 +                * will automatically detect the phy_type.
28821 +                *
28822 +                * 0 - Full Speed PHY
28823 +                * 1 - UTMI+ (default)
28824 +                * 2 - ULPI
28825 +                */
28826 +       int32_t phy_type;
28827 +
28828 +       /**
28829 +        * Specifies the UTMI+ Data Width. This parameter is
28830 +        * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
28831 +        * PHY_TYPE, this parameter indicates the data width between
28832 +        * the MAC and the ULPI Wrapper.) Also, this parameter is
28833 +        * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
28834 +        * to "8 and 16 bits", meaning that the core has been
28835 +        * configured to work at either data path width.
28836 +        *
28837 +        * 8 or 16 bits (default 16)
28838 +        */
28839 +       int32_t phy_utmi_width;
28840 +
28841 +       /**
28842 +        * Specifies whether the ULPI operates at double or single
28843 +        * data rate. This parameter is only applicable if PHY_TYPE is
28844 +        * ULPI.
28845 +        *
28846 +        * 0 - single data rate ULPI interface with 8 bit wide data
28847 +        * bus (default)
28848 +        * 1 - double data rate ULPI interface with 4 bit wide data
28849 +        * bus
28850 +        */
28851 +       int32_t phy_ulpi_ddr;
28852 +
28853 +       /**
28854 +        * Specifies whether to use the internal or external supply to
28855 +        * drive the vbus with a ULPI phy.
28856 +        */
28857 +       int32_t phy_ulpi_ext_vbus;
28858 +
28859 +       /**
28860 +        * Specifies whether to use the I2Cinterface for full speed PHY. This
28861 +        * parameter is only applicable if PHY_TYPE is FS.
28862 +        * 0 - No (default)
28863 +        * 1 - Yes
28864 +        */
28865 +       int32_t i2c_enable;
28866 +
28867 +       int32_t ulpi_fs_ls;
28868 +
28869 +       int32_t ts_dline;
28870 +
28871 +       /**
28872 +        * Specifies whether dedicated transmit FIFOs are
28873 +        * enabled for non periodic IN endpoints in device mode
28874 +        * 0 - No
28875 +        * 1 - Yes
28876 +        */
28877 +       int32_t en_multiple_tx_fifo;
28878 +
28879 +       /** Number of 4-byte words in each of the Tx FIFOs in device
28880 +        * mode when dynamic FIFO sizing is enabled.
28881 +        * 4 to 768 (default 256)
28882 +        */
28883 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
28884 +
28885 +       /** Thresholding enable flag-
28886 +        * bit 0 - enable non-ISO Tx thresholding
28887 +        * bit 1 - enable ISO Tx thresholding
28888 +        * bit 2 - enable Rx thresholding
28889 +        */
28890 +       uint32_t thr_ctl;
28891 +
28892 +       /** Thresholding length for Tx
28893 +        *      FIFOs in 32 bit DWORDs
28894 +        */
28895 +       uint32_t tx_thr_length;
28896 +
28897 +       /** Thresholding length for Rx
28898 +        *      FIFOs in 32 bit DWORDs
28899 +        */
28900 +       uint32_t rx_thr_length;
28901 +
28902 +       /**
28903 +        * Specifies whether LPM (Link Power Management) support is enabled
28904 +        */
28905 +       int32_t lpm_enable;
28906 +
28907 +       /** Per Transfer Interrupt
28908 +        *      mode enable flag
28909 +        * 1 - Enabled
28910 +        * 0 - Disabled
28911 +        */
28912 +       int32_t pti_enable;
28913 +
28914 +       /** Multi Processor Interrupt
28915 +        *      mode enable flag
28916 +        * 1 - Enabled
28917 +        * 0 - Disabled
28918 +        */
28919 +       int32_t mpi_enable;
28920 +
28921 +       /** IS_USB Capability
28922 +        * 1 - Enabled
28923 +        * 0 - Disabled
28924 +        */
28925 +       int32_t ic_usb_cap;
28926 +
28927 +       /** AHB Threshold Ratio
28928 +        * 2'b00 AHB Threshold =        MAC Threshold
28929 +        * 2'b01 AHB Threshold = 1/2    MAC Threshold
28930 +        * 2'b10 AHB Threshold = 1/4    MAC Threshold
28931 +        * 2'b11 AHB Threshold = 1/8    MAC Threshold
28932 +        */
28933 +       int32_t ahb_thr_ratio;
28934 +
28935 +       /** ADP Support
28936 +        * 1 - Enabled
28937 +        * 0 - Disabled
28938 +        */
28939 +       int32_t adp_supp_enable;
28940 +
28941 +       /** HFIR Reload Control
28942 +        * 0 - The HFIR cannot be reloaded dynamically.
28943 +        * 1 - Allow dynamic reloading of the HFIR register during runtime.
28944 +        */
28945 +       int32_t reload_ctl;
28946 +
28947 +       /** DCFG: Enable device Out NAK
28948 +        * 0 - The core does not set NAK after Bulk Out transfer complete.
28949 +        * 1 - The core sets NAK after Bulk OUT transfer complete.
28950 +        */
28951 +       int32_t dev_out_nak;
28952 +
28953 +       /** DCFG: Enable Continue on BNA
28954 +        * After receiving BNA interrupt the core disables the endpoint,when the
28955 +        * endpoint is re-enabled by the application the core starts processing
28956 +        * 0 - from the DOEPDMA descriptor
28957 +        * 1 - from the descriptor which received the BNA.
28958 +        */
28959 +       int32_t cont_on_bna;
28960 +
28961 +       /** GAHBCFG: AHB Single Support
28962 +        * This bit when programmed supports SINGLE transfers for remainder
28963 +        * data in a transfer for DMA mode of operation.
28964 +        * 0 - in this case the remainder data will be sent using INCR burst size.
28965 +        * 1 - in this case the remainder data will be sent using SINGLE burst size.
28966 +        */
28967 +       int32_t ahb_single;
28968 +
28969 +       /** Core Power down mode
28970 +        * 0 - No Power Down is enabled
28971 +        * 1 - Reserved
28972 +        * 2 - Complete Power Down (Hibernation)
28973 +        */
28974 +       int32_t power_down;
28975 +
28976 +       /** OTG revision supported
28977 +        * 0 - OTG 1.3 revision
28978 +        * 1 - OTG 2.0 revision
28979 +        */
28980 +       int32_t otg_ver;
28981 +
28982 +} dwc_otg_core_params_t;
28983 +
28984 +#ifdef DEBUG
28985 +struct dwc_otg_core_if;
28986 +typedef struct hc_xfer_info {
28987 +       struct dwc_otg_core_if *core_if;
28988 +       dwc_hc_t *hc;
28989 +} hc_xfer_info_t;
28990 +#endif
28991 +
28992 +typedef struct ep_xfer_info {
28993 +       struct dwc_otg_core_if *core_if;
28994 +       dwc_ep_t *ep;
28995 +       uint8_t state;
28996 +} ep_xfer_info_t;
28997 +/*
28998 + * Device States
28999 + */
29000 +typedef enum dwc_otg_lx_state {
29001 +       /** On state */
29002 +       DWC_OTG_L0,
29003 +       /** LPM sleep state*/
29004 +       DWC_OTG_L1,
29005 +       /** USB suspend state*/
29006 +       DWC_OTG_L2,
29007 +       /** Off state*/
29008 +       DWC_OTG_L3
29009 +} dwc_otg_lx_state_e;
29010 +
29011 +struct dwc_otg_global_regs_backup {
29012 +       uint32_t gotgctl_local;
29013 +       uint32_t gintmsk_local;
29014 +       uint32_t gahbcfg_local;
29015 +       uint32_t gusbcfg_local;
29016 +       uint32_t grxfsiz_local;
29017 +       uint32_t gnptxfsiz_local;
29018 +#ifdef CONFIG_USB_DWC_OTG_LPM
29019 +       uint32_t glpmcfg_local;
29020 +#endif
29021 +       uint32_t gi2cctl_local;
29022 +       uint32_t hptxfsiz_local;
29023 +       uint32_t pcgcctl_local;
29024 +       uint32_t gdfifocfg_local;
29025 +       uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];
29026 +       uint32_t gpwrdn_local;
29027 +       uint32_t xhib_pcgcctl;
29028 +       uint32_t xhib_gpwrdn;
29029 +};
29030 +
29031 +struct dwc_otg_host_regs_backup {
29032 +       uint32_t hcfg_local;
29033 +       uint32_t haintmsk_local;
29034 +       uint32_t hcintmsk_local[MAX_EPS_CHANNELS];
29035 +       uint32_t hprt0_local;
29036 +       uint32_t hfir_local;
29037 +};
29038 +
29039 +struct dwc_otg_dev_regs_backup {
29040 +       uint32_t dcfg;
29041 +       uint32_t dctl;
29042 +       uint32_t daintmsk;
29043 +       uint32_t diepmsk;
29044 +       uint32_t doepmsk;
29045 +       uint32_t diepctl[MAX_EPS_CHANNELS];
29046 +       uint32_t dieptsiz[MAX_EPS_CHANNELS];
29047 +       uint32_t diepdma[MAX_EPS_CHANNELS];
29048 +};
29049 +/**
29050 + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
29051 + * the DWC_otg controller acting in either host or device mode. It
29052 + * represents the programming view of the controller as a whole.
29053 + */
29054 +struct dwc_otg_core_if {
29055 +       /** Parameters that define how the core should be configured.*/
29056 +       dwc_otg_core_params_t *core_params;
29057 +
29058 +       /** Core Global registers starting at offset 000h. */
29059 +       dwc_otg_core_global_regs_t *core_global_regs;
29060 +
29061 +       /** Device-specific information */
29062 +       dwc_otg_dev_if_t *dev_if;
29063 +       /** Host-specific information */
29064 +       dwc_otg_host_if_t *host_if;
29065 +
29066 +       /** Value from SNPSID register */
29067 +       uint32_t snpsid;
29068 +
29069 +       /*
29070 +        * Set to 1 if the core PHY interface bits in USBCFG have been
29071 +        * initialized.
29072 +        */
29073 +       uint8_t phy_init_done;
29074 +
29075 +       /*
29076 +        * SRP Success flag, set by srp success interrupt in FS I2C mode
29077 +        */
29078 +       uint8_t srp_success;
29079 +       uint8_t srp_timer_started;
29080 +       /** Timer for SRP. If it expires before SRP is successful
29081 +        * clear the SRP. */
29082 +       dwc_timer_t *srp_timer;
29083 +
29084 +#ifdef DWC_DEV_SRPCAP
29085 +       /* This timer is needed to power on the hibernated host core if SRP is not
29086 +        * initiated on connected SRP capable device for limited period of time
29087 +        */
29088 +       uint8_t pwron_timer_started;
29089 +       dwc_timer_t *pwron_timer;
29090 +#endif
29091 +       /* Common configuration information */
29092 +       /** Power and Clock Gating Control Register */
29093 +       volatile uint32_t *pcgcctl;
29094 +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
29095 +
29096 +       /** Push/pop addresses for endpoints or host channels.*/
29097 +       uint32_t *data_fifo[MAX_EPS_CHANNELS];
29098 +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
29099 +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
29100 +
29101 +       /** Total RAM for FIFOs (Bytes) */
29102 +       uint16_t total_fifo_size;
29103 +       /** Size of Rx FIFO (Bytes) */
29104 +       uint16_t rx_fifo_size;
29105 +       /** Size of Non-periodic Tx FIFO (Bytes) */
29106 +       uint16_t nperio_tx_fifo_size;
29107 +
29108 +       /** 1 if DMA is enabled, 0 otherwise. */
29109 +       uint8_t dma_enable;
29110 +
29111 +       /** 1 if DMA descriptor is enabled, 0 otherwise. */
29112 +       uint8_t dma_desc_enable;
29113 +
29114 +       /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
29115 +       uint8_t pti_enh_enable;
29116 +
29117 +       /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
29118 +       uint8_t multiproc_int_enable;
29119 +
29120 +       /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
29121 +       uint8_t en_multiple_tx_fifo;
29122 +
29123 +       /** Set to 1 if multiple packets of a high-bandwidth transfer is in
29124 +        * process of being queued */
29125 +       uint8_t queuing_high_bandwidth;
29126 +
29127 +       /** Hardware Configuration -- stored here for convenience.*/
29128 +       hwcfg1_data_t hwcfg1;
29129 +       hwcfg2_data_t hwcfg2;
29130 +       hwcfg3_data_t hwcfg3;
29131 +       hwcfg4_data_t hwcfg4;
29132 +       fifosize_data_t hptxfsiz;
29133 +
29134 +       /** Host and Device Configuration -- stored here for convenience.*/
29135 +       hcfg_data_t hcfg;
29136 +       dcfg_data_t dcfg;
29137 +
29138 +       /** The operational State, during transations
29139 +        * (a_host>>a_peripherial and b_device=>b_host) this may not
29140 +        * match the core but allows the software to determine
29141 +        * transitions.
29142 +        */
29143 +       uint8_t op_state;
29144 +
29145 +       /**
29146 +        * Set to 1 if the HCD needs to be restarted on a session request
29147 +        * interrupt. This is required if no connector ID status change has
29148 +        * occurred since the HCD was last disconnected.
29149 +        */
29150 +       uint8_t restart_hcd_on_session_req;
29151 +
29152 +       /** HCD callbacks */
29153 +       /** A-Device is a_host */
29154 +#define A_HOST         (1)
29155 +       /** A-Device is a_suspend */
29156 +#define A_SUSPEND      (2)
29157 +       /** A-Device is a_peripherial */
29158 +#define A_PERIPHERAL   (3)
29159 +       /** B-Device is operating as a Peripheral. */
29160 +#define B_PERIPHERAL   (4)
29161 +       /** B-Device is operating as a Host. */
29162 +#define B_HOST         (5)
29163 +
29164 +       /** HCD callbacks */
29165 +       struct dwc_otg_cil_callbacks *hcd_cb;
29166 +       /** PCD callbacks */
29167 +       struct dwc_otg_cil_callbacks *pcd_cb;
29168 +
29169 +       /** Device mode Periodic Tx FIFO Mask */
29170 +       uint32_t p_tx_msk;
29171 +       /** Device mode Periodic Tx FIFO Mask */
29172 +       uint32_t tx_msk;
29173 +
29174 +       /** Workqueue object used for handling several interrupts */
29175 +       dwc_workq_t *wq_otg;
29176 +
29177 +       /** Timer object used for handling "Wakeup Detected" Interrupt */
29178 +       dwc_timer_t *wkp_timer;
29179 +       /** This arrays used for debug purposes for DEV OUT NAK enhancement */
29180 +       uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];
29181 +       ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];
29182 +       dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];
29183 +#ifdef DEBUG
29184 +       uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
29185 +
29186 +       hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
29187 +       dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
29188 +
29189 +       uint32_t hfnum_7_samples;
29190 +       uint64_t hfnum_7_frrem_accum;
29191 +       uint32_t hfnum_0_samples;
29192 +       uint64_t hfnum_0_frrem_accum;
29193 +       uint32_t hfnum_other_samples;
29194 +       uint64_t hfnum_other_frrem_accum;
29195 +#endif
29196 +
29197 +#ifdef DWC_UTE_CFI
29198 +       uint16_t pwron_rxfsiz;
29199 +       uint16_t pwron_gnptxfsiz;
29200 +       uint16_t pwron_txfsiz[15];
29201 +
29202 +       uint16_t init_rxfsiz;
29203 +       uint16_t init_gnptxfsiz;
29204 +       uint16_t init_txfsiz[15];
29205 +#endif
29206 +
29207 +       /** Lx state of device */
29208 +       dwc_otg_lx_state_e lx_state;
29209 +
29210 +       /** Saved Core Global registers */
29211 +       struct dwc_otg_global_regs_backup *gr_backup;
29212 +       /** Saved Host registers */
29213 +       struct dwc_otg_host_regs_backup *hr_backup;
29214 +       /** Saved Device registers */
29215 +       struct dwc_otg_dev_regs_backup *dr_backup;
29216 +
29217 +       /** Power Down Enable */
29218 +       uint32_t power_down;
29219 +
29220 +       /** ADP support Enable */
29221 +       uint32_t adp_enable;
29222 +
29223 +       /** ADP structure object */
29224 +       dwc_otg_adp_t adp;
29225 +
29226 +       /** hibernation/suspend flag */
29227 +       int hibernation_suspend;
29228 +
29229 +       /** Device mode extended hibernation flag */
29230 +       int xhib;
29231 +
29232 +       /** OTG revision supported */
29233 +       uint32_t otg_ver;
29234 +
29235 +       /** OTG status flag used for HNP polling */
29236 +       uint8_t otg_sts;
29237 +
29238 +       /** Pointer to either hcd->lock or pcd->lock */
29239 +       dwc_spinlock_t *lock;
29240 +
29241 +       /** Start predict NextEP based on Learning Queue if equal 1,
29242 +        * also used as counter of disabled NP IN EP's */
29243 +       uint8_t start_predict;
29244 +
29245 +       /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and
29246 +        * active, 0xff otherwise */
29247 +       uint8_t nextep_seq[MAX_EPS_CHANNELS];
29248 +
29249 +       /** Index of fisrt EP in nextep_seq array which should be re-enabled **/
29250 +       uint8_t first_in_nextep_seq;
29251 +
29252 +       /** Frame number while entering to ISR - needed for ISOCs **/
29253 +       uint32_t frame_num;
29254 +
29255 +};
29256 +
29257 +#ifdef DEBUG
29258 +/*
29259 + * This function is called when transfer is timed out.
29260 + */
29261 +extern void hc_xfer_timeout(void *ptr);
29262 +#endif
29263 +
29264 +/*
29265 + * This function is called when transfer is timed out on endpoint.
29266 + */
29267 +extern void ep_xfer_timeout(void *ptr);
29268 +
29269 +/*
29270 + * The following functions are functions for works
29271 + * using during handling some interrupts
29272 + */
29273 +extern void w_conn_id_status_change(void *p);
29274 +
29275 +extern void w_wakeup_detected(void *p);
29276 +
29277 +/** Saves global register values into system memory. */
29278 +extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);
29279 +/** Saves device register values into system memory. */
29280 +extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);
29281 +/** Saves host register values into system memory. */
29282 +extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);
29283 +/** Restore global register values. */
29284 +extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);
29285 +/** Restore host register values. */
29286 +extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);
29287 +/** Restore device register values. */
29288 +extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,
29289 +                                   int rem_wakeup);
29290 +extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);
29291 +extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,
29292 +                                 int is_host);
29293 +
29294 +extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
29295 +                                           int restore_mode, int reset);
29296 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
29297 +                                             int rem_wakeup, int reset);
29298 +
29299 +/*
29300 + * The following functions support initialization of the CIL driver component
29301 + * and the DWC_otg controller.
29302 + */
29303 +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
29304 +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
29305 +
29306 +/** @name Device CIL Functions
29307 + * The following functions support managing the DWC_otg controller in device
29308 + * mode.
29309 + */
29310 +/**@{*/
29311 +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
29312 +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
29313 +                                     uint32_t * _dest);
29314 +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
29315 +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29316 +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29317 +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29318 +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
29319 +                                     dwc_ep_t * _ep);
29320 +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
29321 +                                        dwc_ep_t * _ep);
29322 +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
29323 +                                      dwc_ep_t * _ep);
29324 +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
29325 +                                         dwc_ep_t * _ep);
29326 +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
29327 +                                   dwc_ep_t * _ep, int _dma);
29328 +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29329 +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
29330 +                                  dwc_ep_t * _ep);
29331 +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
29332 +
29333 +#ifdef DWC_EN_ISOC
29334 +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
29335 +                                             dwc_ep_t * ep);
29336 +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
29337 +                                             dwc_ep_t * ep);
29338 +#endif /* DWC_EN_ISOC */
29339 +/**@}*/
29340 +
29341 +/** @name Host CIL Functions
29342 + * The following functions support managing the DWC_otg controller in host
29343 + * mode.
29344 + */
29345 +/**@{*/
29346 +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29347 +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
29348 +                           dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
29349 +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29350 +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
29351 +                                     dwc_hc_t * _hc);
29352 +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
29353 +                                       dwc_hc_t * _hc);
29354 +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29355 +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
29356 +                                   dwc_hc_t * _hc);
29357 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
29358 +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
29359 +
29360 +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,
29361 +                                          dwc_hc_t * hc);
29362 +
29363 +extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);
29364 +
29365 +/* Macro used to clear one channel interrupt */
29366 +#define clear_hc_int(_hc_regs_, _intr_) \
29367 +do { \
29368 +       hcint_data_t hcint_clear = {.d32 = 0}; \
29369 +       hcint_clear.b._intr_ = 1; \
29370 +       DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \
29371 +} while (0)
29372 +
29373 +/*
29374 + * Macro used to disable one channel interrupt. Channel interrupts are
29375 + * disabled when the channel is halted or released by the interrupt handler.
29376 + * There is no need to handle further interrupts of that type until the
29377 + * channel is re-assigned. In fact, subsequent handling may cause crashes
29378 + * because the channel structures are cleaned up when the channel is released.
29379 + */
29380 +#define disable_hc_int(_hc_regs_, _intr_) \
29381 +do { \
29382 +       hcintmsk_data_t hcintmsk = {.d32 = 0}; \
29383 +       hcintmsk.b._intr_ = 1; \
29384 +       DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
29385 +} while (0)
29386 +
29387 +/**
29388 + * This function Reads HPRT0 in preparation to modify. It keeps the
29389 + * WC bits 0 so that if they are read as 1, they won't clear when you
29390 + * write it back
29391 + */
29392 +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
29393 +{
29394 +       hprt0_data_t hprt0;
29395 +       hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);
29396 +       hprt0.b.prtena = 0;
29397 +       hprt0.b.prtconndet = 0;
29398 +       hprt0.b.prtenchng = 0;
29399 +       hprt0.b.prtovrcurrchng = 0;
29400 +       return hprt0.d32;
29401 +}
29402 +
29403 +/**@}*/
29404 +
29405 +/** @name Common CIL Functions
29406 + * The following functions support managing the DWC_otg controller in either
29407 + * device or host mode.
29408 + */
29409 +/**@{*/
29410 +
29411 +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
29412 +                               uint8_t * dest, uint16_t bytes);
29413 +
29414 +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
29415 +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
29416 +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
29417 +
29418 +/**
29419 + * This function returns the Core Interrupt register.
29420 + */
29421 +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
29422 +{
29423 +       return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
29424 +               DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
29425 +}
29426 +
29427 +/**
29428 + * This function returns the OTG Interrupt register.
29429 + */
29430 +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
29431 +{
29432 +       return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));
29433 +}
29434 +
29435 +/**
29436 + * This function reads the Device All Endpoints Interrupt register and
29437 + * returns the IN endpoint interrupt bits.
29438 + */
29439 +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
29440 +                                                      core_if)
29441 +{
29442 +
29443 +       uint32_t v;
29444 +
29445 +       if (core_if->multiproc_int_enable) {
29446 +               v = DWC_READ_REG32(&core_if->dev_if->
29447 +                                  dev_global_regs->deachint) &
29448 +                   DWC_READ_REG32(&core_if->
29449 +                                  dev_if->dev_global_regs->deachintmsk);
29450 +       } else {
29451 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29452 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29453 +       }
29454 +       return (v & 0xffff);
29455 +}
29456 +
29457 +/**
29458 + * This function reads the Device All Endpoints Interrupt register and
29459 + * returns the OUT endpoint interrupt bits.
29460 + */
29461 +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
29462 +                                                       core_if)
29463 +{
29464 +       uint32_t v;
29465 +
29466 +       if (core_if->multiproc_int_enable) {
29467 +               v = DWC_READ_REG32(&core_if->dev_if->
29468 +                                  dev_global_regs->deachint) &
29469 +                   DWC_READ_REG32(&core_if->
29470 +                                  dev_if->dev_global_regs->deachintmsk);
29471 +       } else {
29472 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29473 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29474 +       }
29475 +
29476 +       return ((v & 0xffff0000) >> 16);
29477 +}
29478 +
29479 +/**
29480 + * This function returns the Device IN EP Interrupt register
29481 + */
29482 +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
29483 +                                                  dwc_ep_t * ep)
29484 +{
29485 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
29486 +       uint32_t v, msk, emp;
29487 +
29488 +       if (core_if->multiproc_int_enable) {
29489 +               msk =
29490 +                   DWC_READ_REG32(&dev_if->
29491 +                                  dev_global_regs->diepeachintmsk[ep->num]);
29492 +               emp =
29493 +                   DWC_READ_REG32(&dev_if->
29494 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29495 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29496 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29497 +       } else {
29498 +               msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
29499 +               emp =
29500 +                   DWC_READ_REG32(&dev_if->
29501 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29502 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29503 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29504 +       }
29505 +
29506 +       return v;
29507 +}
29508 +
29509 +/**
29510 + * This function returns the Device OUT EP Interrupt register
29511 + */
29512 +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
29513 +                                                   _core_if, dwc_ep_t * _ep)
29514 +{
29515 +       dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
29516 +       uint32_t v;
29517 +       doepmsk_data_t msk = {.d32 = 0 };
29518 +
29519 +       if (_core_if->multiproc_int_enable) {
29520 +               msk.d32 =
29521 +                   DWC_READ_REG32(&dev_if->
29522 +                                  dev_global_regs->doepeachintmsk[_ep->num]);
29523 +               if (_core_if->pti_enh_enable) {
29524 +                       msk.b.pktdrpsts = 1;
29525 +               }
29526 +               v = DWC_READ_REG32(&dev_if->
29527 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29528 +       } else {
29529 +               msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
29530 +               if (_core_if->pti_enh_enable) {
29531 +                       msk.b.pktdrpsts = 1;
29532 +               }
29533 +               v = DWC_READ_REG32(&dev_if->
29534 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29535 +       }
29536 +       return v;
29537 +}
29538 +
29539 +/**
29540 + * This function returns the Host All Channel Interrupt register
29541 + */
29542 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
29543 +                                                          _core_if)
29544 +{
29545 +       return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));
29546 +}
29547 +
29548 +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
29549 +                                                     _core_if, dwc_hc_t * _hc)
29550 +{
29551 +       return (DWC_READ_REG32
29552 +               (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
29553 +}
29554 +
29555 +/**
29556 + * This function returns the mode of the operation, host or device.
29557 + *
29558 + * @return 0 - Device Mode, 1 - Host Mode
29559 + */
29560 +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
29561 +{
29562 +       return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
29563 +}
29564 +
29565 +/**@}*/
29566 +
29567 +/**
29568 + * DWC_otg CIL callback structure. This structure allows the HCD and
29569 + * PCD to register functions used for starting and stopping the PCD
29570 + * and HCD for role change on for a DRD.
29571 + */
29572 +typedef struct dwc_otg_cil_callbacks {
29573 +       /** Start function for role change */
29574 +       int (*start) (void *_p);
29575 +       /** Stop Function for role change */
29576 +       int (*stop) (void *_p);
29577 +       /** Disconnect Function for role change */
29578 +       int (*disconnect) (void *_p);
29579 +       /** Resume/Remote wakeup Function */
29580 +       int (*resume_wakeup) (void *_p);
29581 +       /** Suspend function */
29582 +       int (*suspend) (void *_p);
29583 +       /** Session Start (SRP) */
29584 +       int (*session_start) (void *_p);
29585 +#ifdef CONFIG_USB_DWC_OTG_LPM
29586 +       /** Sleep (switch to L0 state) */
29587 +       int (*sleep) (void *_p);
29588 +#endif
29589 +       /** Pointer passed to start() and stop() */
29590 +       void *p;
29591 +} dwc_otg_cil_callbacks_t;
29592 +
29593 +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
29594 +                                              dwc_otg_cil_callbacks_t * _cb,
29595 +                                              void *_p);
29596 +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
29597 +                                              dwc_otg_cil_callbacks_t * _cb,
29598 +                                              void *_p);
29599 +
29600 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);
29601 +
29602 +//////////////////////////////////////////////////////////////////////
29603 +/** Start the HCD.  Helper function for using the HCD callbacks.
29604 + *
29605 + * @param core_if Programming view of DWC_otg controller.
29606 + */
29607 +static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)
29608 +{
29609 +       if (core_if->hcd_cb && core_if->hcd_cb->start) {
29610 +               core_if->hcd_cb->start(core_if->hcd_cb->p);
29611 +       }
29612 +}
29613 +
29614 +/** Stop the HCD.  Helper function for using the HCD callbacks.
29615 + *
29616 + * @param core_if Programming view of DWC_otg controller.
29617 + */
29618 +static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)
29619 +{
29620 +       if (core_if->hcd_cb && core_if->hcd_cb->stop) {
29621 +               core_if->hcd_cb->stop(core_if->hcd_cb->p);
29622 +       }
29623 +}
29624 +
29625 +/** Disconnect the HCD.  Helper function for using the HCD callbacks.
29626 + *
29627 + * @param core_if Programming view of DWC_otg controller.
29628 + */
29629 +static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)
29630 +{
29631 +       if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
29632 +               core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
29633 +       }
29634 +}
29635 +
29636 +/** Inform the HCD the a New Session has begun.  Helper function for
29637 + * using the HCD callbacks.
29638 + *
29639 + * @param core_if Programming view of DWC_otg controller.
29640 + */
29641 +static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)
29642 +{
29643 +       if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
29644 +               core_if->hcd_cb->session_start(core_if->hcd_cb->p);
29645 +       }
29646 +}
29647 +
29648 +#ifdef CONFIG_USB_DWC_OTG_LPM
29649 +/**
29650 + * Inform the HCD about LPM sleep.
29651 + * Helper function for using the HCD callbacks.
29652 + *
29653 + * @param core_if Programming view of DWC_otg controller.
29654 + */
29655 +static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)
29656 +{
29657 +       if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
29658 +               core_if->hcd_cb->sleep(core_if->hcd_cb->p);
29659 +       }
29660 +}
29661 +#endif
29662 +
29663 +/** Resume the HCD.  Helper function for using the HCD callbacks.
29664 + *
29665 + * @param core_if Programming view of DWC_otg controller.
29666 + */
29667 +static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)
29668 +{
29669 +       if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
29670 +               core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
29671 +       }
29672 +}
29673 +
29674 +/** Start the PCD.  Helper function for using the PCD callbacks.
29675 + *
29676 + * @param core_if Programming view of DWC_otg controller.
29677 + */
29678 +static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)
29679 +{
29680 +       if (core_if->pcd_cb && core_if->pcd_cb->start) {
29681 +               core_if->pcd_cb->start(core_if->pcd_cb->p);
29682 +       }
29683 +}
29684 +
29685 +/** Stop the PCD.  Helper function for using the PCD callbacks.
29686 + *
29687 + * @param core_if Programming view of DWC_otg controller.
29688 + */
29689 +static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)
29690 +{
29691 +       if (core_if->pcd_cb && core_if->pcd_cb->stop) {
29692 +               core_if->pcd_cb->stop(core_if->pcd_cb->p);
29693 +       }
29694 +}
29695 +
29696 +/** Suspend the PCD.  Helper function for using the PCD callbacks.
29697 + *
29698 + * @param core_if Programming view of DWC_otg controller.
29699 + */
29700 +static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)
29701 +{
29702 +       if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
29703 +               core_if->pcd_cb->suspend(core_if->pcd_cb->p);
29704 +       }
29705 +}
29706 +
29707 +/** Resume the PCD.  Helper function for using the PCD callbacks.
29708 + *
29709 + * @param core_if Programming view of DWC_otg controller.
29710 + */
29711 +static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)
29712 +{
29713 +       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
29714 +               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
29715 +       }
29716 +}
29717 +
29718 +//////////////////////////////////////////////////////////////////////
29719 +
29720 +#endif
29721 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29722 new file mode 100644
29723 index 0000000..59fc862
29724 --- /dev/null
29725 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29726 @@ -0,0 +1,1563 @@
29727 +/* ==========================================================================
29728 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
29729 + * $Revision: #32 $
29730 + * $Date: 2012/08/10 $
29731 + * $Change: 2047372 $
29732 + *
29733 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
29734 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
29735 + * otherwise expressly agreed to in writing between Synopsys and you.
29736 + *
29737 + * The Software IS NOT an item of Licensed Software or Licensed Product under
29738 + * any End User Software License Agreement or Agreement for Licensed Product
29739 + * with Synopsys or any supplement thereto. You are permitted to use and
29740 + * redistribute this Software in source and binary forms, with or without
29741 + * modification, provided that redistributions of source code must retain this
29742 + * notice. You may not view, use, disclose, copy or distribute this file or
29743 + * any information contained herein except pursuant to this license grant from
29744 + * Synopsys. If you do not agree with this notice, including the disclaimer
29745 + * below, then you are not authorized to use the Software.
29746 + *
29747 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
29748 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29749 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29750 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
29751 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29752 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29753 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29754 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29755 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29756 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29757 + * DAMAGE.
29758 + * ========================================================================== */
29759 +
29760 +/** @file
29761 + *
29762 + * The Core Interface Layer provides basic services for accessing and
29763 + * managing the DWC_otg hardware. These services are used by both the
29764 + * Host Controller Driver and the Peripheral Controller Driver.
29765 + *
29766 + * This file contains the Common Interrupt handlers.
29767 + */
29768 +#include "dwc_os.h"
29769 +#include "dwc_otg_regs.h"
29770 +#include "dwc_otg_cil.h"
29771 +#include "dwc_otg_driver.h"
29772 +#include "dwc_otg_pcd.h"
29773 +#include "dwc_otg_hcd.h"
29774 +
29775 +#ifdef DEBUG
29776 +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
29777 +{
29778 +       return (core_if->op_state == A_HOST ? "a_host" :
29779 +               (core_if->op_state == A_SUSPEND ? "a_suspend" :
29780 +                (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
29781 +                 (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
29782 +                  (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
29783 +}
29784 +#endif
29785 +
29786 +/** This function will log a debug message
29787 + *
29788 + * @param core_if Programming view of DWC_otg controller.
29789 + */
29790 +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
29791 +{
29792 +       gintsts_data_t gintsts;
29793 +       DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
29794 +                dwc_otg_mode(core_if) ? "Host" : "Device");
29795 +
29796 +       /* Clear interrupt */
29797 +       gintsts.d32 = 0;
29798 +       gintsts.b.modemismatch = 1;
29799 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29800 +       return 1;
29801 +}
29802 +
29803 +/**
29804 + * This function handles the OTG Interrupts. It reads the OTG
29805 + * Interrupt Register (GOTGINT) to determine what interrupt has
29806 + * occurred.
29807 + *
29808 + * @param core_if Programming view of DWC_otg controller.
29809 + */
29810 +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
29811 +{
29812 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
29813 +       gotgint_data_t gotgint;
29814 +       gotgctl_data_t gotgctl;
29815 +       gintmsk_data_t gintmsk;
29816 +       gpwrdn_data_t gpwrdn;
29817 +
29818 +       gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
29819 +       gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29820 +       DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
29821 +                   op_state_str(core_if));
29822 +
29823 +       if (gotgint.b.sesenddet) {
29824 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29825 +                           "Session End Detected++ (%s)\n",
29826 +                           op_state_str(core_if));
29827 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29828 +
29829 +               if (core_if->op_state == B_HOST) {
29830 +                       cil_pcd_start(core_if);
29831 +                       core_if->op_state = B_PERIPHERAL;
29832 +               } else {
29833 +                       /* If not B_HOST and Device HNP still set. HNP
29834 +                        * Did not succeed!*/
29835 +                       if (gotgctl.b.devhnpen) {
29836 +                               DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
29837 +                               __DWC_ERROR("Device Not Connected/Responding!\n");
29838 +                       }
29839 +
29840 +                       /* If Session End Detected the B-Cable has
29841 +                        * been disconnected. */
29842 +                       /* Reset PCD and Gadget driver to a
29843 +                        * clean state. */
29844 +                       core_if->lx_state = DWC_OTG_L0;
29845 +                       DWC_SPINUNLOCK(core_if->lock);
29846 +                       cil_pcd_stop(core_if);
29847 +                       DWC_SPINLOCK(core_if->lock);
29848 +
29849 +                       if (core_if->adp_enable) {
29850 +                               if (core_if->power_down == 2) {
29851 +                                       gpwrdn.d32 = 0;
29852 +                                       gpwrdn.b.pwrdnswtch = 1;
29853 +                                       DWC_MODIFY_REG32(&core_if->
29854 +                                                        core_global_regs->
29855 +                                                        gpwrdn, gpwrdn.d32, 0);
29856 +                               }
29857 +
29858 +                               gpwrdn.d32 = 0;
29859 +                               gpwrdn.b.pmuintsel = 1;
29860 +                               gpwrdn.b.pmuactv = 1;
29861 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
29862 +                                                gpwrdn, 0, gpwrdn.d32);
29863 +
29864 +                               dwc_otg_adp_sense_start(core_if);
29865 +                       }
29866 +               }
29867 +
29868 +               gotgctl.d32 = 0;
29869 +               gotgctl.b.devhnpen = 1;
29870 +               DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29871 +       }
29872 +       if (gotgint.b.sesreqsucstschng) {
29873 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29874 +                           "Session Reqeust Success Status Change++\n");
29875 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29876 +               if (gotgctl.b.sesreqscs) {
29877 +
29878 +                       if ((core_if->core_params->phy_type ==
29879 +                            DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
29880 +                               core_if->srp_success = 1;
29881 +                       } else {
29882 +                               DWC_SPINUNLOCK(core_if->lock);
29883 +                               cil_pcd_resume(core_if);
29884 +                               DWC_SPINLOCK(core_if->lock);
29885 +                               /* Clear Session Request */
29886 +                               gotgctl.d32 = 0;
29887 +                               gotgctl.b.sesreq = 1;
29888 +                               DWC_MODIFY_REG32(&global_regs->gotgctl,
29889 +                                                gotgctl.d32, 0);
29890 +                       }
29891 +               }
29892 +       }
29893 +       if (gotgint.b.hstnegsucstschng) {
29894 +               /* Print statements during the HNP interrupt handling
29895 +                * can cause it to fail.*/
29896 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29897 +               /* WA for 3.00a- HW is not setting cur_mode, even sometimes
29898 +                * this does not help*/
29899 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
29900 +                       dwc_udelay(100);
29901 +               if (gotgctl.b.hstnegscs) {
29902 +                       if (dwc_otg_is_host_mode(core_if)) {
29903 +                               core_if->op_state = B_HOST;
29904 +                               /*
29905 +                                * Need to disable SOF interrupt immediately.
29906 +                                * When switching from device to host, the PCD
29907 +                                * interrupt handler won't handle the
29908 +                                * interrupt if host mode is already set. The
29909 +                                * HCD interrupt handler won't get called if
29910 +                                * the HCD state is HALT. This means that the
29911 +                                * interrupt does not get handled and Linux
29912 +                                * complains loudly.
29913 +                                */
29914 +                               gintmsk.d32 = 0;
29915 +                               gintmsk.b.sofintr = 1;
29916 +                               DWC_MODIFY_REG32(&global_regs->gintmsk,
29917 +                                                gintmsk.d32, 0);
29918 +                               /* Call callback function with spin lock released */
29919 +                               DWC_SPINUNLOCK(core_if->lock);
29920 +                               cil_pcd_stop(core_if);
29921 +                               /*
29922 +                                * Initialize the Core for Host mode.
29923 +                                */
29924 +                               cil_hcd_start(core_if);
29925 +                               DWC_SPINLOCK(core_if->lock);
29926 +                               core_if->op_state = B_HOST;
29927 +                       }
29928 +               } else {
29929 +                       gotgctl.d32 = 0;
29930 +                       gotgctl.b.hnpreq = 1;
29931 +                       gotgctl.b.devhnpen = 1;
29932 +                       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29933 +                       DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
29934 +                       __DWC_ERROR("Device Not Connected/Responding\n");
29935 +               }
29936 +       }
29937 +       if (gotgint.b.hstnegdet) {
29938 +               /* The disconnect interrupt is set at the same time as
29939 +                * Host Negotiation Detected.  During the mode
29940 +                * switch all interrupts are cleared so the disconnect
29941 +                * interrupt handler will not get executed.
29942 +                */
29943 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29944 +                           "Host Negotiation Detected++ (%s)\n",
29945 +                           (dwc_otg_is_host_mode(core_if) ? "Host" :
29946 +                            "Device"));
29947 +               if (dwc_otg_is_device_mode(core_if)) {
29948 +                       DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
29949 +                                   core_if->op_state);
29950 +                       DWC_SPINUNLOCK(core_if->lock);
29951 +                       cil_hcd_disconnect(core_if);
29952 +                       cil_pcd_start(core_if);
29953 +                       DWC_SPINLOCK(core_if->lock);
29954 +                       core_if->op_state = A_PERIPHERAL;
29955 +               } else {
29956 +                       /*
29957 +                        * Need to disable SOF interrupt immediately. When
29958 +                        * switching from device to host, the PCD interrupt
29959 +                        * handler won't handle the interrupt if host mode is
29960 +                        * already set. The HCD interrupt handler won't get
29961 +                        * called if the HCD state is HALT. This means that
29962 +                        * the interrupt does not get handled and Linux
29963 +                        * complains loudly.
29964 +                        */
29965 +                       gintmsk.d32 = 0;
29966 +                       gintmsk.b.sofintr = 1;
29967 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
29968 +                       DWC_SPINUNLOCK(core_if->lock);
29969 +                       cil_pcd_stop(core_if);
29970 +                       cil_hcd_start(core_if);
29971 +                       DWC_SPINLOCK(core_if->lock);
29972 +                       core_if->op_state = A_HOST;
29973 +               }
29974 +       }
29975 +       if (gotgint.b.adevtoutchng) {
29976 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29977 +                           "A-Device Timeout Change++\n");
29978 +       }
29979 +       if (gotgint.b.debdone) {
29980 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
29981 +       }
29982 +
29983 +       /* Clear GOTGINT */
29984 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
29985 +
29986 +       return 1;
29987 +}
29988 +
29989 +void w_conn_id_status_change(void *p)
29990 +{
29991 +       dwc_otg_core_if_t *core_if = p;
29992 +       uint32_t count = 0;
29993 +       gotgctl_data_t gotgctl = {.d32 = 0 };
29994 +
29995 +       gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
29996 +       DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
29997 +       DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
29998 +
29999 +       /* B-Device connector (Device Mode) */
30000 +       if (gotgctl.b.conidsts) {
30001 +               /* Wait for switch to device mode. */
30002 +               while (!dwc_otg_is_device_mode(core_if)) {
30003 +                       DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
30004 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
30005 +                                   "Peripheral"));
30006 +                       dwc_mdelay(100);
30007 +                       if (++count > 10000)
30008 +                               break;
30009 +               }
30010 +               DWC_ASSERT(++count < 10000,
30011 +                          "Connection id status change timed out");
30012 +               core_if->op_state = B_PERIPHERAL;
30013 +               dwc_otg_core_init(core_if);
30014 +               dwc_otg_enable_global_interrupts(core_if);
30015 +               cil_pcd_start(core_if);
30016 +       } else {
30017 +               /* A-Device connector (Host Mode) */
30018 +               while (!dwc_otg_is_host_mode(core_if)) {
30019 +                       DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
30020 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
30021 +                                   "Peripheral"));
30022 +                       dwc_mdelay(100);
30023 +                       if (++count > 10000)
30024 +                               break;
30025 +               }
30026 +               DWC_ASSERT(++count < 10000,
30027 +                          "Connection id status change timed out");
30028 +               core_if->op_state = A_HOST;
30029 +               /*
30030 +                * Initialize the Core for Host mode.
30031 +                */
30032 +               dwc_otg_core_init(core_if);
30033 +               dwc_otg_enable_global_interrupts(core_if);
30034 +               cil_hcd_start(core_if);
30035 +       }
30036 +}
30037 +
30038 +/**
30039 + * This function handles the Connector ID Status Change Interrupt.  It
30040 + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
30041 + * is a Device to Host Mode transition or a Host Mode to Device
30042 + * Transition.
30043 + *
30044 + * This only occurs when the cable is connected/removed from the PHY
30045 + * connector.
30046 + *
30047 + * @param core_if Programming view of DWC_otg controller.
30048 + */
30049 +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
30050 +{
30051 +
30052 +       /*
30053 +        * Need to disable SOF interrupt immediately. If switching from device
30054 +        * to host, the PCD interrupt handler won't handle the interrupt if
30055 +        * host mode is already set. The HCD interrupt handler won't get
30056 +        * called if the HCD state is HALT. This means that the interrupt does
30057 +        * not get handled and Linux complains loudly.
30058 +        */
30059 +       gintmsk_data_t gintmsk = {.d32 = 0 };
30060 +       gintsts_data_t gintsts = {.d32 = 0 };
30061 +
30062 +       gintmsk.b.sofintr = 1;
30063 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
30064 +
30065 +       DWC_DEBUGPL(DBG_CIL,
30066 +                   " ++Connector ID Status Change Interrupt++  (%s)\n",
30067 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
30068 +
30069 +       DWC_SPINUNLOCK(core_if->lock);
30070 +
30071 +       /*
30072 +        * Need to schedule a work, as there are possible DELAY function calls
30073 +        * Release lock before scheduling workq as it holds spinlock during scheduling
30074 +        */
30075 +
30076 +       DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
30077 +                          core_if, "connection id status change");
30078 +       DWC_SPINLOCK(core_if->lock);
30079 +
30080 +       /* Set flag and clear interrupt */
30081 +       gintsts.b.conidstschng = 1;
30082 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30083 +
30084 +       return 1;
30085 +}
30086 +
30087 +/**
30088 + * This interrupt indicates that a device is initiating the Session
30089 + * Request Protocol to request the host to turn on bus power so a new
30090 + * session can begin. The handler responds by turning on bus power. If
30091 + * the DWC_otg controller is in low power mode, the handler brings the
30092 + * controller out of low power mode before turning on bus power.
30093 + *
30094 + * @param core_if Programming view of DWC_otg controller.
30095 + */
30096 +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
30097 +{
30098 +       gintsts_data_t gintsts;
30099 +
30100 +#ifndef DWC_HOST_ONLY
30101 +       DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
30102 +
30103 +       if (dwc_otg_is_device_mode(core_if)) {
30104 +               DWC_PRINTF("SRP: Device mode\n");
30105 +       } else {
30106 +               hprt0_data_t hprt0;
30107 +               DWC_PRINTF("SRP: Host mode\n");
30108 +
30109 +               /* Turn on the port power bit. */
30110 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
30111 +               hprt0.b.prtpwr = 1;
30112 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30113 +
30114 +               /* Start the Connection timer. So a message can be displayed
30115 +                * if connect does not occur within 10 seconds. */
30116 +               cil_hcd_session_start(core_if);
30117 +       }
30118 +#endif
30119 +
30120 +       /* Clear interrupt */
30121 +       gintsts.d32 = 0;
30122 +       gintsts.b.sessreqintr = 1;
30123 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30124 +
30125 +       return 1;
30126 +}
30127 +
30128 +void w_wakeup_detected(void *p)
30129 +{
30130 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
30131 +       /*
30132 +        * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
30133 +        * so that OPT tests pass with all PHYs).
30134 +        */
30135 +       hprt0_data_t hprt0 = {.d32 = 0 };
30136 +#if 0
30137 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30138 +       /* Restart the Phy Clock */
30139 +       pcgcctl.b.stoppclk = 1;
30140 +       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30141 +       dwc_udelay(10);
30142 +#endif //0
30143 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
30144 +       DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
30145 +//      dwc_mdelay(70);
30146 +       hprt0.b.prtres = 0;     /* Resume */
30147 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30148 +       DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
30149 +                   DWC_READ_REG32(core_if->host_if->hprt0));
30150 +
30151 +       cil_hcd_resume(core_if);
30152 +
30153 +       /** Change to L0 state*/
30154 +       core_if->lx_state = DWC_OTG_L0;
30155 +}
30156 +
30157 +/**
30158 + * This interrupt indicates that the DWC_otg controller has detected a
30159 + * resume or remote wakeup sequence. If the DWC_otg controller is in
30160 + * low power mode, the handler must brings the controller out of low
30161 + * power mode. The controller automatically begins resume
30162 + * signaling. The handler schedules a time to stop resume signaling.
30163 + */
30164 +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30165 +{
30166 +       gintsts_data_t gintsts;
30167 +
30168 +       DWC_DEBUGPL(DBG_ANY,
30169 +                   "++Resume and Remote Wakeup Detected Interrupt++\n");
30170 +
30171 +       DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
30172 +
30173 +       if (dwc_otg_is_device_mode(core_if)) {
30174 +               dctl_data_t dctl = {.d32 = 0 };
30175 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
30176 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
30177 +                                          dsts));
30178 +               if (core_if->lx_state == DWC_OTG_L2) {
30179 +#ifdef PARTIAL_POWER_DOWN
30180 +                       if (core_if->hwcfg4.b.power_optimiz) {
30181 +                               pcgcctl_data_t power = {.d32 = 0 };
30182 +
30183 +                               power.d32 = DWC_READ_REG32(core_if->pcgcctl);
30184 +                               DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
30185 +                                           power.d32);
30186 +
30187 +                               power.b.stoppclk = 0;
30188 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30189 +
30190 +                               power.b.pwrclmp = 0;
30191 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30192 +
30193 +                               power.b.rstpdwnmodule = 0;
30194 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30195 +                       }
30196 +#endif
30197 +                       /* Clear the Remote Wakeup Signaling */
30198 +                       dctl.b.rmtwkupsig = 1;
30199 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
30200 +                                        dctl, dctl.d32, 0);
30201 +
30202 +                       DWC_SPINUNLOCK(core_if->lock);
30203 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
30204 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
30205 +                       }
30206 +                       DWC_SPINLOCK(core_if->lock);
30207 +               } else {
30208 +                       glpmcfg_data_t lpmcfg;
30209 +                       lpmcfg.d32 =
30210 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30211 +                       lpmcfg.b.hird_thres &= (~(1 << 4));
30212 +                       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30213 +                                       lpmcfg.d32);
30214 +               }
30215 +               /** Change to L0 state*/
30216 +               core_if->lx_state = DWC_OTG_L0;
30217 +       } else {
30218 +               if (core_if->lx_state != DWC_OTG_L1) {
30219 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30220 +
30221 +                       /* Restart the Phy Clock */
30222 +                       pcgcctl.b.stoppclk = 1;
30223 +                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30224 +                       DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
30225 +               } else {
30226 +                       /** Change to L0 state*/
30227 +                       core_if->lx_state = DWC_OTG_L0;
30228 +               }
30229 +       }
30230 +
30231 +       /* Clear interrupt */
30232 +       gintsts.d32 = 0;
30233 +       gintsts.b.wkupintr = 1;
30234 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30235 +
30236 +       return 1;
30237 +}
30238 +
30239 +/**
30240 + * This interrupt indicates that the Wakeup Logic has detected a
30241 + * Device disconnect.
30242 + */
30243 +static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
30244 +{
30245 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
30246 +       gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
30247 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30248 +
30249 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30250 +
30251 +       if (!core_if->hibernation_suspend) {
30252 +               DWC_PRINTF("Already exited from Hibernation\n");
30253 +               return 1;
30254 +       }
30255 +
30256 +       /* Switch on the voltage to the core */
30257 +       gpwrdn.b.pwrdnswtch = 1;
30258 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30259 +       dwc_udelay(10);
30260 +
30261 +       /* Reset the core */
30262 +       gpwrdn.d32 = 0;
30263 +       gpwrdn.b.pwrdnrstn = 1;
30264 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30265 +       dwc_udelay(10);
30266 +
30267 +       /* Disable power clamps*/
30268 +       gpwrdn.d32 = 0;
30269 +       gpwrdn.b.pwrdnclmp = 1;
30270 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30271 +
30272 +       /* Remove reset the core signal */
30273 +       gpwrdn.d32 = 0;
30274 +       gpwrdn.b.pwrdnrstn = 1;
30275 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30276 +       dwc_udelay(10);
30277 +
30278 +       /* Disable PMU interrupt */
30279 +       gpwrdn.d32 = 0;
30280 +       gpwrdn.b.pmuintsel = 1;
30281 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30282 +
30283 +       core_if->hibernation_suspend = 0;
30284 +
30285 +       /* Disable PMU */
30286 +       gpwrdn.d32 = 0;
30287 +       gpwrdn.b.pmuactv = 1;
30288 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30289 +       dwc_udelay(10);
30290 +
30291 +       if (gpwrdn_temp.b.idsts) {
30292 +               core_if->op_state = B_PERIPHERAL;
30293 +               dwc_otg_core_init(core_if);
30294 +               dwc_otg_enable_global_interrupts(core_if);
30295 +               cil_pcd_start(core_if);
30296 +       } else {
30297 +               core_if->op_state = A_HOST;
30298 +               dwc_otg_core_init(core_if);
30299 +               dwc_otg_enable_global_interrupts(core_if);
30300 +               cil_hcd_start(core_if);
30301 +       }
30302 +
30303 +       return 1;
30304 +}
30305 +
30306 +/**
30307 + * This interrupt indicates that the Wakeup Logic has detected a
30308 + * remote wakeup sequence.
30309 + */
30310 +static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30311 +{
30312 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30313 +       DWC_DEBUGPL(DBG_ANY,
30314 +                   "++Powerdown Remote Wakeup Detected Interrupt++\n");
30315 +
30316 +       if (!core_if->hibernation_suspend) {
30317 +               DWC_PRINTF("Already exited from Hibernation\n");
30318 +               return 1;
30319 +       }
30320 +
30321 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30322 +       if (gpwrdn.b.idsts) {   // Device Mode
30323 +               if ((core_if->power_down == 2)
30324 +                   && (core_if->hibernation_suspend == 1)) {
30325 +                       dwc_otg_device_hibernation_restore(core_if, 0, 0);
30326 +               }
30327 +       } else {
30328 +               if ((core_if->power_down == 2)
30329 +                   && (core_if->hibernation_suspend == 1)) {
30330 +                       dwc_otg_host_hibernation_restore(core_if, 1, 0);
30331 +               }
30332 +       }
30333 +       return 1;
30334 +}
30335 +
30336 +static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
30337 +{
30338 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30339 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30340 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30341 +
30342 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30343 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30344 +       if (core_if->power_down == 2) {
30345 +               if (!core_if->hibernation_suspend) {
30346 +                       DWC_PRINTF("Already exited from Hibernation\n");
30347 +                       return 1;
30348 +               }
30349 +               DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
30350 +               /* Switch on the voltage to the core */
30351 +               gpwrdn.b.pwrdnswtch = 1;
30352 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30353 +               dwc_udelay(10);
30354 +
30355 +               /* Reset the core */
30356 +               gpwrdn.d32 = 0;
30357 +               gpwrdn.b.pwrdnrstn = 1;
30358 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30359 +               dwc_udelay(10);
30360 +
30361 +               /* Disable power clamps */
30362 +               gpwrdn.d32 = 0;
30363 +               gpwrdn.b.pwrdnclmp = 1;
30364 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30365 +
30366 +               /* Remove reset the core signal */
30367 +               gpwrdn.d32 = 0;
30368 +               gpwrdn.b.pwrdnrstn = 1;
30369 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30370 +               dwc_udelay(10);
30371 +
30372 +               /* Disable PMU interrupt */
30373 +               gpwrdn.d32 = 0;
30374 +               gpwrdn.b.pmuintsel = 1;
30375 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30376 +
30377 +               /*Indicates that we are exiting from hibernation */
30378 +               core_if->hibernation_suspend = 0;
30379 +
30380 +               /* Disable PMU */
30381 +               gpwrdn.d32 = 0;
30382 +               gpwrdn.b.pmuactv = 1;
30383 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30384 +               dwc_udelay(10);
30385 +
30386 +               gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
30387 +               if (gpwrdn.b.dis_vbus == 1) {
30388 +                       gpwrdn.d32 = 0;
30389 +                       gpwrdn.b.dis_vbus = 1;
30390 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30391 +               }
30392 +
30393 +               if (gpwrdn_temp.b.idsts) {
30394 +                       core_if->op_state = B_PERIPHERAL;
30395 +                       dwc_otg_core_init(core_if);
30396 +                       dwc_otg_enable_global_interrupts(core_if);
30397 +                       cil_pcd_start(core_if);
30398 +               } else {
30399 +                       core_if->op_state = A_HOST;
30400 +                       dwc_otg_core_init(core_if);
30401 +                       dwc_otg_enable_global_interrupts(core_if);
30402 +                       cil_hcd_start(core_if);
30403 +               }
30404 +       }
30405 +
30406 +       if (core_if->adp_enable) {
30407 +               uint8_t is_host = 0;
30408 +               DWC_SPINUNLOCK(core_if->lock);
30409 +               /* Change the core_if's lock to hcd/pcd lock depend on mode? */
30410 +#ifndef DWC_HOST_ONLY
30411 +               if (gpwrdn_temp.b.idsts)
30412 +                       core_if->lock = otg_dev->pcd->lock;
30413 +#endif
30414 +#ifndef DWC_DEVICE_ONLY
30415 +               if (!gpwrdn_temp.b.idsts) {
30416 +                               core_if->lock = otg_dev->hcd->lock;
30417 +                               is_host = 1;
30418 +               }
30419 +#endif
30420 +               DWC_PRINTF("RESTART ADP\n");
30421 +               if (core_if->adp.probe_enabled)
30422 +                       dwc_otg_adp_probe_stop(core_if);
30423 +               if (core_if->adp.sense_enabled)
30424 +                       dwc_otg_adp_sense_stop(core_if);
30425 +               if (core_if->adp.sense_timer_started)
30426 +                       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
30427 +               if (core_if->adp.vbuson_timer_started)
30428 +                       DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
30429 +               core_if->adp.probe_timer_values[0] = -1;
30430 +               core_if->adp.probe_timer_values[1] = -1;
30431 +               core_if->adp.sense_timer_started = 0;
30432 +               core_if->adp.vbuson_timer_started = 0;
30433 +               core_if->adp.probe_counter = 0;
30434 +               core_if->adp.gpwrdn = 0;
30435 +
30436 +               /* Disable PMU and restart ADP */
30437 +               gpwrdn_temp.d32 = 0;
30438 +               gpwrdn_temp.b.pmuactv = 1;
30439 +               gpwrdn_temp.b.pmuintsel = 1;
30440 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30441 +               DWC_PRINTF("Check point 1\n");
30442 +               dwc_mdelay(110);
30443 +               dwc_otg_adp_start(core_if, is_host);
30444 +               DWC_SPINLOCK(core_if->lock);
30445 +       }
30446 +
30447 +
30448 +       return 1;
30449 +}
30450 +
30451 +static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
30452 +{
30453 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30454 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
30455 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30456 +
30457 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30458 +       if (core_if->power_down == 2) {
30459 +               if (!core_if->hibernation_suspend) {
30460 +                       DWC_PRINTF("Already exited from Hibernation\n");
30461 +                       return 1;
30462 +               }
30463 +
30464 +               if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30465 +                        otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
30466 +                       gpwrdn.b.bsessvld == 0) {
30467 +                       /* Save gpwrdn register for further usage if stschng interrupt */
30468 +                       core_if->gr_backup->gpwrdn_local =
30469 +                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30470 +                       /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
30471 +                       return 1;
30472 +               }
30473 +
30474 +               /* Switch on the voltage to the core */
30475 +               gpwrdn.d32 = 0;
30476 +               gpwrdn.b.pwrdnswtch = 1;
30477 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30478 +               dwc_udelay(10);
30479 +
30480 +               /* Reset the core */
30481 +               gpwrdn.d32 = 0;
30482 +               gpwrdn.b.pwrdnrstn = 1;
30483 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30484 +               dwc_udelay(10);
30485 +
30486 +               /* Disable power clamps */
30487 +               gpwrdn.d32 = 0;
30488 +               gpwrdn.b.pwrdnclmp = 1;
30489 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30490 +
30491 +               /* Remove reset the core signal */
30492 +               gpwrdn.d32 = 0;
30493 +               gpwrdn.b.pwrdnrstn = 1;
30494 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30495 +               dwc_udelay(10);
30496 +
30497 +               /* Disable PMU interrupt */
30498 +               gpwrdn.d32 = 0;
30499 +               gpwrdn.b.pmuintsel = 1;
30500 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30501 +               dwc_udelay(10);
30502 +
30503 +               /*Indicates that we are exiting from hibernation */
30504 +               core_if->hibernation_suspend = 0;
30505 +
30506 +               /* Disable PMU */
30507 +               gpwrdn.d32 = 0;
30508 +               gpwrdn.b.pmuactv = 1;
30509 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30510 +               dwc_udelay(10);
30511 +
30512 +               core_if->op_state = B_PERIPHERAL;
30513 +               dwc_otg_core_init(core_if);
30514 +               dwc_otg_enable_global_interrupts(core_if);
30515 +               cil_pcd_start(core_if);
30516 +
30517 +               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30518 +                       otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
30519 +                       /*
30520 +                        * Initiate SRP after initial ADP probe.
30521 +                        */
30522 +                       dwc_otg_initiate_srp(core_if);
30523 +               }
30524 +       }
30525 +
30526 +       return 1;
30527 +}
30528 +/**
30529 + * This interrupt indicates that the Wakeup Logic has detected a
30530 + * status change either on IDDIG or BSessVld.
30531 + */
30532 +static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
30533 +{
30534 +       int retval;
30535 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30536 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30537 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30538 +
30539 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30540 +
30541 +       if (core_if->power_down == 2) {
30542 +               if (core_if->hibernation_suspend <= 0) {
30543 +                       DWC_PRINTF("Already exited from Hibernation\n");
30544 +                       return 1;
30545 +               } else
30546 +                       gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
30547 +
30548 +       } else {
30549 +               gpwrdn_temp.d32 = core_if->adp.gpwrdn;
30550 +       }
30551 +
30552 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30553 +
30554 +       if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
30555 +               retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
30556 +       } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
30557 +               retval = dwc_otg_handle_pwrdn_session_change(core_if);
30558 +       }
30559 +
30560 +       return retval;
30561 +}
30562 +
30563 +/**
30564 + * This interrupt indicates that the Wakeup Logic has detected a
30565 + * SRP.
30566 + */
30567 +static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
30568 +{
30569 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30570 +
30571 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30572 +
30573 +       if (!core_if->hibernation_suspend) {
30574 +               DWC_PRINTF("Already exited from Hibernation\n");
30575 +               return 1;
30576 +       }
30577 +#ifdef DWC_DEV_SRPCAP
30578 +       if (core_if->pwron_timer_started) {
30579 +               core_if->pwron_timer_started = 0;
30580 +               DWC_TIMER_CANCEL(core_if->pwron_timer);
30581 +       }
30582 +#endif
30583 +
30584 +       /* Switch on the voltage to the core */
30585 +       gpwrdn.b.pwrdnswtch = 1;
30586 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30587 +       dwc_udelay(10);
30588 +
30589 +       /* Reset the core */
30590 +       gpwrdn.d32 = 0;
30591 +       gpwrdn.b.pwrdnrstn = 1;
30592 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30593 +       dwc_udelay(10);
30594 +
30595 +       /* Disable power clamps */
30596 +       gpwrdn.d32 = 0;
30597 +       gpwrdn.b.pwrdnclmp = 1;
30598 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30599 +
30600 +       /* Remove reset the core signal */
30601 +       gpwrdn.d32 = 0;
30602 +       gpwrdn.b.pwrdnrstn = 1;
30603 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30604 +       dwc_udelay(10);
30605 +
30606 +       /* Disable PMU interrupt */
30607 +       gpwrdn.d32 = 0;
30608 +       gpwrdn.b.pmuintsel = 1;
30609 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30610 +
30611 +       /* Indicates that we are exiting from hibernation */
30612 +       core_if->hibernation_suspend = 0;
30613 +
30614 +       /* Disable PMU */
30615 +       gpwrdn.d32 = 0;
30616 +       gpwrdn.b.pmuactv = 1;
30617 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30618 +       dwc_udelay(10);
30619 +
30620 +       /* Programm Disable VBUS to 0 */
30621 +       gpwrdn.d32 = 0;
30622 +       gpwrdn.b.dis_vbus = 1;
30623 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30624 +
30625 +       /*Initialize the core as Host */
30626 +       core_if->op_state = A_HOST;
30627 +       dwc_otg_core_init(core_if);
30628 +       dwc_otg_enable_global_interrupts(core_if);
30629 +       cil_hcd_start(core_if);
30630 +
30631 +       return 1;
30632 +}
30633 +
30634 +/** This interrupt indicates that restore command after Hibernation
30635 + * was completed by the core. */
30636 +int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
30637 +{
30638 +       pcgcctl_data_t pcgcctl;
30639 +       DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
30640 +
30641 +       //TODO De-assert restore signal. 8.a
30642 +       pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
30643 +       if (pcgcctl.b.restoremode == 1) {
30644 +               gintmsk_data_t gintmsk = {.d32 = 0 };
30645 +               /*
30646 +                * If restore mode is Remote Wakeup,
30647 +                * unmask Remote Wakeup interrupt.
30648 +                */
30649 +               gintmsk.b.wkupintr = 1;
30650 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
30651 +                                0, gintmsk.d32);
30652 +       }
30653 +
30654 +       return 1;
30655 +}
30656 +
30657 +/**
30658 + * This interrupt indicates that a device has been disconnected from
30659 + * the root port.
30660 + */
30661 +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
30662 +{
30663 +       gintsts_data_t gintsts;
30664 +
30665 +       DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
30666 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
30667 +                   op_state_str(core_if));
30668 +
30669 +/** @todo Consolidate this if statement. */
30670 +#ifndef DWC_HOST_ONLY
30671 +       if (core_if->op_state == B_HOST) {
30672 +               /* If in device mode Disconnect and stop the HCD, then
30673 +                * start the PCD. */
30674 +               DWC_SPINUNLOCK(core_if->lock);
30675 +               cil_hcd_disconnect(core_if);
30676 +               cil_pcd_start(core_if);
30677 +               DWC_SPINLOCK(core_if->lock);
30678 +               core_if->op_state = B_PERIPHERAL;
30679 +       } else if (dwc_otg_is_device_mode(core_if)) {
30680 +               gotgctl_data_t gotgctl = {.d32 = 0 };
30681 +               gotgctl.d32 =
30682 +                   DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
30683 +               if (gotgctl.b.hstsethnpen == 1) {
30684 +                       /* Do nothing, if HNP in process the OTG
30685 +                        * interrupt "Host Negotiation Detected"
30686 +                        * interrupt will do the mode switch.
30687 +                        */
30688 +               } else if (gotgctl.b.devhnpen == 0) {
30689 +                       /* If in device mode Disconnect and stop the HCD, then
30690 +                        * start the PCD. */
30691 +                       DWC_SPINUNLOCK(core_if->lock);
30692 +                       cil_hcd_disconnect(core_if);
30693 +                       cil_pcd_start(core_if);
30694 +                       DWC_SPINLOCK(core_if->lock);
30695 +                       core_if->op_state = B_PERIPHERAL;
30696 +               } else {
30697 +                       DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
30698 +               }
30699 +       } else {
30700 +               if (core_if->op_state == A_HOST) {
30701 +                       /* A-Cable still connected but device disconnected. */
30702 +                       cil_hcd_disconnect(core_if);
30703 +                       if (core_if->adp_enable) {
30704 +                               gpwrdn_data_t gpwrdn = { .d32 = 0 };
30705 +                               cil_hcd_stop(core_if);
30706 +                               /* Enable Power Down Logic */
30707 +                               gpwrdn.b.pmuintsel = 1;
30708 +                               gpwrdn.b.pmuactv = 1;
30709 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30710 +                                                gpwrdn, 0, gpwrdn.d32);
30711 +                               dwc_otg_adp_probe_start(core_if);
30712 +
30713 +                               /* Power off the core */
30714 +                               if (core_if->power_down == 2) {
30715 +                                       gpwrdn.d32 = 0;
30716 +                                       gpwrdn.b.pwrdnswtch = 1;
30717 +                                       DWC_MODIFY_REG32
30718 +                                           (&core_if->core_global_regs->gpwrdn,
30719 +                                            gpwrdn.d32, 0);
30720 +                               }
30721 +                       }
30722 +               }
30723 +       }
30724 +#endif
30725 +       /* Change to L3(OFF) state */
30726 +       core_if->lx_state = DWC_OTG_L3;
30727 +
30728 +       gintsts.d32 = 0;
30729 +       gintsts.b.disconnect = 1;
30730 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30731 +       return 1;
30732 +}
30733 +
30734 +/**
30735 + * This interrupt indicates that SUSPEND state has been detected on
30736 + * the USB.
30737 + *
30738 + * For HNP the USB Suspend interrupt signals the change from
30739 + * "a_peripheral" to "a_host".
30740 + *
30741 + * When power management is enabled the core will be put in low power
30742 + * mode.
30743 + */
30744 +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
30745 +{
30746 +       dsts_data_t dsts;
30747 +       gintsts_data_t gintsts;
30748 +       dcfg_data_t dcfg;
30749 +
30750 +       DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
30751 +
30752 +       if (dwc_otg_is_device_mode(core_if)) {
30753 +               /* Check the Device status register to determine if the Suspend
30754 +                * state is active. */
30755 +               dsts.d32 =
30756 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
30757 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
30758 +               DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
30759 +                           "HWCFG4.power Optimize=%d\n",
30760 +                           dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
30761 +
30762 +#ifdef PARTIAL_POWER_DOWN
30763 +/** @todo Add a module parameter for power management. */
30764 +
30765 +               if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
30766 +                       pcgcctl_data_t power = {.d32 = 0 };
30767 +                       DWC_DEBUGPL(DBG_CIL, "suspend\n");
30768 +
30769 +                       power.b.pwrclmp = 1;
30770 +                       DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30771 +
30772 +                       power.b.rstpdwnmodule = 1;
30773 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30774 +
30775 +                       power.b.stoppclk = 1;
30776 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30777 +
30778 +               } else {
30779 +                       DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
30780 +               }
30781 +#endif
30782 +               /* PCD callback for suspend. Release the lock inside of callback function */
30783 +               cil_pcd_suspend(core_if);
30784 +               if (core_if->power_down == 2)
30785 +               {
30786 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30787 +                       DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
30788 +                       DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
30789 +
30790 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30791 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
30792 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
30793 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
30794 +
30795 +                               /* Change to L2(suspend) state */
30796 +                               core_if->lx_state = DWC_OTG_L2;
30797 +
30798 +                               /* Clear interrupt in gintsts */
30799 +                               gintsts.d32 = 0;
30800 +                               gintsts.b.usbsuspend = 1;
30801 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30802 +                                               gintsts, gintsts.d32);
30803 +                               DWC_PRINTF("Start of hibernation completed\n");
30804 +                               dwc_otg_save_global_regs(core_if);
30805 +                               dwc_otg_save_dev_regs(core_if);
30806 +
30807 +                               gusbcfg.d32 =
30808 +                                   DWC_READ_REG32(&core_if->core_global_regs->
30809 +                                                  gusbcfg);
30810 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
30811 +                                       /* ULPI interface */
30812 +                                       /* Suspend the Phy Clock */
30813 +                                       pcgcctl.d32 = 0;
30814 +                                       pcgcctl.b.stoppclk = 1;
30815 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30816 +                                                        pcgcctl.d32);
30817 +                                       dwc_udelay(10);
30818 +                                       gpwrdn.b.pmuactv = 1;
30819 +                                       DWC_MODIFY_REG32(&core_if->
30820 +                                                        core_global_regs->
30821 +                                                        gpwrdn, 0, gpwrdn.d32);
30822 +                               } else {
30823 +                                       /* UTMI+ Interface */
30824 +                                       gpwrdn.b.pmuactv = 1;
30825 +                                       DWC_MODIFY_REG32(&core_if->
30826 +                                                        core_global_regs->
30827 +                                                        gpwrdn, 0, gpwrdn.d32);
30828 +                                       dwc_udelay(10);
30829 +                                       pcgcctl.b.stoppclk = 1;
30830 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30831 +                                                        pcgcctl.d32);
30832 +                                       dwc_udelay(10);
30833 +                               }
30834 +
30835 +                               /* Set flag to indicate that we are in hibernation */
30836 +                               core_if->hibernation_suspend = 1;
30837 +                               /* Enable interrupts from wake up logic */
30838 +                               gpwrdn.d32 = 0;
30839 +                               gpwrdn.b.pmuintsel = 1;
30840 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30841 +                                                gpwrdn, 0, gpwrdn.d32);
30842 +                               dwc_udelay(10);
30843 +
30844 +                               /* Unmask device mode interrupts in GPWRDN */
30845 +                               gpwrdn.d32 = 0;
30846 +                               gpwrdn.b.rst_det_msk = 1;
30847 +                               gpwrdn.b.lnstchng_msk = 1;
30848 +                               gpwrdn.b.sts_chngint_msk = 1;
30849 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30850 +                                                gpwrdn, 0, gpwrdn.d32);
30851 +                               dwc_udelay(10);
30852 +
30853 +                               /* Enable Power Down Clamp */
30854 +                               gpwrdn.d32 = 0;
30855 +                               gpwrdn.b.pwrdnclmp = 1;
30856 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30857 +                                                gpwrdn, 0, gpwrdn.d32);
30858 +                               dwc_udelay(10);
30859 +
30860 +                               /* Switch off VDD */
30861 +                               gpwrdn.d32 = 0;
30862 +                               gpwrdn.b.pwrdnswtch = 1;
30863 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30864 +                                                gpwrdn, 0, gpwrdn.d32);
30865 +
30866 +                               /* Save gpwrdn register for further usage if stschng interrupt */
30867 +                               core_if->gr_backup->gpwrdn_local =
30868 +                                                       DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30869 +                               DWC_PRINTF("Hibernation completed\n");
30870 +
30871 +                               return 1;
30872 +                       }
30873 +               } else if (core_if->power_down == 3) {
30874 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30875 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30876 +                       DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);
30877 +                       DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);
30878 +
30879 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30880 +                               DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");
30881 +                               core_if->xhib = 1;
30882 +
30883 +                               /* Clear interrupt in gintsts */
30884 +                               gintsts.d32 = 0;
30885 +                               gintsts.b.usbsuspend = 1;
30886 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30887 +                                       gintsts, gintsts.d32);
30888 +
30889 +                               dwc_otg_save_global_regs(core_if);
30890 +                               dwc_otg_save_dev_regs(core_if);
30891 +
30892 +                               /* Wait for 10 PHY clocks */
30893 +                               dwc_udelay(10);
30894 +
30895 +                               /* Program GPIO register while entering to xHib */
30896 +                               DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);
30897 +
30898 +                               pcgcctl.b.enbl_extnd_hiber = 1;
30899 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30900 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30901 +
30902 +                               pcgcctl.d32 = 0;
30903 +                               pcgcctl.b.extnd_hiber_pwrclmp = 1;
30904 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30905 +
30906 +                               pcgcctl.d32 = 0;
30907 +                               pcgcctl.b.extnd_hiber_switch = 1;
30908 +                               core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30909 +                               core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;
30910 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30911 +
30912 +                               DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");
30913 +
30914 +                               return 1;
30915 +                       }
30916 +               }
30917 +       } else {
30918 +               if (core_if->op_state == A_PERIPHERAL) {
30919 +                       DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
30920 +                       /* Clear the a_peripheral flag, back to a_host. */
30921 +                       DWC_SPINUNLOCK(core_if->lock);
30922 +                       cil_pcd_stop(core_if);
30923 +                       cil_hcd_start(core_if);
30924 +                       DWC_SPINLOCK(core_if->lock);
30925 +                       core_if->op_state = A_HOST;
30926 +               }
30927 +       }
30928 +
30929 +       /* Change to L2(suspend) state */
30930 +       core_if->lx_state = DWC_OTG_L2;
30931 +
30932 +       /* Clear interrupt */
30933 +       gintsts.d32 = 0;
30934 +       gintsts.b.usbsuspend = 1;
30935 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30936 +
30937 +       return 1;
30938 +}
30939 +
30940 +static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)
30941 +{
30942 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30943 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30944 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
30945 +
30946 +       dwc_udelay(10);
30947 +
30948 +       /* Program GPIO register while entering to xHib */
30949 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
30950 +
30951 +       pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
30952 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30953 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30954 +       dwc_udelay(10);
30955 +
30956 +       gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
30957 +       gpwrdn.b.restore = 1;
30958 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
30959 +       dwc_udelay(10);
30960 +
30961 +       restore_lpm_i2c_regs(core_if);
30962 +
30963 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30964 +       pcgcctl.b.max_xcvrselect = 1;
30965 +       pcgcctl.b.ess_reg_restored = 0;
30966 +       pcgcctl.b.extnd_hiber_switch = 0;
30967 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30968 +       pcgcctl.b.enbl_extnd_hiber = 1;
30969 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30970 +
30971 +       gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
30972 +       gahbcfg.b.glblintrmsk = 1;
30973 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
30974 +
30975 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
30976 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
30977 +
30978 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
30979 +                       core_if->gr_backup->gusbcfg_local);
30980 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
30981 +                       core_if->dr_backup->dcfg);
30982 +
30983 +       pcgcctl.d32 = 0;
30984 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30985 +       pcgcctl.b.max_xcvrselect = 1;
30986 +       pcgcctl.d32 |= 0x608;
30987 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30988 +       dwc_udelay(10);
30989 +
30990 +       pcgcctl.d32 = 0;
30991 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30992 +       pcgcctl.b.max_xcvrselect = 1;
30993 +       pcgcctl.b.ess_reg_restored = 1;
30994 +       pcgcctl.b.enbl_extnd_hiber = 1;
30995 +       pcgcctl.b.rstpdwnmodule = 1;
30996 +       pcgcctl.b.restoremode = 1;
30997 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30998 +
30999 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
31000 +
31001 +       return 1;
31002 +}
31003 +
31004 +#ifdef CONFIG_USB_DWC_OTG_LPM
31005 +/**
31006 + * This function hadles LPM transaction received interrupt.
31007 + */
31008 +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
31009 +{
31010 +       glpmcfg_data_t lpmcfg;
31011 +       gintsts_data_t gintsts;
31012 +
31013 +       if (!core_if->core_params->lpm_enable) {
31014 +               DWC_PRINTF("Unexpected LPM interrupt\n");
31015 +       }
31016 +
31017 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
31018 +       DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
31019 +
31020 +       if (dwc_otg_is_host_mode(core_if)) {
31021 +               cil_hcd_sleep(core_if);
31022 +       } else {
31023 +               lpmcfg.b.hird_thres |= (1 << 4);
31024 +               DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
31025 +                               lpmcfg.d32);
31026 +       }
31027 +
31028 +       /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
31029 +       dwc_udelay(10);
31030 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
31031 +       if (lpmcfg.b.prt_sleep_sts) {
31032 +               /* Save the current state */
31033 +               core_if->lx_state = DWC_OTG_L1;
31034 +       }
31035 +
31036 +       /* Clear interrupt  */
31037 +       gintsts.d32 = 0;
31038 +       gintsts.b.lpmtranrcvd = 1;
31039 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
31040 +       return 1;
31041 +}
31042 +#endif /* CONFIG_USB_DWC_OTG_LPM */
31043 +
31044 +/**
31045 + * This function returns the Core Interrupt register.
31046 + */
31047 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
31048 +{
31049 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
31050 +       gintsts_data_t gintsts;
31051 +       gintmsk_data_t gintmsk;
31052 +       gintmsk_data_t gintmsk_common = {.d32 = 0 };
31053 +       gintmsk_common.b.wkupintr = 1;
31054 +       gintmsk_common.b.sessreqintr = 1;
31055 +       gintmsk_common.b.conidstschng = 1;
31056 +       gintmsk_common.b.otgintr = 1;
31057 +       gintmsk_common.b.modemismatch = 1;
31058 +       gintmsk_common.b.disconnect = 1;
31059 +       gintmsk_common.b.usbsuspend = 1;
31060 +#ifdef CONFIG_USB_DWC_OTG_LPM
31061 +       gintmsk_common.b.lpmtranrcvd = 1;
31062 +#endif
31063 +       gintmsk_common.b.restoredone = 1;
31064 +       /** @todo: The port interrupt occurs while in device
31065 +         * mode. Added code to CIL to clear the interrupt for now!
31066 +         */
31067 +       gintmsk_common.b.portintr = 1;
31068 +
31069 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
31070 +       gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
31071 +       gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
31072 +
31073 +#ifdef DEBUG
31074 +       /* if any common interrupts set */
31075 +       if (gintsts.d32 & gintmsk_common.d32) {
31076 +               DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
31077 +                           gintsts.d32, gintmsk.d32);
31078 +       }
31079 +#endif
31080 +       if (gahbcfg.b.glblintrmsk)
31081 +               return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
31082 +       else
31083 +               return 0;
31084 +
31085 +}
31086 +
31087 +/* MACRO for clearing interupt bits in GPWRDN register */
31088 +#define CLEAR_GPWRDN_INTR(__core_if,__intr) \
31089 +do { \
31090 +               gpwrdn_data_t gpwrdn = {.d32=0}; \
31091 +               gpwrdn.b.__intr = 1; \
31092 +               DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
31093 +               0, gpwrdn.d32); \
31094 +} while (0)
31095 +
31096 +/**
31097 + * Common interrupt handler.
31098 + *
31099 + * The common interrupts are those that occur in both Host and Device mode.
31100 + * This handler handles the following interrupts:
31101 + * - Mode Mismatch Interrupt
31102 + * - Disconnect Interrupt
31103 + * - OTG Interrupt
31104 + * - Connector ID Status Change Interrupt
31105 + * - Session Request Interrupt.
31106 + * - Resume / Remote Wakeup Detected Interrupt.
31107 + * - LPM Transaction Received Interrupt
31108 + * - ADP Transaction Received Interrupt
31109 + *
31110 + */
31111 +int32_t dwc_otg_handle_common_intr(void *dev)
31112 +{
31113 +       int retval = 0;
31114 +       gintsts_data_t gintsts;
31115 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
31116 +       dwc_otg_device_t *otg_dev = dev;
31117 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
31118 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
31119 +       if (dwc_otg_is_device_mode(core_if))
31120 +               core_if->frame_num = dwc_otg_get_frame_number(core_if);
31121 +
31122 +       if (core_if->lock)
31123 +               DWC_SPINLOCK(core_if->lock);
31124 +
31125 +       if (core_if->power_down == 3 && core_if->xhib == 1) {
31126 +               DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
31127 +               retval |= dwc_otg_handle_xhib_exit_intr(core_if);
31128 +               core_if->xhib = 2;
31129 +               if (core_if->lock)
31130 +                       DWC_SPINUNLOCK(core_if->lock);
31131 +
31132 +               return retval;
31133 +       }
31134 +
31135 +       if (core_if->hibernation_suspend <= 0) {
31136 +               gintsts.d32 = dwc_otg_read_common_intr(core_if);
31137 +
31138 +               if (gintsts.b.modemismatch) {
31139 +                       retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
31140 +               }
31141 +               if (gintsts.b.otgintr) {
31142 +                       retval |= dwc_otg_handle_otg_intr(core_if);
31143 +               }
31144 +               if (gintsts.b.conidstschng) {
31145 +                       retval |=
31146 +                           dwc_otg_handle_conn_id_status_change_intr(core_if);
31147 +               }
31148 +               if (gintsts.b.disconnect) {
31149 +                       retval |= dwc_otg_handle_disconnect_intr(core_if);
31150 +               }
31151 +               if (gintsts.b.sessreqintr) {
31152 +                       retval |= dwc_otg_handle_session_req_intr(core_if);
31153 +               }
31154 +               if (gintsts.b.wkupintr) {
31155 +                       retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
31156 +               }
31157 +               if (gintsts.b.usbsuspend) {
31158 +                       retval |= dwc_otg_handle_usb_suspend_intr(core_if);
31159 +               }
31160 +#ifdef CONFIG_USB_DWC_OTG_LPM
31161 +               if (gintsts.b.lpmtranrcvd) {
31162 +                       retval |= dwc_otg_handle_lpm_intr(core_if);
31163 +               }
31164 +#endif
31165 +               if (gintsts.b.restoredone) {
31166 +                       gintsts.d32 = 0;
31167 +                       if (core_if->power_down == 2)
31168 +                               core_if->hibernation_suspend = -1;
31169 +                       else if (core_if->power_down == 3 && core_if->xhib == 2) {
31170 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
31171 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
31172 +                               dctl_data_t dctl = {.d32 = 0 };
31173 +
31174 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
31175 +                                               gintsts, 0xFFFFFFFF);
31176 +
31177 +                               DWC_DEBUGPL(DBG_ANY,
31178 +                                           "RESTORE DONE generated\n");
31179 +
31180 +                               gpwrdn.b.restore = 1;
31181 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
31182 +                               dwc_udelay(10);
31183 +
31184 +                               pcgcctl.b.rstpdwnmodule = 1;
31185 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31186 +
31187 +                               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);
31188 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);
31189 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);
31190 +                               dwc_udelay(50);
31191 +
31192 +                               dctl.b.pwronprgdone = 1;
31193 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
31194 +                               dwc_udelay(10);
31195 +
31196 +                               dwc_otg_restore_global_regs(core_if);
31197 +                               dwc_otg_restore_dev_regs(core_if, 0);
31198 +
31199 +                               dctl.d32 = 0;
31200 +                               dctl.b.pwronprgdone = 1;
31201 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
31202 +                               dwc_udelay(10);
31203 +
31204 +                               pcgcctl.d32 = 0;
31205 +                               pcgcctl.b.enbl_extnd_hiber = 1;
31206 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31207 +
31208 +                               /* The core will be in ON STATE */
31209 +                               core_if->lx_state = DWC_OTG_L0;
31210 +                               core_if->xhib = 0;
31211 +
31212 +                               DWC_SPINUNLOCK(core_if->lock);
31213 +                               if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
31214 +                                       core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
31215 +                               }
31216 +                               DWC_SPINLOCK(core_if->lock);
31217 +
31218 +                       }
31219 +
31220 +                       gintsts.b.restoredone = 1;
31221 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31222 +                       DWC_PRINTF(" --Restore done interrupt received-- \n");
31223 +                       retval |= 1;
31224 +               }
31225 +               if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
31226 +                       /* The port interrupt occurs while in device mode with HPRT0
31227 +                        * Port Enable/Disable.
31228 +                        */
31229 +                       gintsts.d32 = 0;
31230 +                       gintsts.b.portintr = 1;
31231 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31232 +                       retval |= 1;
31233 +
31234 +               }
31235 +       } else {
31236 +               DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
31237 +
31238 +               if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
31239 +                       CLEAR_GPWRDN_INTR(core_if, disconn_det);
31240 +                       if (gpwrdn.b.linestate == 0) {
31241 +                               dwc_otg_handle_pwrdn_disconnect_intr(core_if);
31242 +                       } else {
31243 +                               DWC_PRINTF("Disconnect detected while linestate is not 0\n");
31244 +                       }
31245 +
31246 +                       retval |= 1;
31247 +               }
31248 +               if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
31249 +                       CLEAR_GPWRDN_INTR(core_if, lnstschng);
31250 +                       /* remote wakeup from hibernation */
31251 +                       if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
31252 +                               dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
31253 +                       } else {
31254 +                               DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
31255 +                       }
31256 +                       retval |= 1;
31257 +               }
31258 +               if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
31259 +                       CLEAR_GPWRDN_INTR(core_if, rst_det);
31260 +                       if (gpwrdn.b.linestate == 0) {
31261 +                               DWC_PRINTF("Reset detected\n");
31262 +                               retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
31263 +                       }
31264 +               }
31265 +               if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
31266 +                       CLEAR_GPWRDN_INTR(core_if, srp_det);
31267 +                       dwc_otg_handle_pwrdn_srp_intr(core_if);
31268 +                       retval |= 1;
31269 +               }
31270 +       }
31271 +       /* Handle ADP interrupt here */
31272 +       if (gpwrdn.b.adp_int) {
31273 +               DWC_PRINTF("ADP interrupt\n");
31274 +               CLEAR_GPWRDN_INTR(core_if, adp_int);
31275 +               dwc_otg_adp_handle_intr(core_if);
31276 +               retval |= 1;
31277 +       }
31278 +       if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
31279 +               DWC_PRINTF("STS CHNG interrupt asserted\n");
31280 +               CLEAR_GPWRDN_INTR(core_if, sts_chngint);
31281 +               dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
31282 +
31283 +               retval |= 1;
31284 +       }
31285 +       if (core_if->lock)
31286 +               DWC_SPINUNLOCK(core_if->lock);
31287 +
31288 +       return retval;
31289 +}
31290 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31291 new file mode 100644
31292 index 0000000..4138fd1
31293 --- /dev/null
31294 +++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31295 @@ -0,0 +1,705 @@
31296 +/* ==========================================================================
31297 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
31298 + * $Revision: #13 $
31299 + * $Date: 2012/08/10 $
31300 + * $Change: 2047372 $
31301 + *
31302 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31303 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31304 + * otherwise expressly agreed to in writing between Synopsys and you.
31305 + *
31306 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31307 + * any End User Software License Agreement or Agreement for Licensed Product
31308 + * with Synopsys or any supplement thereto. You are permitted to use and
31309 + * redistribute this Software in source and binary forms, with or without
31310 + * modification, provided that redistributions of source code must retain this
31311 + * notice. You may not view, use, disclose, copy or distribute this file or
31312 + * any information contained herein except pursuant to this license grant from
31313 + * Synopsys. If you do not agree with this notice, including the disclaimer
31314 + * below, then you are not authorized to use the Software.
31315 + *
31316 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31317 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31318 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31319 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31320 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31321 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31322 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31323 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31324 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31325 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31326 + * DAMAGE.
31327 + * ========================================================================== */
31328 +#if !defined(__DWC_CORE_IF_H__)
31329 +#define __DWC_CORE_IF_H__
31330 +
31331 +#include "dwc_os.h"
31332 +
31333 +/** @file
31334 + * This file defines DWC_OTG Core API
31335 + */
31336 +
31337 +struct dwc_otg_core_if;
31338 +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
31339 +
31340 +/** Maximum number of Periodic FIFOs */
31341 +#define MAX_PERIO_FIFOS 15
31342 +/** Maximum number of Periodic FIFOs */
31343 +#define MAX_TX_FIFOS 15
31344 +
31345 +/** Maximum number of Endpoints/HostChannels */
31346 +#define MAX_EPS_CHANNELS 16
31347 +
31348 +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
31349 +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
31350 +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
31351 +
31352 +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
31353 +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
31354 +
31355 +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
31356 +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
31357 +
31358 +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
31359 +
31360 +/** This function should be called on every hardware interrupt. */
31361 +extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
31362 +
31363 +/** @name OTG Core Parameters */
31364 +/** @{ */
31365 +
31366 +/**
31367 + * Specifies the OTG capabilities. The driver will automatically
31368 + * detect the value for this parameter if none is specified.
31369 + * 0 - HNP and SRP capable (default)
31370 + * 1 - SRP Only capable
31371 + * 2 - No HNP/SRP capable
31372 + */
31373 +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
31374 +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
31375 +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
31376 +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
31377 +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
31378 +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
31379 +
31380 +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
31381 +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
31382 +#define dwc_param_opt_default 1
31383 +
31384 +/**
31385 + * Specifies whether to use slave or DMA mode for accessing the data
31386 + * FIFOs. The driver will automatically detect the value for this
31387 + * parameter if none is specified.
31388 + * 0 - Slave
31389 + * 1 - DMA (default, if available)
31390 + */
31391 +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
31392 +                                       int32_t val);
31393 +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
31394 +#define dwc_param_dma_enable_default 1
31395 +
31396 +/**
31397 + * When DMA mode is enabled specifies whether to use
31398 + * address DMA or DMA Descritor mode for accessing the data
31399 + * FIFOs in device mode. The driver will automatically detect
31400 + * the value for this parameter if none is specified.
31401 + * 0 - address DMA
31402 + * 1 - DMA Descriptor(default, if available)
31403 + */
31404 +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
31405 +                                            int32_t val);
31406 +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
31407 +//#define dwc_param_dma_desc_enable_default 1
31408 +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
31409 +
31410 +/** The DMA Burst size (applicable only for External DMA
31411 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
31412 + */
31413 +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
31414 +                                           int32_t val);
31415 +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
31416 +#define dwc_param_dma_burst_size_default 32
31417 +
31418 +/**
31419 + * Specifies the maximum speed of operation in host and device mode.
31420 + * The actual speed depends on the speed of the attached device and
31421 + * the value of phy_type. The actual speed depends on the speed of the
31422 + * attached device.
31423 + * 0 - High Speed (default)
31424 + * 1 - Full Speed
31425 + */
31426 +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
31427 +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
31428 +#define dwc_param_speed_default 0
31429 +#define DWC_SPEED_PARAM_HIGH 0
31430 +#define DWC_SPEED_PARAM_FULL 1
31431 +
31432 +/** Specifies whether low power mode is supported when attached
31433 + *     to a Full Speed or Low Speed device in host mode.
31434 + * 0 - Don't support low power mode (default)
31435 + * 1 - Support low power mode
31436 + */
31437 +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
31438 +                                                         core_if, int32_t val);
31439 +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
31440 +                                                             * core_if);
31441 +#define dwc_param_host_support_fs_ls_low_power_default 0
31442 +
31443 +/** Specifies the PHY clock rate in low power mode when connected to a
31444 + * Low Speed device in host mode. This parameter is applicable only if
31445 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
31446 + * then defaults to 6 MHZ otherwise 48 MHZ.
31447 + *
31448 + * 0 - 48 MHz
31449 + * 1 - 6 MHz
31450 + */
31451 +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31452 +                                                      core_if, int32_t val);
31453 +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31454 +                                                          core_if);
31455 +#define dwc_param_host_ls_low_power_phy_clk_default 0
31456 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
31457 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
31458 +
31459 +/**
31460 + * 0 - Use cC FIFO size parameters
31461 + * 1 - Allow dynamic FIFO sizing (default)
31462 + */
31463 +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
31464 +                                                int32_t val);
31465 +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
31466 +                                                    core_if);
31467 +#define dwc_param_enable_dynamic_fifo_default 1
31468 +
31469 +/** Total number of 4-byte words in the data FIFO memory. This
31470 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
31471 + * Tx FIFOs.
31472 + * 32 to 32768 (default 8192)
31473 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
31474 + */
31475 +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
31476 +                                           int32_t val);
31477 +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
31478 +//#define dwc_param_data_fifo_size_default 8192
31479 +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
31480 +
31481 +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
31482 + * FIFO sizing is enabled.
31483 + * 16 to 32768 (default 1064)
31484 + */
31485 +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
31486 +                                             int32_t val);
31487 +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
31488 +#define dwc_param_dev_rx_fifo_size_default 1064
31489 +
31490 +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
31491 + * when dynamic FIFO sizing is enabled.
31492 + * 16 to 32768 (default 1024)
31493 + */
31494 +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31495 +                                                    core_if, int32_t val);
31496 +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31497 +                                                        core_if);
31498 +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
31499 +
31500 +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
31501 + * mode when dynamic FIFO sizing is enabled.
31502 + * 4 to 768 (default 256)
31503 + */
31504 +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
31505 +                                                   int32_t val, int fifo_num);
31506 +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
31507 +                                                       core_if, int fifo_num);
31508 +#define dwc_param_dev_perio_tx_fifo_size_default 256
31509 +
31510 +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
31511 + * FIFO sizing is enabled.
31512 + * 16 to 32768 (default 1024)
31513 + */
31514 +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
31515 +                                              int32_t val);
31516 +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
31517 +//#define dwc_param_host_rx_fifo_size_default 1024
31518 +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
31519 +
31520 +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
31521 + * when Dynamic FIFO sizing is enabled in the core.
31522 + * 16 to 32768 (default 1024)
31523 + */
31524 +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31525 +                                                     core_if, int32_t val);
31526 +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31527 +                                                         core_if);
31528 +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
31529 +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
31530 +
31531 +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
31532 + * FIFO sizing is enabled.
31533 + * 16 to 32768 (default 1024)
31534 + */
31535 +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31536 +                                                    core_if, int32_t val);
31537 +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31538 +                                                        core_if);
31539 +//#define dwc_param_host_perio_tx_fifo_size_default 1024
31540 +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
31541 +
31542 +/** The maximum transfer size supported in bytes.
31543 + * 2047 to 65,535  (default 65,535)
31544 + */
31545 +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
31546 +                                              int32_t val);
31547 +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
31548 +#define dwc_param_max_transfer_size_default 65535
31549 +
31550 +/** The maximum number of packets in a transfer.
31551 + * 15 to 511  (default 511)
31552 + */
31553 +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
31554 +                                             int32_t val);
31555 +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
31556 +#define dwc_param_max_packet_count_default 511
31557 +
31558 +/** The number of host channel registers to use.
31559 + * 1 to 16 (default 12)
31560 + * Note: The FPGA configuration supports a maximum of 12 host channels.
31561 + */
31562 +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
31563 +                                          int32_t val);
31564 +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
31565 +//#define dwc_param_host_channels_default 12
31566 +#define dwc_param_host_channels_default 8 // Broadcom BCM2708
31567 +
31568 +/** The number of endpoints in addition to EP0 available for device
31569 + * mode operations.
31570 + * 1 to 15 (default 6 IN and OUT)
31571 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
31572 + * endpoints in addition to EP0.
31573 + */
31574 +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
31575 +                                          int32_t val);
31576 +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
31577 +#define dwc_param_dev_endpoints_default 6
31578 +
31579 +/**
31580 + * Specifies the type of PHY interface to use. By default, the driver
31581 + * will automatically detect the phy_type.
31582 + *
31583 + * 0 - Full Speed PHY
31584 + * 1 - UTMI+ (default)
31585 + * 2 - ULPI
31586 + */
31587 +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
31588 +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
31589 +#define DWC_PHY_TYPE_PARAM_FS 0
31590 +#define DWC_PHY_TYPE_PARAM_UTMI 1
31591 +#define DWC_PHY_TYPE_PARAM_ULPI 2
31592 +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
31593 +
31594 +/**
31595 + * Specifies the UTMI+ Data Width. This parameter is
31596 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
31597 + * PHY_TYPE, this parameter indicates the data width between
31598 + * the MAC and the ULPI Wrapper.) Also, this parameter is
31599 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
31600 + * to "8 and 16 bits", meaning that the core has been
31601 + * configured to work at either data path width.
31602 + *
31603 + * 8 or 16 bits (default 16)
31604 + */
31605 +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
31606 +                                           int32_t val);
31607 +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
31608 +//#define dwc_param_phy_utmi_width_default 16
31609 +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708
31610 +
31611 +/**
31612 + * Specifies whether the ULPI operates at double or single
31613 + * data rate. This parameter is only applicable if PHY_TYPE is
31614 + * ULPI.
31615 + *
31616 + * 0 - single data rate ULPI interface with 8 bit wide data
31617 + * bus (default)
31618 + * 1 - double data rate ULPI interface with 4 bit wide data
31619 + * bus
31620 + */
31621 +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
31622 +                                         int32_t val);
31623 +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
31624 +#define dwc_param_phy_ulpi_ddr_default 0
31625 +
31626 +/**
31627 + * Specifies whether to use the internal or external supply to
31628 + * drive the vbus with a ULPI phy.
31629 + */
31630 +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
31631 +                                              int32_t val);
31632 +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
31633 +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
31634 +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
31635 +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
31636 +
31637 +/**
31638 + * Specifies whether to use the I2Cinterface for full speed PHY. This
31639 + * parameter is only applicable if PHY_TYPE is FS.
31640 + * 0 - No (default)
31641 + * 1 - Yes
31642 + */
31643 +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
31644 +                                       int32_t val);
31645 +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
31646 +#define dwc_param_i2c_enable_default 0
31647 +
31648 +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
31649 +                                       int32_t val);
31650 +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
31651 +#define dwc_param_ulpi_fs_ls_default 0
31652 +
31653 +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
31654 +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
31655 +#define dwc_param_ts_dline_default 0
31656 +
31657 +/**
31658 + * Specifies whether dedicated transmit FIFOs are
31659 + * enabled for non periodic IN endpoints in device mode
31660 + * 0 - No
31661 + * 1 - Yes
31662 + */
31663 +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
31664 +                                                int32_t val);
31665 +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
31666 +                                                    core_if);
31667 +#define dwc_param_en_multiple_tx_fifo_default 1
31668 +
31669 +/** Number of 4-byte words in each of the Tx FIFOs in device
31670 + * mode when dynamic FIFO sizing is enabled.
31671 + * 4 to 768 (default 256)
31672 + */
31673 +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31674 +                                             int fifo_num, int32_t val);
31675 +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31676 +                                                 int fifo_num);
31677 +#define dwc_param_dev_tx_fifo_size_default 768
31678 +
31679 +/** Thresholding enable flag-
31680 + * bit 0 - enable non-ISO Tx thresholding
31681 + * bit 1 - enable ISO Tx thresholding
31682 + * bit 2 - enable Rx thresholding
31683 + */
31684 +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
31685 +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
31686 +#define dwc_param_thr_ctl_default 0
31687 +
31688 +/** Thresholding length for Tx
31689 + * FIFOs in 32 bit DWORDs
31690 + */
31691 +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
31692 +                                          int32_t val);
31693 +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
31694 +#define dwc_param_tx_thr_length_default 64
31695 +
31696 +/** Thresholding length for Rx
31697 + *     FIFOs in 32 bit DWORDs
31698 + */
31699 +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
31700 +                                          int32_t val);
31701 +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
31702 +#define dwc_param_rx_thr_length_default 64
31703 +
31704 +/**
31705 + * Specifies whether LPM (Link Power Management) support is enabled
31706 + */
31707 +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
31708 +                                       int32_t val);
31709 +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
31710 +#define dwc_param_lpm_enable_default 1
31711 +
31712 +/**
31713 + * Specifies whether PTI enhancement is enabled
31714 + */
31715 +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
31716 +                                       int32_t val);
31717 +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
31718 +#define dwc_param_pti_enable_default 0
31719 +
31720 +/**
31721 + * Specifies whether MPI enhancement is enabled
31722 + */
31723 +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
31724 +                                       int32_t val);
31725 +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
31726 +#define dwc_param_mpi_enable_default 0
31727 +
31728 +/**
31729 + * Specifies whether ADP capability is enabled
31730 + */
31731 +extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,
31732 +                                       int32_t val);
31733 +extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);
31734 +#define dwc_param_adp_enable_default 0
31735 +
31736 +/**
31737 + * Specifies whether IC_USB capability is enabled
31738 + */
31739 +
31740 +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
31741 +                                       int32_t val);
31742 +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
31743 +#define dwc_param_ic_usb_cap_default 0
31744 +
31745 +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,
31746 +                                          int32_t val);
31747 +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
31748 +#define dwc_param_ahb_thr_ratio_default 0
31749 +
31750 +extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,
31751 +                                       int32_t val);
31752 +extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);
31753 +#define dwc_param_power_down_default 0
31754 +
31755 +extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,
31756 +                                       int32_t val);
31757 +extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);
31758 +#define dwc_param_reload_ctl_default 0
31759 +
31760 +extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,
31761 +                                                                               int32_t val);
31762 +extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
31763 +#define dwc_param_dev_out_nak_default 0
31764 +
31765 +extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
31766 +                                                                                int32_t val);
31767 +extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
31768 +#define dwc_param_cont_on_bna_default 0
31769 +
31770 +extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
31771 +                                                                                int32_t val);
31772 +extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
31773 +#define dwc_param_ahb_single_default 0
31774 +
31775 +extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
31776 +extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
31777 +#define dwc_param_otg_ver_default 0
31778 +
31779 +/** @} */
31780 +
31781 +/** @name Access to registers and bit-fields */
31782 +
31783 +/**
31784 + * Dump core registers and SPRAM
31785 + */
31786 +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
31787 +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
31788 +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
31789 +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
31790 +
31791 +/**
31792 + * Get host negotiation status.
31793 + */
31794 +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
31795 +
31796 +/**
31797 + * Get srp status
31798 + */
31799 +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
31800 +
31801 +/**
31802 + * Set hnpreq bit in the GOTGCTL register.
31803 + */
31804 +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
31805 +
31806 +/**
31807 + * Get Content of SNPSID register.
31808 + */
31809 +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
31810 +
31811 +/**
31812 + * Get current mode.
31813 + * Returns 0 if in device mode, and 1 if in host mode.
31814 + */
31815 +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
31816 +
31817 +/**
31818 + * Get value of hnpcapable field in the GUSBCFG register
31819 + */
31820 +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
31821 +/**
31822 + * Set value of hnpcapable field in the GUSBCFG register
31823 + */
31824 +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31825 +
31826 +/**
31827 + * Get value of srpcapable field in the GUSBCFG register
31828 + */
31829 +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
31830 +/**
31831 + * Set value of srpcapable field in the GUSBCFG register
31832 + */
31833 +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31834 +
31835 +/**
31836 + * Get value of devspeed field in the DCFG register
31837 + */
31838 +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
31839 +/**
31840 + * Set value of devspeed field in the DCFG register
31841 + */
31842 +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
31843 +
31844 +/**
31845 + * Get the value of busconnected field from the HPRT0 register
31846 + */
31847 +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
31848 +
31849 +/**
31850 + * Gets the device enumeration Speed.
31851 + */
31852 +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
31853 +
31854 +/**
31855 + * Get value of prtpwr field from the HPRT0 register
31856 + */
31857 +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
31858 +
31859 +/**
31860 + * Get value of flag indicating core state - hibernated or not
31861 + */
31862 +extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);
31863 +
31864 +/**
31865 + * Set value of prtpwr field from the HPRT0 register
31866 + */
31867 +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
31868 +
31869 +/**
31870 + * Get value of prtsusp field from the HPRT0 regsiter
31871 + */
31872 +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
31873 +/**
31874 + * Set value of prtpwr field from the HPRT0 register
31875 + */
31876 +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
31877 +
31878 +/**
31879 + * Get value of ModeChTimEn field from the HCFG regsiter
31880 + */
31881 +extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);
31882 +/**
31883 + * Set value of ModeChTimEn field from the HCFG regsiter
31884 + */
31885 +extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);
31886 +
31887 +/**
31888 + * Get value of Fram Interval field from the HFIR regsiter
31889 + */
31890 +extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);
31891 +/**
31892 + * Set value of Frame Interval field from the HFIR regsiter
31893 + */
31894 +extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);
31895 +
31896 +/**
31897 + * Set value of prtres field from the HPRT0 register
31898 + *FIXME Remove?
31899 + */
31900 +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
31901 +
31902 +/**
31903 + * Get value of rmtwkupsig bit in DCTL register
31904 + */
31905 +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
31906 +
31907 +/**
31908 + * Get value of prt_sleep_sts field from the GLPMCFG register
31909 + */
31910 +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
31911 +
31912 +/**
31913 + * Get value of rem_wkup_en field from the GLPMCFG register
31914 + */
31915 +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
31916 +
31917 +/**
31918 + * Get value of appl_resp field from the GLPMCFG register
31919 + */
31920 +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
31921 +/**
31922 + * Set value of appl_resp field from the GLPMCFG register
31923 + */
31924 +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
31925 +
31926 +/**
31927 + * Get value of hsic_connect field from the GLPMCFG register
31928 + */
31929 +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
31930 +/**
31931 + * Set value of hsic_connect field from the GLPMCFG register
31932 + */
31933 +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
31934 +
31935 +/**
31936 + * Get value of inv_sel_hsic field from the GLPMCFG register.
31937 + */
31938 +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
31939 +/**
31940 + * Set value of inv_sel_hsic field from the GLPMFG register.
31941 + */
31942 +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
31943 +
31944 +/*
31945 + * Some functions for accessing registers
31946 + */
31947 +
31948 +/**
31949 + *  GOTGCTL register
31950 + */
31951 +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
31952 +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
31953 +
31954 +/**
31955 + * GUSBCFG register
31956 + */
31957 +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
31958 +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
31959 +
31960 +/**
31961 + * GRXFSIZ register
31962 + */
31963 +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
31964 +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31965 +
31966 +/**
31967 + * GNPTXFSIZ register
31968 + */
31969 +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
31970 +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31971 +
31972 +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
31973 +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
31974 +
31975 +/**
31976 + * GGPIO register
31977 + */
31978 +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
31979 +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
31980 +
31981 +/**
31982 + * GUID register
31983 + */
31984 +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
31985 +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
31986 +
31987 +/**
31988 + * HPRT0 register
31989 + */
31990 +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
31991 +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
31992 +
31993 +/**
31994 + * GHPTXFSIZE
31995 + */
31996 +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
31997 +
31998 +/** @} */
31999 +
32000 +#endif                         /* __DWC_CORE_IF_H__ */
32001 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
32002 new file mode 100644
32003 index 0000000..8900318
32004 --- /dev/null
32005 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
32006 @@ -0,0 +1,116 @@
32007 +/* ==========================================================================
32008 + *
32009 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32010 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32011 + * otherwise expressly agreed to in writing between Synopsys and you.
32012 + *
32013 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32014 + * any End User Software License Agreement or Agreement for Licensed Product
32015 + * with Synopsys or any supplement thereto. You are permitted to use and
32016 + * redistribute this Software in source and binary forms, with or without
32017 + * modification, provided that redistributions of source code must retain this
32018 + * notice. You may not view, use, disclose, copy or distribute this file or
32019 + * any information contained herein except pursuant to this license grant from
32020 + * Synopsys. If you do not agree with this notice, including the disclaimer
32021 + * below, then you are not authorized to use the Software.
32022 + *
32023 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32024 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32025 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32026 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32027 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32028 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32029 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32030 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32031 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32032 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32033 + * DAMAGE.
32034 + * ========================================================================== */
32035 +
32036 +#ifndef __DWC_OTG_DBG_H__
32037 +#define __DWC_OTG_DBG_H__
32038 +
32039 +/** @file
32040 + * This file defines debug levels.
32041 + * Debugging support vanishes in non-debug builds.
32042 + */
32043 +
32044 +/**
32045 + * The Debug Level bit-mask variable.
32046 + */
32047 +extern uint32_t g_dbg_lvl;
32048 +/**
32049 + * Set the Debug Level variable.
32050 + */
32051 +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
32052 +{
32053 +       uint32_t old = g_dbg_lvl;
32054 +       g_dbg_lvl = new;
32055 +       return old;
32056 +}
32057 +
32058 +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
32059 +#define DBG_CIL                (0x2)
32060 +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
32061 + * messages */
32062 +#define DBG_CILV       (0x20)
32063 +/**  When debug level has the DBG_PCD bit set, display PCD (Device) debug
32064 + *  messages */
32065 +#define DBG_PCD                (0x4)
32066 +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
32067 + * messages */
32068 +#define DBG_PCDV       (0x40)
32069 +/** When debug level has the DBG_HCD bit set, display Host debug messages */
32070 +#define DBG_HCD                (0x8)
32071 +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
32072 + * messages */
32073 +#define DBG_HCDV       (0x80)
32074 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
32075 + *  mode. */
32076 +#define DBG_HCD_URB    (0x800)
32077 +/** When debug level has the DBG_HCDI bit set, display host interrupt
32078 + *  messages. */
32079 +#define DBG_HCDI       (0x1000)
32080 +
32081 +/** When debug level has any bit set, display debug messages */
32082 +#define DBG_ANY                (0xFF)
32083 +
32084 +/** All debug messages off */
32085 +#define DBG_OFF                0
32086 +
32087 +/** Prefix string for DWC_DEBUG print macros. */
32088 +#define USB_DWC "DWC_otg: "
32089 +
32090 +/**
32091 + * Print a debug message when the Global debug level variable contains
32092 + * the bit defined in <code>lvl</code>.
32093 + *
32094 + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
32095 + * @param[in] x - like printf
32096 + *
32097 + *    Example:<p>
32098 + * <code>
32099 + *      DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
32100 + * </code>
32101 + * <br>
32102 + * results in:<br>
32103 + * <code>
32104 + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
32105 + * </code>
32106 + */
32107 +#ifdef DEBUG
32108 +
32109 +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
32110 +# define DWC_DEBUGP(x...)      DWC_DEBUGPL(DBG_ANY, x )
32111 +
32112 +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
32113 +
32114 +#else
32115 +
32116 +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
32117 +# define DWC_DEBUGP(x...)
32118 +
32119 +# define CHK_DEBUG_LEVEL(level) (0)
32120 +
32121 +#endif /*DEBUG*/
32122 +#endif
32123 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
32124 new file mode 100644
32125 index 0000000..ac2c846
32126 --- /dev/null
32127 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
32128 @@ -0,0 +1,1700 @@
32129 +/* ==========================================================================
32130 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
32131 + * $Revision: #92 $
32132 + * $Date: 2012/08/10 $
32133 + * $Change: 2047372 $
32134 + *
32135 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32136 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32137 + * otherwise expressly agreed to in writing between Synopsys and you.
32138 + *
32139 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32140 + * any End User Software License Agreement or Agreement for Licensed Product
32141 + * with Synopsys or any supplement thereto. You are permitted to use and
32142 + * redistribute this Software in source and binary forms, with or without
32143 + * modification, provided that redistributions of source code must retain this
32144 + * notice. You may not view, use, disclose, copy or distribute this file or
32145 + * any information contained herein except pursuant to this license grant from
32146 + * Synopsys. If you do not agree with this notice, including the disclaimer
32147 + * below, then you are not authorized to use the Software.
32148 + *
32149 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32150 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32151 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32152 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32153 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32154 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32155 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32156 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32157 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32158 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32159 + * DAMAGE.
32160 + * ========================================================================== */
32161 +
32162 +/** @file
32163 + * The dwc_otg_driver module provides the initialization and cleanup entry
32164 + * points for the DWC_otg driver. This module will be dynamically installed
32165 + * after Linux is booted using the insmod command. When the module is
32166 + * installed, the dwc_otg_driver_init function is called. When the module is
32167 + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
32168 + *
32169 + * This module also defines a data structure for the dwc_otg_driver, which is
32170 + * used in conjunction with the standard ARM lm_device structure. These
32171 + * structures allow the OTG driver to comply with the standard Linux driver
32172 + * model in which devices and drivers are registered with a bus driver. This
32173 + * has the benefit that Linux can expose attributes of the driver and device
32174 + * in its special sysfs file system. Users can then read or write files in
32175 + * this file system to perform diagnostics on the driver components or the
32176 + * device.
32177 + */
32178 +
32179 +#include "dwc_otg_os_dep.h"
32180 +#include "dwc_os.h"
32181 +#include "dwc_otg_dbg.h"
32182 +#include "dwc_otg_driver.h"
32183 +#include "dwc_otg_attr.h"
32184 +#include "dwc_otg_core_if.h"
32185 +#include "dwc_otg_pcd_if.h"
32186 +#include "dwc_otg_hcd_if.h"
32187 +
32188 +#define DWC_DRIVER_VERSION     "3.00a 10-AUG-2012"
32189 +#define DWC_DRIVER_DESC                "HS OTG USB Controller driver"
32190 +
32191 +bool microframe_schedule=true;
32192 +
32193 +static const char dwc_driver_name[] = "dwc_otg";
32194 +
32195 +extern int pcd_init(
32196 +#ifdef LM_INTERFACE
32197 +                          struct lm_device *_dev
32198 +#elif  defined(PCI_INTERFACE)
32199 +                          struct pci_dev *_dev
32200 +#elif  defined(PLATFORM_INTERFACE)
32201 +       struct platform_device *dev
32202 +#endif
32203 +    );
32204 +extern int hcd_init(
32205 +#ifdef LM_INTERFACE
32206 +                          struct lm_device *_dev
32207 +#elif  defined(PCI_INTERFACE)
32208 +                          struct pci_dev *_dev
32209 +#elif  defined(PLATFORM_INTERFACE)
32210 +       struct platform_device *dev
32211 +#endif
32212 +    );
32213 +
32214 +extern int pcd_remove(
32215 +#ifdef LM_INTERFACE
32216 +                            struct lm_device *_dev
32217 +#elif  defined(PCI_INTERFACE)
32218 +                            struct pci_dev *_dev
32219 +#elif  defined(PLATFORM_INTERFACE)
32220 +       struct platform_device *_dev
32221 +#endif
32222 +    );
32223 +
32224 +extern void hcd_remove(
32225 +#ifdef LM_INTERFACE
32226 +                             struct lm_device *_dev
32227 +#elif  defined(PCI_INTERFACE)
32228 +                             struct pci_dev *_dev
32229 +#elif  defined(PLATFORM_INTERFACE)
32230 +       struct platform_device *_dev
32231 +#endif
32232 +    );
32233 +
32234 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
32235 +
32236 +/*-------------------------------------------------------------------------*/
32237 +/* Encapsulate the module parameter settings */
32238 +
32239 +struct dwc_otg_driver_module_params {
32240 +       int32_t opt;
32241 +       int32_t otg_cap;
32242 +       int32_t dma_enable;
32243 +       int32_t dma_desc_enable;
32244 +       int32_t dma_burst_size;
32245 +       int32_t speed;
32246 +       int32_t host_support_fs_ls_low_power;
32247 +       int32_t host_ls_low_power_phy_clk;
32248 +       int32_t enable_dynamic_fifo;
32249 +       int32_t data_fifo_size;
32250 +       int32_t dev_rx_fifo_size;
32251 +       int32_t dev_nperio_tx_fifo_size;
32252 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
32253 +       int32_t host_rx_fifo_size;
32254 +       int32_t host_nperio_tx_fifo_size;
32255 +       int32_t host_perio_tx_fifo_size;
32256 +       int32_t max_transfer_size;
32257 +       int32_t max_packet_count;
32258 +       int32_t host_channels;
32259 +       int32_t dev_endpoints;
32260 +       int32_t phy_type;
32261 +       int32_t phy_utmi_width;
32262 +       int32_t phy_ulpi_ddr;
32263 +       int32_t phy_ulpi_ext_vbus;
32264 +       int32_t i2c_enable;
32265 +       int32_t ulpi_fs_ls;
32266 +       int32_t ts_dline;
32267 +       int32_t en_multiple_tx_fifo;
32268 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
32269 +       uint32_t thr_ctl;
32270 +       uint32_t tx_thr_length;
32271 +       uint32_t rx_thr_length;
32272 +       int32_t pti_enable;
32273 +       int32_t mpi_enable;
32274 +       int32_t lpm_enable;
32275 +       int32_t ic_usb_cap;
32276 +       int32_t ahb_thr_ratio;
32277 +       int32_t power_down;
32278 +       int32_t reload_ctl;
32279 +       int32_t dev_out_nak;
32280 +       int32_t cont_on_bna;
32281 +       int32_t ahb_single;
32282 +       int32_t otg_ver;
32283 +       int32_t adp_enable;
32284 +};
32285 +
32286 +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
32287 +       .opt = -1,
32288 +       .otg_cap = -1,
32289 +       .dma_enable = -1,
32290 +       .dma_desc_enable = -1,
32291 +       .dma_burst_size = -1,
32292 +       .speed = -1,
32293 +       .host_support_fs_ls_low_power = -1,
32294 +       .host_ls_low_power_phy_clk = -1,
32295 +       .enable_dynamic_fifo = -1,
32296 +       .data_fifo_size = -1,
32297 +       .dev_rx_fifo_size = -1,
32298 +       .dev_nperio_tx_fifo_size = -1,
32299 +       .dev_perio_tx_fifo_size = {
32300 +                                  /* dev_perio_tx_fifo_size_1 */
32301 +                                  -1,
32302 +                                  -1,
32303 +                                  -1,
32304 +                                  -1,
32305 +                                  -1,
32306 +                                  -1,
32307 +                                  -1,
32308 +                                  -1,
32309 +                                  -1,
32310 +                                  -1,
32311 +                                  -1,
32312 +                                  -1,
32313 +                                  -1,
32314 +                                  -1,
32315 +                                  -1
32316 +                                  /* 15 */
32317 +                                  },
32318 +       .host_rx_fifo_size = -1,
32319 +       .host_nperio_tx_fifo_size = -1,
32320 +       .host_perio_tx_fifo_size = -1,
32321 +       .max_transfer_size = -1,
32322 +       .max_packet_count = -1,
32323 +       .host_channels = -1,
32324 +       .dev_endpoints = -1,
32325 +       .phy_type = -1,
32326 +       .phy_utmi_width = -1,
32327 +       .phy_ulpi_ddr = -1,
32328 +       .phy_ulpi_ext_vbus = -1,
32329 +       .i2c_enable = -1,
32330 +       .ulpi_fs_ls = -1,
32331 +       .ts_dline = -1,
32332 +       .en_multiple_tx_fifo = -1,
32333 +       .dev_tx_fifo_size = {
32334 +                            /* dev_tx_fifo_size */
32335 +                            -1,
32336 +                            -1,
32337 +                            -1,
32338 +                            -1,
32339 +                            -1,
32340 +                            -1,
32341 +                            -1,
32342 +                            -1,
32343 +                            -1,
32344 +                            -1,
32345 +                            -1,
32346 +                            -1,
32347 +                            -1,
32348 +                            -1,
32349 +                            -1
32350 +                            /* 15 */
32351 +                            },
32352 +       .thr_ctl = -1,
32353 +       .tx_thr_length = -1,
32354 +       .rx_thr_length = -1,
32355 +       .pti_enable = -1,
32356 +       .mpi_enable = -1,
32357 +       .lpm_enable = 0,
32358 +       .ic_usb_cap = -1,
32359 +       .ahb_thr_ratio = -1,
32360 +       .power_down = -1,
32361 +       .reload_ctl = -1,
32362 +       .dev_out_nak = -1,
32363 +       .cont_on_bna = -1,
32364 +       .ahb_single = -1,
32365 +       .otg_ver = -1,
32366 +       .adp_enable = -1,
32367 +};
32368 +
32369 +/**
32370 + * This function shows the Driver Version.
32371 + */
32372 +static ssize_t version_show(struct device_driver *dev, char *buf)
32373 +{
32374 +       return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
32375 +                       DWC_DRIVER_VERSION);
32376 +}
32377 +
32378 +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
32379 +
32380 +/**
32381 + * Global Debug Level Mask.
32382 + */
32383 +uint32_t g_dbg_lvl = 0;                /* OFF */
32384 +
32385 +/**
32386 + * This function shows the driver Debug Level.
32387 + */
32388 +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
32389 +{
32390 +       return sprintf(buf, "0x%0x\n", g_dbg_lvl);
32391 +}
32392 +
32393 +/**
32394 + * This function stores the driver Debug Level.
32395 + */
32396 +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
32397 +                              size_t count)
32398 +{
32399 +       g_dbg_lvl = simple_strtoul(buf, NULL, 16);
32400 +       return count;
32401 +}
32402 +
32403 +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
32404 +                  dbg_level_store);
32405 +
32406 +/**
32407 + * This function is called during module intialization
32408 + * to pass module parameters to the DWC_OTG CORE.
32409 + */
32410 +static int set_parameters(dwc_otg_core_if_t * core_if)
32411 +{
32412 +       int retval = 0;
32413 +       int i;
32414 +
32415 +       if (dwc_otg_module_params.otg_cap != -1) {
32416 +               retval +=
32417 +                   dwc_otg_set_param_otg_cap(core_if,
32418 +                                             dwc_otg_module_params.otg_cap);
32419 +       }
32420 +       if (dwc_otg_module_params.dma_enable != -1) {
32421 +               retval +=
32422 +                   dwc_otg_set_param_dma_enable(core_if,
32423 +                                                dwc_otg_module_params.
32424 +                                                dma_enable);
32425 +       }
32426 +       if (dwc_otg_module_params.dma_desc_enable != -1) {
32427 +               retval +=
32428 +                   dwc_otg_set_param_dma_desc_enable(core_if,
32429 +                                                     dwc_otg_module_params.
32430 +                                                     dma_desc_enable);
32431 +       }
32432 +       if (dwc_otg_module_params.opt != -1) {
32433 +               retval +=
32434 +                   dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
32435 +       }
32436 +       if (dwc_otg_module_params.dma_burst_size != -1) {
32437 +               retval +=
32438 +                   dwc_otg_set_param_dma_burst_size(core_if,
32439 +                                                    dwc_otg_module_params.
32440 +                                                    dma_burst_size);
32441 +       }
32442 +       if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
32443 +               retval +=
32444 +                   dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
32445 +                                                                  dwc_otg_module_params.
32446 +                                                                  host_support_fs_ls_low_power);
32447 +       }
32448 +       if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
32449 +               retval +=
32450 +                   dwc_otg_set_param_enable_dynamic_fifo(core_if,
32451 +                                                         dwc_otg_module_params.
32452 +                                                         enable_dynamic_fifo);
32453 +       }
32454 +       if (dwc_otg_module_params.data_fifo_size != -1) {
32455 +               retval +=
32456 +                   dwc_otg_set_param_data_fifo_size(core_if,
32457 +                                                    dwc_otg_module_params.
32458 +                                                    data_fifo_size);
32459 +       }
32460 +       if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
32461 +               retval +=
32462 +                   dwc_otg_set_param_dev_rx_fifo_size(core_if,
32463 +                                                      dwc_otg_module_params.
32464 +                                                      dev_rx_fifo_size);
32465 +       }
32466 +       if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
32467 +               retval +=
32468 +                   dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
32469 +                                                             dwc_otg_module_params.
32470 +                                                             dev_nperio_tx_fifo_size);
32471 +       }
32472 +       if (dwc_otg_module_params.host_rx_fifo_size != -1) {
32473 +               retval +=
32474 +                   dwc_otg_set_param_host_rx_fifo_size(core_if,
32475 +                                                       dwc_otg_module_params.host_rx_fifo_size);
32476 +       }
32477 +       if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
32478 +               retval +=
32479 +                   dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
32480 +                                                              dwc_otg_module_params.
32481 +                                                              host_nperio_tx_fifo_size);
32482 +       }
32483 +       if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
32484 +               retval +=
32485 +                   dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
32486 +                                                             dwc_otg_module_params.
32487 +                                                             host_perio_tx_fifo_size);
32488 +       }
32489 +       if (dwc_otg_module_params.max_transfer_size != -1) {
32490 +               retval +=
32491 +                   dwc_otg_set_param_max_transfer_size(core_if,
32492 +                                                       dwc_otg_module_params.
32493 +                                                       max_transfer_size);
32494 +       }
32495 +       if (dwc_otg_module_params.max_packet_count != -1) {
32496 +               retval +=
32497 +                   dwc_otg_set_param_max_packet_count(core_if,
32498 +                                                      dwc_otg_module_params.
32499 +                                                      max_packet_count);
32500 +       }
32501 +       if (dwc_otg_module_params.host_channels != -1) {
32502 +               retval +=
32503 +                   dwc_otg_set_param_host_channels(core_if,
32504 +                                                   dwc_otg_module_params.
32505 +                                                   host_channels);
32506 +       }
32507 +       if (dwc_otg_module_params.dev_endpoints != -1) {
32508 +               retval +=
32509 +                   dwc_otg_set_param_dev_endpoints(core_if,
32510 +                                                   dwc_otg_module_params.
32511 +                                                   dev_endpoints);
32512 +       }
32513 +       if (dwc_otg_module_params.phy_type != -1) {
32514 +               retval +=
32515 +                   dwc_otg_set_param_phy_type(core_if,
32516 +                                              dwc_otg_module_params.phy_type);
32517 +       }
32518 +       if (dwc_otg_module_params.speed != -1) {
32519 +               retval +=
32520 +                   dwc_otg_set_param_speed(core_if,
32521 +                                           dwc_otg_module_params.speed);
32522 +       }
32523 +       if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
32524 +               retval +=
32525 +                   dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
32526 +                                                               dwc_otg_module_params.
32527 +                                                               host_ls_low_power_phy_clk);
32528 +       }
32529 +       if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
32530 +               retval +=
32531 +                   dwc_otg_set_param_phy_ulpi_ddr(core_if,
32532 +                                                  dwc_otg_module_params.
32533 +                                                  phy_ulpi_ddr);
32534 +       }
32535 +       if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
32536 +               retval +=
32537 +                   dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
32538 +                                                       dwc_otg_module_params.
32539 +                                                       phy_ulpi_ext_vbus);
32540 +       }
32541 +       if (dwc_otg_module_params.phy_utmi_width != -1) {
32542 +               retval +=
32543 +                   dwc_otg_set_param_phy_utmi_width(core_if,
32544 +                                                    dwc_otg_module_params.
32545 +                                                    phy_utmi_width);
32546 +       }
32547 +       if (dwc_otg_module_params.ulpi_fs_ls != -1) {
32548 +               retval +=
32549 +                   dwc_otg_set_param_ulpi_fs_ls(core_if,
32550 +                                                dwc_otg_module_params.ulpi_fs_ls);
32551 +       }
32552 +       if (dwc_otg_module_params.ts_dline != -1) {
32553 +               retval +=
32554 +                   dwc_otg_set_param_ts_dline(core_if,
32555 +                                              dwc_otg_module_params.ts_dline);
32556 +       }
32557 +       if (dwc_otg_module_params.i2c_enable != -1) {
32558 +               retval +=
32559 +                   dwc_otg_set_param_i2c_enable(core_if,
32560 +                                                dwc_otg_module_params.
32561 +                                                i2c_enable);
32562 +       }
32563 +       if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
32564 +               retval +=
32565 +                   dwc_otg_set_param_en_multiple_tx_fifo(core_if,
32566 +                                                         dwc_otg_module_params.
32567 +                                                         en_multiple_tx_fifo);
32568 +       }
32569 +       for (i = 0; i < 15; i++) {
32570 +               if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
32571 +                       retval +=
32572 +                           dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
32573 +                                                                    dwc_otg_module_params.
32574 +                                                                    dev_perio_tx_fifo_size
32575 +                                                                    [i], i);
32576 +               }
32577 +       }
32578 +
32579 +       for (i = 0; i < 15; i++) {
32580 +               if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
32581 +                       retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
32582 +                                                                    dwc_otg_module_params.
32583 +                                                                    dev_tx_fifo_size
32584 +                                                                    [i], i);
32585 +               }
32586 +       }
32587 +       if (dwc_otg_module_params.thr_ctl != -1) {
32588 +               retval +=
32589 +                   dwc_otg_set_param_thr_ctl(core_if,
32590 +                                             dwc_otg_module_params.thr_ctl);
32591 +       }
32592 +       if (dwc_otg_module_params.mpi_enable != -1) {
32593 +               retval +=
32594 +                   dwc_otg_set_param_mpi_enable(core_if,
32595 +                                                dwc_otg_module_params.
32596 +                                                mpi_enable);
32597 +       }
32598 +       if (dwc_otg_module_params.pti_enable != -1) {
32599 +               retval +=
32600 +                   dwc_otg_set_param_pti_enable(core_if,
32601 +                                                dwc_otg_module_params.
32602 +                                                pti_enable);
32603 +       }
32604 +       if (dwc_otg_module_params.lpm_enable != -1) {
32605 +               retval +=
32606 +                   dwc_otg_set_param_lpm_enable(core_if,
32607 +                                                dwc_otg_module_params.
32608 +                                                lpm_enable);
32609 +       }
32610 +       if (dwc_otg_module_params.ic_usb_cap != -1) {
32611 +               retval +=
32612 +                   dwc_otg_set_param_ic_usb_cap(core_if,
32613 +                                                dwc_otg_module_params.
32614 +                                                ic_usb_cap);
32615 +       }
32616 +       if (dwc_otg_module_params.tx_thr_length != -1) {
32617 +               retval +=
32618 +                   dwc_otg_set_param_tx_thr_length(core_if,
32619 +                                                   dwc_otg_module_params.tx_thr_length);
32620 +       }
32621 +       if (dwc_otg_module_params.rx_thr_length != -1) {
32622 +               retval +=
32623 +                   dwc_otg_set_param_rx_thr_length(core_if,
32624 +                                                   dwc_otg_module_params.
32625 +                                                   rx_thr_length);
32626 +       }
32627 +       if (dwc_otg_module_params.ahb_thr_ratio != -1) {
32628 +               retval +=
32629 +                   dwc_otg_set_param_ahb_thr_ratio(core_if,
32630 +                                                   dwc_otg_module_params.ahb_thr_ratio);
32631 +       }
32632 +       if (dwc_otg_module_params.power_down != -1) {
32633 +               retval +=
32634 +                   dwc_otg_set_param_power_down(core_if,
32635 +                                                dwc_otg_module_params.power_down);
32636 +       }
32637 +       if (dwc_otg_module_params.reload_ctl != -1) {
32638 +               retval +=
32639 +                   dwc_otg_set_param_reload_ctl(core_if,
32640 +                                                dwc_otg_module_params.reload_ctl);
32641 +       }
32642 +
32643 +       if (dwc_otg_module_params.dev_out_nak != -1) {
32644 +               retval +=
32645 +                       dwc_otg_set_param_dev_out_nak(core_if,
32646 +                       dwc_otg_module_params.dev_out_nak);
32647 +       }
32648 +
32649 +       if (dwc_otg_module_params.cont_on_bna != -1) {
32650 +               retval +=
32651 +                       dwc_otg_set_param_cont_on_bna(core_if,
32652 +                       dwc_otg_module_params.cont_on_bna);
32653 +       }
32654 +
32655 +       if (dwc_otg_module_params.ahb_single != -1) {
32656 +               retval +=
32657 +                       dwc_otg_set_param_ahb_single(core_if,
32658 +                       dwc_otg_module_params.ahb_single);
32659 +       }
32660 +
32661 +       if (dwc_otg_module_params.otg_ver != -1) {
32662 +               retval +=
32663 +                   dwc_otg_set_param_otg_ver(core_if,
32664 +                                             dwc_otg_module_params.otg_ver);
32665 +       }
32666 +       if (dwc_otg_module_params.adp_enable != -1) {
32667 +               retval +=
32668 +                   dwc_otg_set_param_adp_enable(core_if,
32669 +                                                dwc_otg_module_params.
32670 +                                                adp_enable);
32671 +       }
32672 +       return retval;
32673 +}
32674 +
32675 +/**
32676 + * This function is the top level interrupt handler for the Common
32677 + * (Device and host modes) interrupts.
32678 + */
32679 +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
32680 +{
32681 +       int32_t retval = IRQ_NONE;
32682 +
32683 +       retval = dwc_otg_handle_common_intr(dev);
32684 +       if (retval != 0) {
32685 +               S3C2410X_CLEAR_EINTPEND();
32686 +       }
32687 +       return IRQ_RETVAL(retval);
32688 +}
32689 +
32690 +/**
32691 + * This function is called when a lm_device is unregistered with the
32692 + * dwc_otg_driver. This happens, for example, when the rmmod command is
32693 + * executed. The device may or may not be electrically present. If it is
32694 + * present, the driver stops device processing. Any resources used on behalf
32695 + * of this device are freed.
32696 + *
32697 + * @param _dev
32698 + */
32699 +#ifdef LM_INTERFACE
32700 +#define REM_RETVAL(n)
32701 +static void dwc_otg_driver_remove(      struct lm_device *_dev )
32702 +{       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
32703 +#elif  defined(PCI_INTERFACE)
32704 +#define REM_RETVAL(n)
32705 +static void dwc_otg_driver_remove(      struct pci_dev *_dev )
32706 +{      dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
32707 +#elif  defined(PLATFORM_INTERFACE)
32708 +#define REM_RETVAL(n) n
32709 +static int dwc_otg_driver_remove(        struct platform_device *_dev )
32710 +{       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
32711 +#endif
32712 +
32713 +       DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
32714 +
32715 +       if (!otg_dev) {
32716 +               /* Memory allocation for the dwc_otg_device failed. */
32717 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
32718 +                return REM_RETVAL(-ENOMEM);
32719 +       }
32720 +#ifndef DWC_DEVICE_ONLY
32721 +       if (otg_dev->hcd) {
32722 +               hcd_remove(_dev);
32723 +       } else {
32724 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
32725 +                return REM_RETVAL(-EINVAL);
32726 +       }
32727 +#endif
32728 +
32729 +#ifndef DWC_HOST_ONLY
32730 +       if (otg_dev->pcd) {
32731 +               pcd_remove(_dev);
32732 +       } else {
32733 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);
32734 +                return REM_RETVAL(-EINVAL);
32735 +       }
32736 +#endif
32737 +       /*
32738 +        * Free the IRQ
32739 +        */
32740 +       if (otg_dev->common_irq_installed) {
32741 +#ifdef PLATFORM_INTERFACE
32742 +               free_irq(platform_get_irq(_dev, 0), otg_dev);
32743 +#else
32744 +               free_irq(_dev->irq, otg_dev);
32745 +#endif
32746 +        } else {
32747 +               DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
32748 +               return REM_RETVAL(-ENXIO);
32749 +       }
32750 +
32751 +       if (otg_dev->core_if) {
32752 +               dwc_otg_cil_remove(otg_dev->core_if);
32753 +       } else {
32754 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);
32755 +               return REM_RETVAL(-ENXIO);
32756 +       }
32757 +
32758 +       /*
32759 +        * Remove the device attributes
32760 +        */
32761 +       dwc_otg_attr_remove(_dev);
32762 +
32763 +       /*
32764 +        * Return the memory.
32765 +        */
32766 +       if (otg_dev->os_dep.base) {
32767 +               iounmap(otg_dev->os_dep.base);
32768 +       }
32769 +       DWC_FREE(otg_dev);
32770 +
32771 +       /*
32772 +        * Clear the drvdata pointer.
32773 +        */
32774 +#ifdef LM_INTERFACE
32775 +       lm_set_drvdata(_dev, 0);
32776 +#elif defined(PCI_INTERFACE)
32777 +        release_mem_region(otg_dev->os_dep.rsrc_start,
32778 +                           otg_dev->os_dep.rsrc_len);
32779 +       pci_set_drvdata(_dev, 0);
32780 +#elif  defined(PLATFORM_INTERFACE)
32781 +        platform_set_drvdata(_dev, 0);
32782 +#endif
32783 +        return REM_RETVAL(0);
32784 +}
32785 +
32786 +/**
32787 + * This function is called when an lm_device is bound to a
32788 + * dwc_otg_driver. It creates the driver components required to
32789 + * control the device (CIL, HCD, and PCD) and it initializes the
32790 + * device. The driver components are stored in a dwc_otg_device
32791 + * structure. A reference to the dwc_otg_device is saved in the
32792 + * lm_device. This allows the driver to access the dwc_otg_device
32793 + * structure on subsequent calls to driver methods for this device.
32794 + *
32795 + * @param _dev Bus device
32796 + */
32797 +static int dwc_otg_driver_probe(
32798 +#ifdef LM_INTERFACE
32799 +                                      struct lm_device *_dev
32800 +#elif defined(PCI_INTERFACE)
32801 +                                      struct pci_dev *_dev,
32802 +                                      const struct pci_device_id *id
32803 +#elif  defined(PLATFORM_INTERFACE)
32804 +                                       struct platform_device *_dev
32805 +#endif
32806 +    )
32807 +{
32808 +       int retval = 0;
32809 +       dwc_otg_device_t *dwc_otg_device;
32810 +        int devirq;
32811 +
32812 +       dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
32813 +#ifdef LM_INTERFACE
32814 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
32815 +#elif defined(PCI_INTERFACE)
32816 +       if (!id) {
32817 +               DWC_ERROR("Invalid pci_device_id %p", id);
32818 +               return -EINVAL;
32819 +       }
32820 +
32821 +       if (!_dev || (pci_enable_device(_dev) < 0)) {
32822 +               DWC_ERROR("Invalid pci_device %p", _dev);
32823 +               return -ENODEV;
32824 +       }
32825 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
32826 +       /* other stuff needed as well? */
32827 +
32828 +#elif  defined(PLATFORM_INTERFACE)
32829 +       dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
32830 +                (unsigned)_dev->resource->start,
32831 +                (unsigned)(_dev->resource->end - _dev->resource->start));
32832 +#endif
32833 +
32834 +       dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
32835 +
32836 +       if (!dwc_otg_device) {
32837 +               dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
32838 +               return -ENOMEM;
32839 +       }
32840 +
32841 +       memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
32842 +       dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
32843 +
32844 +       /*
32845 +        * Map the DWC_otg Core memory into virtual address space.
32846 +        */
32847 +#ifdef LM_INTERFACE
32848 +       dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);
32849 +
32850 +       if (!dwc_otg_device->os_dep.base) {
32851 +               dev_err(&_dev->dev, "ioremap() failed\n");
32852 +               DWC_FREE(dwc_otg_device);
32853 +               return -ENOMEM;
32854 +       }
32855 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32856 +               (unsigned)dwc_otg_device->os_dep.base);
32857 +#elif defined(PCI_INTERFACE)
32858 +       _dev->current_state = PCI_D0;
32859 +       _dev->dev.power.power_state = PMSG_ON;
32860 +
32861 +       if (!_dev->irq) {
32862 +               DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",
32863 +                         pci_name(_dev));
32864 +               iounmap(dwc_otg_device->os_dep.base);
32865 +               DWC_FREE(dwc_otg_device);
32866 +               return -ENODEV;
32867 +       }
32868 +
32869 +       dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);
32870 +       dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);
32871 +       DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",
32872 +                   (unsigned)dwc_otg_device->os_dep.rsrc_start,
32873 +                   (unsigned)dwc_otg_device->os_dep.rsrc_len);
32874 +       if (!request_mem_region
32875 +           (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,
32876 +            "dwc_otg")) {
32877 +               dev_dbg(&_dev->dev, "error requesting memory\n");
32878 +               iounmap(dwc_otg_device->os_dep.base);
32879 +               DWC_FREE(dwc_otg_device);
32880 +               return -EFAULT;
32881 +       }
32882 +
32883 +       dwc_otg_device->os_dep.base =
32884 +           ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,
32885 +                           dwc_otg_device->os_dep.rsrc_len);
32886 +       if (dwc_otg_device->os_dep.base == NULL) {
32887 +               dev_dbg(&_dev->dev, "error mapping memory\n");
32888 +               release_mem_region(dwc_otg_device->os_dep.rsrc_start,
32889 +                                  dwc_otg_device->os_dep.rsrc_len);
32890 +               iounmap(dwc_otg_device->os_dep.base);
32891 +               DWC_FREE(dwc_otg_device);
32892 +               return -EFAULT;
32893 +       }
32894 +       dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",
32895 +               dwc_otg_device->os_dep.base);
32896 +       dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;
32897 +       dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",
32898 +               dwc_otg_device->os_dep.base);
32899 +       dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
32900 +               (unsigned)dwc_otg_device->os_dep.rsrc_start,
32901 +               dwc_otg_device->os_dep.base);
32902 +
32903 +       pci_set_master(_dev);
32904 +       pci_set_drvdata(_dev, dwc_otg_device);
32905 +#elif defined(PLATFORM_INTERFACE)
32906 +        DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
32907 +                    _dev->resource->start,
32908 +                    _dev->resource->end - _dev->resource->start + 1);
32909 +#if 1
32910 +        if (!request_mem_region(_dev->resource->start,
32911 +                                _dev->resource->end - _dev->resource->start + 1,
32912 +                                "dwc_otg")) {
32913 +          dev_dbg(&_dev->dev, "error reserving mapped memory\n");
32914 +          retval = -EFAULT;
32915 +          goto fail;
32916 +        }
32917 +
32918 +       dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
32919 +                                                      _dev->resource->end -
32920 +                                                      _dev->resource->start+1);
32921 +#else
32922 +        {
32923 +                struct map_desc desc = {
32924 +                    .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
32925 +                    .pfn     = __phys_to_pfn((unsigned)_dev->resource->start),
32926 +                    .length  = SZ_128K,
32927 +                    .type    = MT_DEVICE
32928 +                };
32929 +                iotable_init(&desc, 1);
32930 +                dwc_otg_device->os_dep.base = (void *)desc.virtual;
32931 +        }
32932 +#endif
32933 +       if (!dwc_otg_device->os_dep.base) {
32934 +               dev_err(&_dev->dev, "ioremap() failed\n");
32935 +               retval = -ENOMEM;
32936 +               goto fail;
32937 +       }
32938 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32939 +                (unsigned)dwc_otg_device->os_dep.base);
32940 +#endif
32941 +
32942 +       /*
32943 +        * Initialize driver data to point to the global DWC_otg
32944 +        * Device structure.
32945 +        */
32946 +#ifdef LM_INTERFACE
32947 +       lm_set_drvdata(_dev, dwc_otg_device);
32948 +#elif defined(PLATFORM_INTERFACE)
32949 +       platform_set_drvdata(_dev, dwc_otg_device);
32950 +#endif
32951 +       dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
32952 +
32953 +       dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
32954 +        DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
32955 +                    dwc_otg_device, dwc_otg_device->core_if);//GRAYG
32956 +
32957 +       if (!dwc_otg_device->core_if) {
32958 +               dev_err(&_dev->dev, "CIL initialization failed!\n");
32959 +               retval = -ENOMEM;
32960 +               goto fail;
32961 +       }
32962 +
32963 +       dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
32964 +       /*
32965 +        * Attempt to ensure this device is really a DWC_otg Controller.
32966 +        * Read and verify the SNPSID register contents. The value should be
32967 +        * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",
32968 +        * as in "OTG version 2.XX" or "OTG version 3.XX".
32969 +        */
32970 +
32971 +       if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=     0x4F542000) &&
32972 +               ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
32973 +               dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
32974 +                       dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
32975 +               retval = -EINVAL;
32976 +               goto fail;
32977 +       }
32978 +
32979 +       /*
32980 +        * Validate parameter values.
32981 +        */
32982 +       dev_dbg(&_dev->dev, "Calling set_parameters\n");
32983 +       if (set_parameters(dwc_otg_device->core_if)) {
32984 +               retval = -EINVAL;
32985 +               goto fail;
32986 +       }
32987 +
32988 +       /*
32989 +        * Create Device Attributes in sysfs
32990 +        */
32991 +       dev_dbg(&_dev->dev, "Calling attr_create\n");
32992 +       dwc_otg_attr_create(_dev);
32993 +
32994 +       /*
32995 +        * Disable the global interrupt until all the interrupt
32996 +        * handlers are installed.
32997 +        */
32998 +       dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
32999 +       dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
33000 +
33001 +       /*
33002 +        * Install the interrupt handler for the common interrupts before
33003 +        * enabling common interrupts in core_init below.
33004 +        */
33005 +
33006 +#if defined(PLATFORM_INTERFACE)
33007 +        devirq = platform_get_irq(_dev, 0);
33008 +#else
33009 +        devirq = _dev->irq;
33010 +#endif
33011 +       DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
33012 +                   devirq);
33013 +       dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
33014 +       retval = request_irq(devirq, dwc_otg_common_irq,
33015 +                             IRQF_SHARED,
33016 +                             "dwc_otg", dwc_otg_device);
33017 +       if (retval) {
33018 +               DWC_ERROR("request of irq%d failed\n", devirq);
33019 +               retval = -EBUSY;
33020 +               goto fail;
33021 +       } else {
33022 +               dwc_otg_device->common_irq_installed = 1;
33023 +       }
33024 +
33025 +#ifndef IRQF_TRIGGER_LOW
33026 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
33027 +       dev_dbg(&_dev->dev, "Calling set_irq_type\n");
33028 +       set_irq_type(devirq,
33029 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
33030 +                     IRQT_LOW
33031 +#else
33032 +                     IRQ_TYPE_LEVEL_LOW
33033 +#endif
33034 +                    );
33035 +#endif
33036 +#endif /*IRQF_TRIGGER_LOW*/
33037 +
33038 +       /*
33039 +        * Initialize the DWC_otg core.
33040 +        */
33041 +       dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
33042 +       dwc_otg_core_init(dwc_otg_device->core_if);
33043 +
33044 +#ifndef DWC_HOST_ONLY
33045 +       /*
33046 +        * Initialize the PCD
33047 +        */
33048 +       dev_dbg(&_dev->dev, "Calling pcd_init\n");
33049 +       retval = pcd_init(_dev);
33050 +       if (retval != 0) {
33051 +               DWC_ERROR("pcd_init failed\n");
33052 +               dwc_otg_device->pcd = NULL;
33053 +               goto fail;
33054 +       }
33055 +#endif
33056 +#ifndef DWC_DEVICE_ONLY
33057 +       /*
33058 +        * Initialize the HCD
33059 +        */
33060 +       dev_dbg(&_dev->dev, "Calling hcd_init\n");
33061 +       retval = hcd_init(_dev);
33062 +       if (retval != 0) {
33063 +               DWC_ERROR("hcd_init failed\n");
33064 +               dwc_otg_device->hcd = NULL;
33065 +               goto fail;
33066 +       }
33067 +#endif
33068 +        /* Recover from drvdata having been overwritten by hcd_init() */
33069 +#ifdef LM_INTERFACE
33070 +       lm_set_drvdata(_dev, dwc_otg_device);
33071 +#elif defined(PLATFORM_INTERFACE)
33072 +       platform_set_drvdata(_dev, dwc_otg_device);
33073 +#elif defined(PCI_INTERFACE)
33074 +       pci_set_drvdata(_dev, dwc_otg_device);
33075 +       dwc_otg_device->os_dep.pcidev = _dev;
33076 +#endif
33077 +
33078 +       /*
33079 +        * Enable the global interrupt after all the interrupt
33080 +        * handlers are installed if there is no ADP support else
33081 +        * perform initial actions required for Internal ADP logic.
33082 +        */
33083 +       if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
33084 +               dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
33085 +               dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
33086 +               dev_dbg(&_dev->dev, "Done\n");
33087 +       } else
33088 +               dwc_otg_adp_start(dwc_otg_device->core_if,
33089 +                                                       dwc_otg_is_host_mode(dwc_otg_device->core_if));
33090 +
33091 +       return 0;
33092 +
33093 +fail:
33094 +       dwc_otg_driver_remove(_dev);
33095 +       return retval;
33096 +}
33097 +
33098 +/**
33099 + * This structure defines the methods to be called by a bus driver
33100 + * during the lifecycle of a device on that bus. Both drivers and
33101 + * devices are registered with a bus driver. The bus driver matches
33102 + * devices to drivers based on information in the device and driver
33103 + * structures.
33104 + *
33105 + * The probe function is called when the bus driver matches a device
33106 + * to this driver. The remove function is called when a device is
33107 + * unregistered with the bus driver.
33108 + */
33109 +#ifdef LM_INTERFACE
33110 +static struct lm_driver dwc_otg_driver = {
33111 +       .drv = {.name = (char *)dwc_driver_name,},
33112 +       .probe = dwc_otg_driver_probe,
33113 +       .remove = dwc_otg_driver_remove,
33114 +        // 'suspend' and 'resume' absent
33115 +};
33116 +#elif defined(PCI_INTERFACE)
33117 +static const struct pci_device_id pci_ids[] = { {
33118 +                                                PCI_DEVICE(0x16c3, 0xabcd),
33119 +                                                .driver_data =
33120 +                                                (unsigned long)0xdeadbeef,
33121 +                                                }, { /* end: all zeroes */ }
33122 +};
33123 +
33124 +MODULE_DEVICE_TABLE(pci, pci_ids);
33125 +
33126 +/* pci driver glue; this is a "new style" PCI driver module */
33127 +static struct pci_driver dwc_otg_driver = {
33128 +       .name = "dwc_otg",
33129 +       .id_table = pci_ids,
33130 +
33131 +       .probe = dwc_otg_driver_probe,
33132 +       .remove = dwc_otg_driver_remove,
33133 +
33134 +       .driver = {
33135 +                  .name = (char *)dwc_driver_name,
33136 +                  },
33137 +};
33138 +#elif defined(PLATFORM_INTERFACE)
33139 +static struct platform_device_id platform_ids[] = {
33140 +        {
33141 +              .name = "bcm2708_usb",
33142 +              .driver_data = (kernel_ulong_t) 0xdeadbeef,
33143 +        },
33144 +        { /* end: all zeroes */ }
33145 +};
33146 +MODULE_DEVICE_TABLE(platform, platform_ids);
33147 +
33148 +static struct platform_driver dwc_otg_driver = {
33149 +       .driver = {
33150 +               .name = (char *)dwc_driver_name,
33151 +               },
33152 +        .id_table = platform_ids,
33153 +
33154 +       .probe = dwc_otg_driver_probe,
33155 +       .remove = dwc_otg_driver_remove,
33156 +        // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early'
33157 +};
33158 +#endif
33159 +
33160 +/**
33161 + * This function is called when the dwc_otg_driver is installed with the
33162 + * insmod command. It registers the dwc_otg_driver structure with the
33163 + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
33164 + * to be called. In addition, the bus driver will automatically expose
33165 + * attributes defined for the device and driver in the special sysfs file
33166 + * system.
33167 + *
33168 + * @return
33169 + */
33170 +static int __init dwc_otg_driver_init(void)
33171 +{
33172 +       int retval = 0;
33173 +       int error;
33174 +        struct device_driver *drv;
33175 +       printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
33176 +              DWC_DRIVER_VERSION,
33177 +#ifdef LM_INTERFACE
33178 +               "logicmodule");
33179 +       retval = lm_driver_register(&dwc_otg_driver);
33180 +        drv = &dwc_otg_driver.drv;
33181 +#elif defined(PCI_INTERFACE)
33182 +               "pci");
33183 +       retval = pci_register_driver(&dwc_otg_driver);
33184 +        drv = &dwc_otg_driver.driver;
33185 +#elif defined(PLATFORM_INTERFACE)
33186 +               "platform");
33187 +       retval = platform_driver_register(&dwc_otg_driver);
33188 +        drv = &dwc_otg_driver.driver;
33189 +#endif
33190 +       if (retval < 0) {
33191 +               printk(KERN_ERR "%s retval=%d\n", __func__, retval);
33192 +               return retval;
33193 +       }
33194 +
33195 +       error = driver_create_file(drv, &driver_attr_version);
33196 +#ifdef DEBUG
33197 +       error = driver_create_file(drv, &driver_attr_debuglevel);
33198 +#endif
33199 +       return retval;
33200 +}
33201 +
33202 +module_init(dwc_otg_driver_init);
33203 +
33204 +/**
33205 + * This function is called when the driver is removed from the kernel
33206 + * with the rmmod command. The driver unregisters itself with its bus
33207 + * driver.
33208 + *
33209 + */
33210 +static void __exit dwc_otg_driver_cleanup(void)
33211 +{
33212 +       printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
33213 +
33214 +#ifdef LM_INTERFACE
33215 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
33216 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
33217 +       lm_driver_unregister(&dwc_otg_driver);
33218 +#elif defined(PCI_INTERFACE)
33219 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33220 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33221 +       pci_unregister_driver(&dwc_otg_driver);
33222 +#elif defined(PLATFORM_INTERFACE)
33223 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33224 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33225 +       platform_driver_unregister(&dwc_otg_driver);
33226 +#endif
33227 +
33228 +       printk(KERN_INFO "%s module removed\n", dwc_driver_name);
33229 +}
33230 +
33231 +module_exit(dwc_otg_driver_cleanup);
33232 +
33233 +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
33234 +MODULE_AUTHOR("Synopsys Inc.");
33235 +MODULE_LICENSE("GPL");
33236 +
33237 +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
33238 +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
33239 +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
33240 +MODULE_PARM_DESC(opt, "OPT Mode");
33241 +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
33242 +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
33243 +
33244 +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
33245 +                  0444);
33246 +MODULE_PARM_DESC(dma_desc_enable,
33247 +                "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
33248 +
33249 +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
33250 +                  0444);
33251 +MODULE_PARM_DESC(dma_burst_size,
33252 +                "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
33253 +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
33254 +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
33255 +module_param_named(host_support_fs_ls_low_power,
33256 +                  dwc_otg_module_params.host_support_fs_ls_low_power, int,
33257 +                  0444);
33258 +MODULE_PARM_DESC(host_support_fs_ls_low_power,
33259 +                "Support Low Power w/FS or LS 0=Support 1=Don't Support");
33260 +module_param_named(host_ls_low_power_phy_clk,
33261 +                  dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
33262 +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
33263 +                "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
33264 +module_param_named(enable_dynamic_fifo,
33265 +                  dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
33266 +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
33267 +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
33268 +                  0444);
33269 +MODULE_PARM_DESC(data_fifo_size,
33270 +                "Total number of words in the data FIFO memory 32-32768");
33271 +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
33272 +                  int, 0444);
33273 +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33274 +module_param_named(dev_nperio_tx_fifo_size,
33275 +                  dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
33276 +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
33277 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33278 +module_param_named(dev_perio_tx_fifo_size_1,
33279 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
33280 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
33281 +                "Number of words in the periodic Tx FIFO 4-768");
33282 +module_param_named(dev_perio_tx_fifo_size_2,
33283 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
33284 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
33285 +                "Number of words in the periodic Tx FIFO 4-768");
33286 +module_param_named(dev_perio_tx_fifo_size_3,
33287 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
33288 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
33289 +                "Number of words in the periodic Tx FIFO 4-768");
33290 +module_param_named(dev_perio_tx_fifo_size_4,
33291 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
33292 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
33293 +                "Number of words in the periodic Tx FIFO 4-768");
33294 +module_param_named(dev_perio_tx_fifo_size_5,
33295 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
33296 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
33297 +                "Number of words in the periodic Tx FIFO 4-768");
33298 +module_param_named(dev_perio_tx_fifo_size_6,
33299 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
33300 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
33301 +                "Number of words in the periodic Tx FIFO 4-768");
33302 +module_param_named(dev_perio_tx_fifo_size_7,
33303 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
33304 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
33305 +                "Number of words in the periodic Tx FIFO 4-768");
33306 +module_param_named(dev_perio_tx_fifo_size_8,
33307 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
33308 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
33309 +                "Number of words in the periodic Tx FIFO 4-768");
33310 +module_param_named(dev_perio_tx_fifo_size_9,
33311 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
33312 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
33313 +                "Number of words in the periodic Tx FIFO 4-768");
33314 +module_param_named(dev_perio_tx_fifo_size_10,
33315 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
33316 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
33317 +                "Number of words in the periodic Tx FIFO 4-768");
33318 +module_param_named(dev_perio_tx_fifo_size_11,
33319 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
33320 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
33321 +                "Number of words in the periodic Tx FIFO 4-768");
33322 +module_param_named(dev_perio_tx_fifo_size_12,
33323 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
33324 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
33325 +                "Number of words in the periodic Tx FIFO 4-768");
33326 +module_param_named(dev_perio_tx_fifo_size_13,
33327 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
33328 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
33329 +                "Number of words in the periodic Tx FIFO 4-768");
33330 +module_param_named(dev_perio_tx_fifo_size_14,
33331 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
33332 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
33333 +                "Number of words in the periodic Tx FIFO 4-768");
33334 +module_param_named(dev_perio_tx_fifo_size_15,
33335 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
33336 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
33337 +                "Number of words in the periodic Tx FIFO 4-768");
33338 +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
33339 +                  int, 0444);
33340 +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33341 +module_param_named(host_nperio_tx_fifo_size,
33342 +                  dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
33343 +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
33344 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33345 +module_param_named(host_perio_tx_fifo_size,
33346 +                  dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
33347 +MODULE_PARM_DESC(host_perio_tx_fifo_size,
33348 +                "Number of words in the host periodic Tx FIFO 16-32768");
33349 +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
33350 +                  int, 0444);
33351 +/** @todo Set the max to 512K, modify checks */
33352 +MODULE_PARM_DESC(max_transfer_size,
33353 +                "The maximum transfer size supported in bytes 2047-65535");
33354 +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
33355 +                  int, 0444);
33356 +MODULE_PARM_DESC(max_packet_count,
33357 +                "The maximum number of packets in a transfer 15-511");
33358 +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
33359 +                  0444);
33360 +MODULE_PARM_DESC(host_channels,
33361 +                "The number of host channel registers to use 1-16");
33362 +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
33363 +                  0444);
33364 +MODULE_PARM_DESC(dev_endpoints,
33365 +                "The number of endpoints in addition to EP0 available for device mode 1-15");
33366 +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
33367 +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
33368 +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
33369 +                  0444);
33370 +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
33371 +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
33372 +MODULE_PARM_DESC(phy_ulpi_ddr,
33373 +                "ULPI at double or single data rate 0=Single 1=Double");
33374 +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
33375 +                  int, 0444);
33376 +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
33377 +                "ULPI PHY using internal or external vbus 0=Internal");
33378 +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
33379 +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
33380 +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
33381 +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
33382 +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
33383 +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
33384 +module_param_named(debug, g_dbg_lvl, int, 0444);
33385 +MODULE_PARM_DESC(debug, "");
33386 +
33387 +module_param_named(en_multiple_tx_fifo,
33388 +                  dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
33389 +MODULE_PARM_DESC(en_multiple_tx_fifo,
33390 +                "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
33391 +module_param_named(dev_tx_fifo_size_1,
33392 +                  dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
33393 +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
33394 +module_param_named(dev_tx_fifo_size_2,
33395 +                  dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
33396 +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
33397 +module_param_named(dev_tx_fifo_size_3,
33398 +                  dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
33399 +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
33400 +module_param_named(dev_tx_fifo_size_4,
33401 +                  dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
33402 +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
33403 +module_param_named(dev_tx_fifo_size_5,
33404 +                  dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
33405 +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
33406 +module_param_named(dev_tx_fifo_size_6,
33407 +                  dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
33408 +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
33409 +module_param_named(dev_tx_fifo_size_7,
33410 +                  dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
33411 +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
33412 +module_param_named(dev_tx_fifo_size_8,
33413 +                  dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
33414 +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
33415 +module_param_named(dev_tx_fifo_size_9,
33416 +                  dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
33417 +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
33418 +module_param_named(dev_tx_fifo_size_10,
33419 +                  dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
33420 +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
33421 +module_param_named(dev_tx_fifo_size_11,
33422 +                  dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
33423 +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
33424 +module_param_named(dev_tx_fifo_size_12,
33425 +                  dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
33426 +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
33427 +module_param_named(dev_tx_fifo_size_13,
33428 +                  dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
33429 +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
33430 +module_param_named(dev_tx_fifo_size_14,
33431 +                  dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
33432 +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
33433 +module_param_named(dev_tx_fifo_size_15,
33434 +                  dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
33435 +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
33436 +
33437 +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
33438 +MODULE_PARM_DESC(thr_ctl,
33439 +                "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
33440 +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
33441 +                  0444);
33442 +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
33443 +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
33444 +                  0444);
33445 +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
33446 +
33447 +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
33448 +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
33449 +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
33450 +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
33451 +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
33452 +MODULE_PARM_DESC(ic_usb_cap,
33453 +                "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
33454 +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,
33455 +                  0444);
33456 +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
33457 +module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);
33458 +MODULE_PARM_DESC(power_down, "Power Down Mode");
33459 +module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);
33460 +MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
33461 +module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
33462 +MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
33463 +module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
33464 +MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
33465 +module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
33466 +MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
33467 +module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
33468 +MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
33469 +module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
33470 +MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
33471 +module_param(microframe_schedule, bool, 0444);
33472 +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
33473 +
33474 +/** @page "Module Parameters"
33475 + *
33476 + * The following parameters may be specified when starting the module.
33477 + * These parameters define how the DWC_otg controller should be
33478 + * configured. Parameter values are passed to the CIL initialization
33479 + * function dwc_otg_cil_init
33480 + *
33481 + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
33482 + *
33483 +
33484 + <table>
33485 + <tr><td>Parameter Name</td><td>Meaning</td></tr>
33486 +
33487 + <tr>
33488 + <td>otg_cap</td>
33489 + <td>Specifies the OTG capabilities. The driver will automatically detect the
33490 + value for this parameter if none is specified.
33491 + - 0: HNP and SRP capable (default, if available)
33492 + - 1: SRP Only capable
33493 + - 2: No HNP/SRP capable
33494 + </td></tr>
33495 +
33496 + <tr>
33497 + <td>dma_enable</td>
33498 + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
33499 + The driver will automatically detect the value for this parameter if none is
33500 + specified.
33501 + - 0: Slave
33502 + - 1: DMA (default, if available)
33503 + </td></tr>
33504 +
33505 + <tr>
33506 + <td>dma_burst_size</td>
33507 + <td>The DMA Burst size (applicable only for External DMA Mode).
33508 + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
33509 + </td></tr>
33510 +
33511 + <tr>
33512 + <td>speed</td>
33513 + <td>Specifies the maximum speed of operation in host and device mode. The
33514 + actual speed depends on the speed of the attached device and the value of
33515 + phy_type.
33516 + - 0: High Speed (default)
33517 + - 1: Full Speed
33518 + </td></tr>
33519 +
33520 + <tr>
33521 + <td>host_support_fs_ls_low_power</td>
33522 + <td>Specifies whether low power mode is supported when attached to a Full
33523 + Speed or Low Speed device in host mode.
33524 + - 0: Don't support low power mode (default)
33525 + - 1: Support low power mode
33526 + </td></tr>
33527 +
33528 + <tr>
33529 + <td>host_ls_low_power_phy_clk</td>
33530 + <td>Specifies the PHY clock rate in low power mode when connected to a Low
33531 + Speed device in host mode. This parameter is applicable only if
33532 + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
33533 + - 0: 48 MHz (default)
33534 + - 1: 6 MHz
33535 + </td></tr>
33536 +
33537 + <tr>
33538 + <td>enable_dynamic_fifo</td>
33539 + <td> Specifies whether FIFOs may be resized by the driver software.
33540 + - 0: Use cC FIFO size parameters
33541 + - 1: Allow dynamic FIFO sizing (default)
33542 + </td></tr>
33543 +
33544 + <tr>
33545 + <td>data_fifo_size</td>
33546 + <td>Total number of 4-byte words in the data FIFO memory. This memory
33547 + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
33548 + - Values: 32 to 32768 (default 8192)
33549 +
33550 + Note: The total FIFO memory depth in the FPGA configuration is 8192.
33551 + </td></tr>
33552 +
33553 + <tr>
33554 + <td>dev_rx_fifo_size</td>
33555 + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
33556 + FIFO sizing is enabled.
33557 + - Values: 16 to 32768 (default 1064)
33558 + </td></tr>
33559 +
33560 + <tr>
33561 + <td>dev_nperio_tx_fifo_size</td>
33562 + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
33563 + dynamic FIFO sizing is enabled.
33564 + - Values: 16 to 32768 (default 1024)
33565 + </td></tr>
33566 +
33567 + <tr>
33568 + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
33569 + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
33570 + when dynamic FIFO sizing is enabled.
33571 + - Values: 4 to 768 (default 256)
33572 + </td></tr>
33573 +
33574 + <tr>
33575 + <td>host_rx_fifo_size</td>
33576 + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
33577 + sizing is enabled.
33578 + - Values: 16 to 32768 (default 1024)
33579 + </td></tr>
33580 +
33581 + <tr>
33582 + <td>host_nperio_tx_fifo_size</td>
33583 + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
33584 + dynamic FIFO sizing is enabled in the core.
33585 + - Values: 16 to 32768 (default 1024)
33586 + </td></tr>
33587 +
33588 + <tr>
33589 + <td>host_perio_tx_fifo_size</td>
33590 + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
33591 + sizing is enabled.
33592 + - Values: 16 to 32768 (default 1024)
33593 + </td></tr>
33594 +
33595 + <tr>
33596 + <td>max_transfer_size</td>
33597 + <td>The maximum transfer size supported in bytes.
33598 + - Values: 2047 to 65,535 (default 65,535)
33599 + </td></tr>
33600 +
33601 + <tr>
33602 + <td>max_packet_count</td>
33603 + <td>The maximum number of packets in a transfer.
33604 + - Values: 15 to 511 (default 511)
33605 + </td></tr>
33606 +
33607 + <tr>
33608 + <td>host_channels</td>
33609 + <td>The number of host channel registers to use.
33610 + - Values: 1 to 16 (default 12)
33611 +
33612 + Note: The FPGA configuration supports a maximum of 12 host channels.
33613 + </td></tr>
33614 +
33615 + <tr>
33616 + <td>dev_endpoints</td>
33617 + <td>The number of endpoints in addition to EP0 available for device mode
33618 + operations.
33619 + - Values: 1 to 15 (default 6 IN and OUT)
33620 +
33621 + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
33622 + addition to EP0.
33623 + </td></tr>
33624 +
33625 + <tr>
33626 + <td>phy_type</td>
33627 + <td>Specifies the type of PHY interface to use. By default, the driver will
33628 + automatically detect the phy_type.
33629 + - 0: Full Speed
33630 + - 1: UTMI+ (default, if available)
33631 + - 2: ULPI
33632 + </td></tr>
33633 +
33634 + <tr>
33635 + <td>phy_utmi_width</td>
33636 + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
33637 + phy_type of UTMI+. Also, this parameter is applicable only if the
33638 + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
33639 + core has been configured to work at either data path width.
33640 + - Values: 8 or 16 bits (default 16)
33641 + </td></tr>
33642 +
33643 + <tr>
33644 + <td>phy_ulpi_ddr</td>
33645 + <td>Specifies whether the ULPI operates at double or single data rate. This
33646 + parameter is only applicable if phy_type is ULPI.
33647 + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
33648 + - 1: double data rate ULPI interface with 4 bit wide data bus
33649 + </td></tr>
33650 +
33651 + <tr>
33652 + <td>i2c_enable</td>
33653 + <td>Specifies whether to use the I2C interface for full speed PHY. This
33654 + parameter is only applicable if PHY_TYPE is FS.
33655 + - 0: Disabled (default)
33656 + - 1: Enabled
33657 + </td></tr>
33658 +
33659 + <tr>
33660 + <td>ulpi_fs_ls</td>
33661 + <td>Specifies whether to use ULPI FS/LS mode only.
33662 + - 0: Disabled (default)
33663 + - 1: Enabled
33664 + </td></tr>
33665 +
33666 + <tr>
33667 + <td>ts_dline</td>
33668 + <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.
33669 + - 0: Disabled (default)
33670 + - 1: Enabled
33671 + </td></tr>
33672 +
33673 + <tr>
33674 + <td>en_multiple_tx_fifo</td>
33675 + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
33676 + The driver will automatically detect the value for this parameter if none is
33677 + specified.
33678 + - 0: Disabled
33679 + - 1: Enabled (default, if available)
33680 + </td></tr>
33681 +
33682 + <tr>
33683 + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
33684 + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
33685 + when dynamic FIFO sizing is enabled.
33686 + - Values: 4 to 768 (default 256)
33687 + </td></tr>
33688 +
33689 + <tr>
33690 + <td>tx_thr_length</td>
33691 + <td>Transmit Threshold length in 32 bit double words
33692 + - Values: 8 to 128 (default 64)
33693 + </td></tr>
33694 +
33695 + <tr>
33696 + <td>rx_thr_length</td>
33697 + <td>Receive Threshold length in 32 bit double words
33698 + - Values: 8 to 128 (default 64)
33699 + </td></tr>
33700 +
33701 +<tr>
33702 + <td>thr_ctl</td>
33703 + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
33704 + this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
33705 + Rx transfers accordingly.
33706 + The driver will automatically detect the value for this parameter if none is
33707 + specified.
33708 + - Values: 0 to 7 (default 0)
33709 + Bit values indicate:
33710 + - 0: Thresholding disabled
33711 + - 1: Thresholding enabled
33712 + </td></tr>
33713 +
33714 +<tr>
33715 + <td>dma_desc_enable</td>
33716 + <td>Specifies whether to enable Descriptor DMA mode.
33717 + The driver will automatically detect the value for this parameter if none is
33718 + specified.
33719 + - 0: Descriptor DMA disabled
33720 + - 1: Descriptor DMA (default, if available)
33721 + </td></tr>
33722 +
33723 +<tr>
33724 + <td>mpi_enable</td>
33725 + <td>Specifies whether to enable MPI enhancement mode.
33726 + The driver will automatically detect the value for this parameter if none is
33727 + specified.
33728 + - 0: MPI disabled (default)
33729 + - 1: MPI enable
33730 + </td></tr>
33731 +
33732 +<tr>
33733 + <td>pti_enable</td>
33734 + <td>Specifies whether to enable PTI enhancement support.
33735 + The driver will automatically detect the value for this parameter if none is
33736 + specified.
33737 + - 0: PTI disabled (default)
33738 + - 1: PTI enable
33739 + </td></tr>
33740 +
33741 +<tr>
33742 + <td>lpm_enable</td>
33743 + <td>Specifies whether to enable LPM support.
33744 + The driver will automatically detect the value for this parameter if none is
33745 + specified.
33746 + - 0: LPM disabled
33747 + - 1: LPM enable (default, if available)
33748 + </td></tr>
33749 +
33750 +<tr>
33751 + <td>ic_usb_cap</td>
33752 + <td>Specifies whether to enable IC_USB capability.
33753 + The driver will automatically detect the value for this parameter if none is
33754 + specified.
33755 + - 0: IC_USB disabled (default, if available)
33756 + - 1: IC_USB enable
33757 + </td></tr>
33758 +
33759 +<tr>
33760 + <td>ahb_thr_ratio</td>
33761 + <td>Specifies AHB Threshold ratio.
33762 + - Values: 0 to 3 (default 0)
33763 + </td></tr>
33764 +
33765 +<tr>
33766 + <td>power_down</td>
33767 + <td>Specifies Power Down(Hibernation) Mode.
33768 + The driver will automatically detect the value for this parameter if none is
33769 + specified.
33770 + - 0: Power Down disabled (default)
33771 + - 2: Power Down enabled
33772 + </td></tr>
33773 +
33774 + <tr>
33775 + <td>reload_ctl</td>
33776 + <td>Specifies whether dynamic reloading of the HFIR register is allowed during
33777 + run time. The driver will automatically detect the value for this parameter if
33778 + none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0
33779 + the core might misbehave.
33780 + - 0: Reload Control disabled (default)
33781 + - 1: Reload Control enabled
33782 + </td></tr>
33783 +
33784 + <tr>
33785 + <td>dev_out_nak</td>
33786 + <td>Specifies whether  Device OUT NAK enhancement enabled or no.
33787 + The driver will automatically detect the value for this parameter if
33788 + none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33789 + - 0: The core does not set NAK after Bulk OUT transfer complete (default)
33790 + - 1: The core sets NAK after Bulk OUT transfer complete
33791 + </td></tr>
33792 +
33793 + <tr>
33794 + <td>cont_on_bna</td>
33795 + <td>Specifies whether Enable Continue on BNA enabled or no.
33796 + After receiving BNA interrupt the core disables the endpoint,when the
33797 + endpoint is re-enabled by the application the
33798 + - 0: Core starts processing from the DOEPDMA descriptor (default)
33799 + - 1: Core starts processing from the descriptor which received the BNA.
33800 + This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33801 + </td></tr>
33802 +
33803 + <tr>
33804 + <td>ahb_single</td>
33805 + <td>This bit when programmed supports SINGLE transfers for remainder data
33806 + in a transfer for DMA mode of operation.
33807 + - 0: The remainder data will be sent using INCR burst size (default)
33808 + - 1: The remainder data will be sent using SINGLE burst size.
33809 + </td></tr>
33810 +
33811 +<tr>
33812 + <td>adp_enable</td>
33813 + <td>Specifies whether ADP feature is enabled.
33814 + The driver will automatically detect the value for this parameter if none is
33815 + specified.
33816 + - 0: ADP feature disabled (default)
33817 + - 1: ADP feature enabled
33818 + </td></tr>
33819 +
33820 +  <tr>
33821 + <td>otg_ver</td>
33822 + <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
33823 + USB OTG device.
33824 + - 0: OTG 2.0 support disabled (default)
33825 + - 1: OTG 2.0 support enabled
33826 + </td></tr>
33827 +
33828 +*/
33829 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33830 new file mode 100644
33831 index 0000000..6a8be63
33832 --- /dev/null
33833 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33834 @@ -0,0 +1,86 @@
33835 +/* ==========================================================================
33836 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
33837 + * $Revision: #19 $
33838 + * $Date: 2010/11/15 $
33839 + * $Change: 1627671 $
33840 + *
33841 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33842 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33843 + * otherwise expressly agreed to in writing between Synopsys and you.
33844 + *
33845 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33846 + * any End User Software License Agreement or Agreement for Licensed Product
33847 + * with Synopsys or any supplement thereto. You are permitted to use and
33848 + * redistribute this Software in source and binary forms, with or without
33849 + * modification, provided that redistributions of source code must retain this
33850 + * notice. You may not view, use, disclose, copy or distribute this file or
33851 + * any information contained herein except pursuant to this license grant from
33852 + * Synopsys. If you do not agree with this notice, including the disclaimer
33853 + * below, then you are not authorized to use the Software.
33854 + *
33855 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33856 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33857 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33858 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33859 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33860 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33861 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33862 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33863 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33864 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33865 + * DAMAGE.
33866 + * ========================================================================== */
33867 +
33868 +#ifndef __DWC_OTG_DRIVER_H__
33869 +#define __DWC_OTG_DRIVER_H__
33870 +
33871 +/** @file
33872 + * This file contains the interface to the Linux driver.
33873 + */
33874 +#include "dwc_otg_os_dep.h"
33875 +#include "dwc_otg_core_if.h"
33876 +
33877 +/* Type declarations */
33878 +struct dwc_otg_pcd;
33879 +struct dwc_otg_hcd;
33880 +
33881 +/**
33882 + * This structure is a wrapper that encapsulates the driver components used to
33883 + * manage a single DWC_otg controller.
33884 + */
33885 +typedef struct dwc_otg_device {
33886 +       /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE
33887 +        * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD
33888 +        * require this. */
33889 +       struct os_dependent os_dep;
33890 +
33891 +       /** Pointer to the core interface structure. */
33892 +       dwc_otg_core_if_t *core_if;
33893 +
33894 +       /** Pointer to the PCD structure. */
33895 +       struct dwc_otg_pcd *pcd;
33896 +
33897 +       /** Pointer to the HCD structure. */
33898 +       struct dwc_otg_hcd *hcd;
33899 +
33900 +       /** Flag to indicate whether the common IRQ handler is installed. */
33901 +       uint8_t common_irq_installed;
33902 +
33903 +} dwc_otg_device_t;
33904 +
33905 +/*We must clear S3C24XX_EINTPEND external interrupt register
33906 + * because after clearing in this register trigerred IRQ from
33907 + * H/W core in kernel interrupt can be occured again before OTG
33908 + * handlers clear all IRQ sources of Core registers because of
33909 + * timing latencies and Low Level IRQ Type.
33910 + */
33911 +#ifdef CONFIG_MACH_IPMATE
33912 +#define  S3C2410X_CLEAR_EINTPEND()   \
33913 +do { \
33914 +       __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
33915 +} while (0)
33916 +#else
33917 +#define  S3C2410X_CLEAR_EINTPEND()   do { } while (0)
33918 +#endif
33919 +
33920 +#endif
33921 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33922 new file mode 100644
33923 index 0000000..1e89549
33924 --- /dev/null
33925 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33926 @@ -0,0 +1,3479 @@
33927 +
33928 +/* ==========================================================================
33929 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
33930 + * $Revision: #104 $
33931 + * $Date: 2011/10/24 $
33932 + * $Change: 1871159 $
33933 + *
33934 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33935 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33936 + * otherwise expressly agreed to in writing between Synopsys and you.
33937 + *
33938 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33939 + * any End User Software License Agreement or Agreement for Licensed Product
33940 + * with Synopsys or any supplement thereto. You are permitted to use and
33941 + * redistribute this Software in source and binary forms, with or without
33942 + * modification, provided that redistributions of source code must retain this
33943 + * notice. You may not view, use, disclose, copy or distribute this file or
33944 + * any information contained herein except pursuant to this license grant from
33945 + * Synopsys. If you do not agree with this notice, including the disclaimer
33946 + * below, then you are not authorized to use the Software.
33947 + *
33948 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33949 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33950 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33951 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33952 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33953 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33954 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33955 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33956 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33957 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33958 + * DAMAGE.
33959 + * ========================================================================== */
33960 +#ifndef DWC_DEVICE_ONLY
33961 +
33962 +/** @file
33963 + * This file implements HCD Core. All code in this file is portable and doesn't
33964 + * use any OS specific functions.
33965 + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
33966 + * header file.
33967 + */
33968 +
33969 +#include "dwc_otg_hcd.h"
33970 +#include "dwc_otg_regs.h"
33971 +
33972 +extern bool microframe_schedule;
33973 +
33974 +//#define DEBUG_HOST_CHANNELS
33975 +#ifdef DEBUG_HOST_CHANNELS
33976 +static int last_sel_trans_num_per_scheduled = 0;
33977 +static int last_sel_trans_num_nonper_scheduled = 0;
33978 +static int last_sel_trans_num_avail_hc_at_start = 0;
33979 +static int last_sel_trans_num_avail_hc_at_end = 0;
33980 +#endif /* DEBUG_HOST_CHANNELS */
33981 +
33982 +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
33983 +{
33984 +       return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
33985 +}
33986 +
33987 +/**
33988 + * Connection timeout function.  An OTG host is required to display a
33989 + * message if the device does not connect within 10 seconds.
33990 + */
33991 +void dwc_otg_hcd_connect_timeout(void *ptr)
33992 +{
33993 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
33994 +       DWC_PRINTF("Connect Timeout\n");
33995 +       __DWC_ERROR("Device Not Connected/Responding\n");
33996 +}
33997 +
33998 +#if defined(DEBUG)
33999 +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34000 +{
34001 +       if (qh->channel != NULL) {
34002 +               dwc_hc_t *hc = qh->channel;
34003 +               dwc_list_link_t *item;
34004 +               dwc_otg_qh_t *qh_item;
34005 +               int num_channels = hcd->core_if->core_params->host_channels;
34006 +               int i;
34007 +
34008 +               dwc_otg_hc_regs_t *hc_regs;
34009 +               hcchar_data_t hcchar;
34010 +               hcsplt_data_t hcsplt;
34011 +               hctsiz_data_t hctsiz;
34012 +               uint32_t hcdma;
34013 +
34014 +               hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
34015 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34016 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
34017 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
34018 +               hcdma = DWC_READ_REG32(&hc_regs->hcdma);
34019 +
34020 +               DWC_PRINTF("  Assigned to channel %p:\n", hc);
34021 +               DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
34022 +                          hcsplt.d32);
34023 +               DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
34024 +                          hcdma);
34025 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
34026 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
34027 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
34028 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
34029 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
34030 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
34031 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
34032 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
34033 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
34034 +               DWC_PRINTF("    qh: %p\n", hc->qh);
34035 +               DWC_PRINTF("  NP inactive sched:\n");
34036 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
34037 +                       qh_item =
34038 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34039 +                       DWC_PRINTF("    %p\n", qh_item);
34040 +               }
34041 +               DWC_PRINTF("  NP active sched:\n");
34042 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
34043 +                       qh_item =
34044 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34045 +                       DWC_PRINTF("    %p\n", qh_item);
34046 +               }
34047 +               DWC_PRINTF("  Channels: \n");
34048 +               for (i = 0; i < num_channels; i++) {
34049 +                       dwc_hc_t *hc = hcd->hc_ptr_array[i];
34050 +                       DWC_PRINTF("    %2d: %p\n", i, hc);
34051 +               }
34052 +       }
34053 +}
34054 +#else
34055 +#define dump_channel_info(hcd, qh)
34056 +#endif /* DEBUG */
34057 +
34058 +/**
34059 + * Work queue function for starting the HCD when A-Cable is connected.
34060 + * The hcd_start() must be called in a process context.
34061 + */
34062 +static void hcd_start_func(void *_vp)
34063 +{
34064 +       dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
34065 +
34066 +       DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
34067 +       if (hcd) {
34068 +               hcd->fops->start(hcd);
34069 +       }
34070 +}
34071 +
34072 +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
34073 +{
34074 +#ifdef DEBUG
34075 +       int i;
34076 +       int num_channels = hcd->core_if->core_params->host_channels;
34077 +       for (i = 0; i < num_channels; i++) {
34078 +               DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
34079 +       }
34080 +#endif
34081 +}
34082 +
34083 +static void del_timers(dwc_otg_hcd_t * hcd)
34084 +{
34085 +       del_xfer_timers(hcd);
34086 +       DWC_TIMER_CANCEL(hcd->conn_timer);
34087 +}
34088 +
34089 +/**
34090 + * Processes all the URBs in a single list of QHs. Completes them with
34091 + * -ETIMEDOUT and frees the QTD.
34092 + */
34093 +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34094 +{
34095 +       dwc_list_link_t *qh_item;
34096 +       dwc_otg_qh_t *qh;
34097 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
34098 +
34099 +       DWC_LIST_FOREACH(qh_item, qh_list) {
34100 +               qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
34101 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
34102 +                                        &qh->qtd_list, qtd_list_entry) {
34103 +                       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34104 +                       if (qtd->urb != NULL) {
34105 +                               hcd->fops->complete(hcd, qtd->urb->priv,
34106 +                                                   qtd->urb, -DWC_E_TIMEOUT);
34107 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
34108 +                       }
34109 +
34110 +               }
34111 +       }
34112 +}
34113 +
34114 +/**
34115 + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
34116 + * and periodic schedules. The QTD associated with each URB is removed from
34117 + * the schedule and freed. This function may be called when a disconnect is
34118 + * detected or when the HCD is being stopped.
34119 + */
34120 +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
34121 +{
34122 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
34123 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
34124 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
34125 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
34126 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
34127 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
34128 +}
34129 +
34130 +/**
34131 + * Start the connection timer.  An OTG host is required to display a
34132 + * message if the device does not connect within 10 seconds.  The
34133 + * timer is deleted if a port connect interrupt occurs before the
34134 + * timer expires.
34135 + */
34136 +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
34137 +{
34138 +       DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
34139 +}
34140 +
34141 +/**
34142 + * HCD Callback function for disconnect of the HCD.
34143 + *
34144 + * @param p void pointer to the <code>struct usb_hcd</code>
34145 + */
34146 +static int32_t dwc_otg_hcd_session_start_cb(void *p)
34147 +{
34148 +       dwc_otg_hcd_t *dwc_otg_hcd;
34149 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34150 +       dwc_otg_hcd = p;
34151 +       dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
34152 +       return 1;
34153 +}
34154 +
34155 +/**
34156 + * HCD Callback function for starting the HCD when A-Cable is
34157 + * connected.
34158 + *
34159 + * @param p void pointer to the <code>struct usb_hcd</code>
34160 + */
34161 +static int32_t dwc_otg_hcd_start_cb(void *p)
34162 +{
34163 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34164 +       dwc_otg_core_if_t *core_if;
34165 +       hprt0_data_t hprt0;
34166 +
34167 +       core_if = dwc_otg_hcd->core_if;
34168 +
34169 +       if (core_if->op_state == B_HOST) {
34170 +               /*
34171 +                * Reset the port.  During a HNP mode switch the reset
34172 +                * needs to occur within 1ms and have a duration of at
34173 +                * least 50ms.
34174 +                */
34175 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
34176 +               hprt0.b.prtrst = 1;
34177 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34178 +       }
34179 +       DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
34180 +                                  hcd_start_func, dwc_otg_hcd, 50,
34181 +                                  "start hcd");
34182 +
34183 +       return 1;
34184 +}
34185 +
34186 +/**
34187 + * HCD Callback function for disconnect of the HCD.
34188 + *
34189 + * @param p void pointer to the <code>struct usb_hcd</code>
34190 + */
34191 +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
34192 +{
34193 +       gintsts_data_t intr;
34194 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34195 +
34196 +       /*
34197 +        * Set status flags for the hub driver.
34198 +        */
34199 +       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
34200 +       dwc_otg_hcd->flags.b.port_connect_status = 0;
34201 +
34202 +       /*
34203 +        * Shutdown any transfers in process by clearing the Tx FIFO Empty
34204 +        * interrupt mask and status bits and disabling subsequent host
34205 +        * channel interrupts.
34206 +        */
34207 +       intr.d32 = 0;
34208 +       intr.b.nptxfempty = 1;
34209 +       intr.b.ptxfempty = 1;
34210 +       intr.b.hcintr = 1;
34211 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
34212 +                        intr.d32, 0);
34213 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
34214 +                        intr.d32, 0);
34215 +
34216 +       del_timers(dwc_otg_hcd);
34217 +
34218 +       /*
34219 +        * Turn off the vbus power only if the core has transitioned to device
34220 +        * mode. If still in host mode, need to keep power on to detect a
34221 +        * reconnection.
34222 +        */
34223 +       if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
34224 +               if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
34225 +                       hprt0_data_t hprt0 = {.d32 = 0 };
34226 +                       DWC_PRINTF("Disconnect: PortPower off\n");
34227 +                       hprt0.b.prtpwr = 0;
34228 +                       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
34229 +                                       hprt0.d32);
34230 +               }
34231 +
34232 +               dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
34233 +       }
34234 +
34235 +       /* Respond with an error status to all URBs in the schedule. */
34236 +       kill_all_urbs(dwc_otg_hcd);
34237 +
34238 +       if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
34239 +               /* Clean up any host channels that were in use. */
34240 +               int num_channels;
34241 +               int i;
34242 +               dwc_hc_t *channel;
34243 +               dwc_otg_hc_regs_t *hc_regs;
34244 +               hcchar_data_t hcchar;
34245 +
34246 +               num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
34247 +
34248 +               if (!dwc_otg_hcd->core_if->dma_enable) {
34249 +                       /* Flush out any channel requests in slave mode. */
34250 +                       for (i = 0; i < num_channels; i++) {
34251 +                               channel = dwc_otg_hcd->hc_ptr_array[i];
34252 +                               if (DWC_CIRCLEQ_EMPTY_ENTRY
34253 +                                   (channel, hc_list_entry)) {
34254 +                                       hc_regs =
34255 +                                           dwc_otg_hcd->core_if->
34256 +                                           host_if->hc_regs[i];
34257 +                                       hcchar.d32 =
34258 +                                           DWC_READ_REG32(&hc_regs->hcchar);
34259 +                                       if (hcchar.b.chen) {
34260 +                                               hcchar.b.chen = 0;
34261 +                                               hcchar.b.chdis = 1;
34262 +                                               hcchar.b.epdir = 0;
34263 +                                               DWC_WRITE_REG32
34264 +                                                   (&hc_regs->hcchar,
34265 +                                                    hcchar.d32);
34266 +                                       }
34267 +                               }
34268 +                       }
34269 +               }
34270 +
34271 +               for (i = 0; i < num_channels; i++) {
34272 +                       channel = dwc_otg_hcd->hc_ptr_array[i];
34273 +                       if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
34274 +                               hc_regs =
34275 +                                   dwc_otg_hcd->core_if->host_if->hc_regs[i];
34276 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34277 +                               if (hcchar.b.chen) {
34278 +                                       /* Halt the channel. */
34279 +                                       hcchar.b.chdis = 1;
34280 +                                       DWC_WRITE_REG32(&hc_regs->hcchar,
34281 +                                                       hcchar.d32);
34282 +                               }
34283 +
34284 +                               dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
34285 +                                                  channel);
34286 +                               DWC_CIRCLEQ_INSERT_TAIL
34287 +                                   (&dwc_otg_hcd->free_hc_list, channel,
34288 +                                    hc_list_entry);
34289 +                               /*
34290 +                                * Added for Descriptor DMA to prevent channel double cleanup
34291 +                                * in release_channel_ddma(). Which called from ep_disable
34292 +                                * when device disconnect.
34293 +                                */
34294 +                               channel->qh = NULL;
34295 +                       }
34296 +               }
34297 +       }
34298 +
34299 +       if (dwc_otg_hcd->fops->disconnect) {
34300 +               dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
34301 +       }
34302 +
34303 +       return 1;
34304 +}
34305 +
34306 +/**
34307 + * HCD Callback function for stopping the HCD.
34308 + *
34309 + * @param p void pointer to the <code>struct usb_hcd</code>
34310 + */
34311 +static int32_t dwc_otg_hcd_stop_cb(void *p)
34312 +{
34313 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34314 +
34315 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34316 +       dwc_otg_hcd_stop(dwc_otg_hcd);
34317 +       return 1;
34318 +}
34319 +
34320 +#ifdef CONFIG_USB_DWC_OTG_LPM
34321 +/**
34322 + * HCD Callback function for sleep of HCD.
34323 + *
34324 + * @param p void pointer to the <code>struct usb_hcd</code>
34325 + */
34326 +static int dwc_otg_hcd_sleep_cb(void *p)
34327 +{
34328 +       dwc_otg_hcd_t *hcd = p;
34329 +
34330 +       dwc_otg_hcd_free_hc_from_lpm(hcd);
34331 +
34332 +       return 0;
34333 +}
34334 +#endif
34335 +
34336 +/**
34337 + * HCD Callback function for Remote Wakeup.
34338 + *
34339 + * @param p void pointer to the <code>struct usb_hcd</code>
34340 + */
34341 +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
34342 +{
34343 +       dwc_otg_hcd_t *hcd = p;
34344 +
34345 +       if (hcd->core_if->lx_state == DWC_OTG_L2) {
34346 +               hcd->flags.b.port_suspend_change = 1;
34347 +       }
34348 +#ifdef CONFIG_USB_DWC_OTG_LPM
34349 +       else {
34350 +               hcd->flags.b.port_l1_change = 1;
34351 +       }
34352 +#endif
34353 +       return 0;
34354 +}
34355 +
34356 +/**
34357 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
34358 + * stopped.
34359 + */
34360 +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
34361 +{
34362 +       hprt0_data_t hprt0 = {.d32 = 0 };
34363 +
34364 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
34365 +
34366 +       /*
34367 +        * The root hub should be disconnected before this function is called.
34368 +        * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
34369 +        * and the QH lists (via ..._hcd_endpoint_disable).
34370 +        */
34371 +
34372 +       /* Turn off all host-specific interrupts. */
34373 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34374 +
34375 +       /* Turn off the vbus power */
34376 +       DWC_PRINTF("PortPower off\n");
34377 +       hprt0.b.prtpwr = 0;
34378 +       DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
34379 +       dwc_mdelay(1);
34380 +}
34381 +
34382 +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
34383 +                           dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
34384 +                           int atomic_alloc)
34385 +{
34386 +       dwc_irqflags_t flags;
34387 +       int retval = 0;
34388 +       dwc_otg_qtd_t *qtd;
34389 +       gintmsk_data_t intr_mask = {.d32 = 0 };
34390 +
34391 +#ifdef DEBUG /* integrity checks (Broadcom) */
34392 +       if (NULL == hcd->core_if) {
34393 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
34394 +               /* No longer connected. */
34395 +               return -DWC_E_INVALID;
34396 +       }
34397 +#endif
34398 +       if (!hcd->flags.b.port_connect_status) {
34399 +               /* No longer connected. */
34400 +               DWC_ERROR("Not connected\n");
34401 +               return -DWC_E_NO_DEVICE;
34402 +       }
34403 +
34404 +       qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
34405 +       if (qtd == NULL) {
34406 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
34407 +               return -DWC_E_NO_MEMORY;
34408 +       }
34409 +#ifdef DEBUG /* integrity checks (Broadcom) */
34410 +       if (qtd->urb == NULL) {
34411 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
34412 +               return -DWC_E_NO_MEMORY;
34413 +       }
34414 +       if (qtd->urb->priv == NULL) {
34415 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
34416 +               return -DWC_E_NO_MEMORY;
34417 +       }
34418 +#endif
34419 +       retval =
34420 +           dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
34421 +            // creates a new queue in ep_handle if it doesn't exist already
34422 +       if (retval < 0) {
34423 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
34424 +                         "Error status %d\n", retval);
34425 +               dwc_otg_hcd_qtd_free(qtd);
34426 +       } else {
34427 +               qtd->qh = *ep_handle;
34428 +       }
34429 +       intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
34430 +       if (!intr_mask.b.sofintr && retval == 0) {
34431 +               dwc_otg_transaction_type_e tr_type;
34432 +               if ((qtd->qh->ep_type == UE_BULK)
34433 +                   && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
34434 +                       /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
34435 +                       return 0;
34436 +               }
34437 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34438 +               tr_type = dwc_otg_hcd_select_transactions(hcd);
34439 +               if (tr_type != DWC_OTG_TRANSACTION_NONE) {
34440 +                       dwc_otg_hcd_queue_transactions(hcd, tr_type);
34441 +               }
34442 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34443 +       }
34444 +
34445 +       return retval;
34446 +}
34447 +
34448 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
34449 +                           dwc_otg_hcd_urb_t * dwc_otg_urb)
34450 +{
34451 +       dwc_otg_qh_t *qh;
34452 +       dwc_otg_qtd_t *urb_qtd;
34453 +
34454 +#ifdef DEBUG /* integrity checks (Broadcom) */
34455 +
34456 +       if (hcd == NULL) {
34457 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
34458 +               return -DWC_E_INVALID;
34459 +       }
34460 +       if (dwc_otg_urb == NULL) {
34461 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
34462 +               return -DWC_E_INVALID;
34463 +       }
34464 +       if (dwc_otg_urb->qtd == NULL) {
34465 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
34466 +               return -DWC_E_INVALID;
34467 +       }
34468 +       urb_qtd = dwc_otg_urb->qtd;
34469 +       if (urb_qtd->qh == NULL) {
34470 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
34471 +               return -DWC_E_INVALID;
34472 +       }
34473 +#else
34474 +       urb_qtd = dwc_otg_urb->qtd;
34475 +#endif
34476 +       qh = urb_qtd->qh;
34477 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
34478 +               if (urb_qtd->in_process) {
34479 +                       dump_channel_info(hcd, qh);
34480 +               }
34481 +       }
34482 +#ifdef DEBUG /* integrity checks (Broadcom) */
34483 +       if (hcd->core_if == NULL) {
34484 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
34485 +               return -DWC_E_INVALID;
34486 +       }
34487 +#endif
34488 +       if (urb_qtd->in_process && qh->channel) {
34489 +               /* The QTD is in process (it has been assigned to a channel). */
34490 +               if (hcd->flags.b.port_connect_status) {
34491 +                       /*
34492 +                        * If still connected (i.e. in host mode), halt the
34493 +                        * channel so it can be used for other transfers. If
34494 +                        * no longer connected, the host registers can't be
34495 +                        * written to halt the channel since the core is in
34496 +                        * device mode.
34497 +                        */
34498 +                       dwc_otg_hc_halt(hcd->core_if, qh->channel,
34499 +                                       DWC_OTG_HC_XFER_URB_DEQUEUE);
34500 +               }
34501 +       }
34502 +
34503 +       /*
34504 +        * Free the QTD and clean up the associated QH. Leave the QH in the
34505 +        * schedule if it has any remaining QTDs.
34506 +        */
34507 +
34508 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
34509 +                    "delete %sQueue handler\n",
34510 +                    hcd->core_if->dma_desc_enable?"DMA ":"");
34511 +       if (!hcd->core_if->dma_desc_enable) {
34512 +               uint8_t b = urb_qtd->in_process;
34513 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34514 +               if (b) {
34515 +                       dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
34516 +                       qh->channel = NULL;
34517 +               } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
34518 +                       dwc_otg_hcd_qh_remove(hcd, qh);
34519 +               }
34520 +       } else {
34521 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34522 +       }
34523 +       return 0;
34524 +}
34525 +
34526 +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
34527 +                                int retry)
34528 +{
34529 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34530 +       int retval = 0;
34531 +       dwc_irqflags_t flags;
34532 +
34533 +       if (retry < 0) {
34534 +               retval = -DWC_E_INVALID;
34535 +               goto done;
34536 +       }
34537 +
34538 +       if (!qh) {
34539 +               retval = -DWC_E_INVALID;
34540 +               goto done;
34541 +       }
34542 +
34543 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34544 +
34545 +       while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
34546 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34547 +               retry--;
34548 +               dwc_msleep(5);
34549 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34550 +       }
34551 +
34552 +       dwc_otg_hcd_qh_remove(hcd, qh);
34553 +
34554 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34555 +       /*
34556 +        * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
34557 +        * and qh_free to prevent stack dump on DWC_DMA_FREE() with
34558 +        * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
34559 +        * and dwc_otg_hcd_frame_list_alloc().
34560 +        */
34561 +       dwc_otg_hcd_qh_free(hcd, qh);
34562 +
34563 +done:
34564 +       return retval;
34565 +}
34566 +
34567 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
34568 +int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
34569 +{
34570 +       int retval = 0;
34571 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34572 +       if (!qh)
34573 +               return -DWC_E_INVALID;
34574 +
34575 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
34576 +       return retval;
34577 +}
34578 +#endif
34579 +
34580 +/**
34581 + * HCD Callback structure for handling mode switching.
34582 + */
34583 +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
34584 +       .start = dwc_otg_hcd_start_cb,
34585 +       .stop = dwc_otg_hcd_stop_cb,
34586 +       .disconnect = dwc_otg_hcd_disconnect_cb,
34587 +       .session_start = dwc_otg_hcd_session_start_cb,
34588 +       .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
34589 +#ifdef CONFIG_USB_DWC_OTG_LPM
34590 +       .sleep = dwc_otg_hcd_sleep_cb,
34591 +#endif
34592 +       .p = 0,
34593 +};
34594 +
34595 +/**
34596 + * Reset tasklet function
34597 + */
34598 +static void reset_tasklet_func(void *data)
34599 +{
34600 +       dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
34601 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
34602 +       hprt0_data_t hprt0;
34603 +
34604 +       DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
34605 +
34606 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
34607 +       hprt0.b.prtrst = 1;
34608 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34609 +       dwc_mdelay(60);
34610 +
34611 +       hprt0.b.prtrst = 0;
34612 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34613 +       dwc_otg_hcd->flags.b.port_reset_change = 1;
34614 +}
34615 +
34616 +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34617 +{
34618 +       dwc_list_link_t *item;
34619 +       dwc_otg_qh_t *qh;
34620 +       dwc_irqflags_t flags;
34621 +
34622 +       if (!qh_list->next) {
34623 +               /* The list hasn't been initialized yet. */
34624 +               return;
34625 +       }
34626 +       /*
34627 +        * Hold spinlock here. Not needed in that case if bellow
34628 +        * function is being called from ISR
34629 +        */
34630 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34631 +       /* Ensure there are no QTDs or URBs left. */
34632 +       kill_urbs_in_qh_list(hcd, qh_list);
34633 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34634 +
34635 +       DWC_LIST_FOREACH(item, qh_list) {
34636 +               qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34637 +               dwc_otg_hcd_qh_remove_and_free(hcd, qh);
34638 +       }
34639 +}
34640 +
34641 +/**
34642 + * Exit from Hibernation if Host did not detect SRP from connected SRP capable
34643 + * Device during SRP time by host power up.
34644 + */
34645 +void dwc_otg_hcd_power_up(void *ptr)
34646 +{
34647 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
34648 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
34649 +
34650 +       DWC_PRINTF("%s called\n", __FUNCTION__);
34651 +
34652 +       if (!core_if->hibernation_suspend) {
34653 +               DWC_PRINTF("Already exited from Hibernation\n");
34654 +               return;
34655 +       }
34656 +
34657 +       /* Switch on the voltage to the core */
34658 +       gpwrdn.b.pwrdnswtch = 1;
34659 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34660 +       dwc_udelay(10);
34661 +
34662 +       /* Reset the core */
34663 +       gpwrdn.d32 = 0;
34664 +       gpwrdn.b.pwrdnrstn = 1;
34665 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34666 +       dwc_udelay(10);
34667 +
34668 +       /* Disable power clamps */
34669 +       gpwrdn.d32 = 0;
34670 +       gpwrdn.b.pwrdnclmp = 1;
34671 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34672 +
34673 +       /* Remove reset the core signal */
34674 +       gpwrdn.d32 = 0;
34675 +       gpwrdn.b.pwrdnrstn = 1;
34676 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
34677 +       dwc_udelay(10);
34678 +
34679 +       /* Disable PMU interrupt */
34680 +       gpwrdn.d32 = 0;
34681 +       gpwrdn.b.pmuintsel = 1;
34682 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34683 +
34684 +       core_if->hibernation_suspend = 0;
34685 +
34686 +       /* Disable PMU */
34687 +       gpwrdn.d32 = 0;
34688 +       gpwrdn.b.pmuactv = 1;
34689 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34690 +       dwc_udelay(10);
34691 +
34692 +       /* Enable VBUS */
34693 +       gpwrdn.d32 = 0;
34694 +       gpwrdn.b.dis_vbus = 1;
34695 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34696 +
34697 +       core_if->op_state = A_HOST;
34698 +       dwc_otg_core_init(core_if);
34699 +       dwc_otg_enable_global_interrupts(core_if);
34700 +       cil_hcd_start(core_if);
34701 +}
34702 +
34703 +/**
34704 + * Frees secondary storage associated with the dwc_otg_hcd structure contained
34705 + * in the struct usb_hcd field.
34706 + */
34707 +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
34708 +{
34709 +       int i;
34710 +
34711 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
34712 +
34713 +       del_timers(dwc_otg_hcd);
34714 +
34715 +       /* Free memory for QH/QTD lists */
34716 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
34717 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
34718 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
34719 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
34720 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
34721 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
34722 +
34723 +       /* Free memory for the host channels. */
34724 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
34725 +               dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
34726 +
34727 +#ifdef DEBUG
34728 +               if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
34729 +                       DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
34730 +               }
34731 +#endif
34732 +               if (hc != NULL) {
34733 +                       DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
34734 +                                   i, hc);
34735 +                       DWC_FREE(hc);
34736 +               }
34737 +       }
34738 +
34739 +       if (dwc_otg_hcd->core_if->dma_enable) {
34740 +               if (dwc_otg_hcd->status_buf_dma) {
34741 +                       DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
34742 +                                    dwc_otg_hcd->status_buf,
34743 +                                    dwc_otg_hcd->status_buf_dma);
34744 +               }
34745 +       } else if (dwc_otg_hcd->status_buf != NULL) {
34746 +               DWC_FREE(dwc_otg_hcd->status_buf);
34747 +       }
34748 +       DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
34749 +       /* Set core_if's lock pointer to NULL */
34750 +       dwc_otg_hcd->core_if->lock = NULL;
34751 +
34752 +       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
34753 +       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
34754 +
34755 +#ifdef DWC_DEV_SRPCAP
34756 +       if (dwc_otg_hcd->core_if->power_down == 2 &&
34757 +           dwc_otg_hcd->core_if->pwron_timer) {
34758 +               DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
34759 +       }
34760 +#endif
34761 +       DWC_FREE(dwc_otg_hcd);
34762 +}
34763 +
34764 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
34765 +
34766 +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
34767 +{
34768 +       int retval = 0;
34769 +       int num_channels;
34770 +       int i;
34771 +       dwc_hc_t *channel;
34772 +
34773 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
34774 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->lock);
34775 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->channel_lock);
34776 +#else
34777 +       hcd->lock = DWC_SPINLOCK_ALLOC();
34778 +       hcd->channel_lock = DWC_SPINLOCK_ALLOC();
34779 +#endif
34780 +        DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
34781 +                    hcd, core_if);
34782 +       if (!hcd->lock) {
34783 +               DWC_ERROR("Could not allocate lock for pcd");
34784 +               DWC_FREE(hcd);
34785 +               retval = -DWC_E_NO_MEMORY;
34786 +               goto out;
34787 +       }
34788 +       hcd->core_if = core_if;
34789 +
34790 +       /* Register the HCD CIL Callbacks */
34791 +       dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
34792 +                                          &hcd_cil_callbacks, hcd);
34793 +
34794 +       /* Initialize the non-periodic schedule. */
34795 +       DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
34796 +       DWC_LIST_INIT(&hcd->non_periodic_sched_active);
34797 +
34798 +       /* Initialize the periodic schedule. */
34799 +       DWC_LIST_INIT(&hcd->periodic_sched_inactive);
34800 +       DWC_LIST_INIT(&hcd->periodic_sched_ready);
34801 +       DWC_LIST_INIT(&hcd->periodic_sched_assigned);
34802 +       DWC_LIST_INIT(&hcd->periodic_sched_queued);
34803 +
34804 +       /*
34805 +        * Create a host channel descriptor for each host channel implemented
34806 +        * in the controller. Initialize the channel descriptor array.
34807 +        */
34808 +       DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
34809 +       num_channels = hcd->core_if->core_params->host_channels;
34810 +       DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
34811 +       for (i = 0; i < num_channels; i++) {
34812 +               channel = DWC_ALLOC(sizeof(dwc_hc_t));
34813 +               if (channel == NULL) {
34814 +                       retval = -DWC_E_NO_MEMORY;
34815 +                       DWC_ERROR("%s: host channel allocation failed\n",
34816 +                                 __func__);
34817 +                       dwc_otg_hcd_free(hcd);
34818 +                       goto out;
34819 +               }
34820 +               channel->hc_num = i;
34821 +               hcd->hc_ptr_array[i] = channel;
34822 +#ifdef DEBUG
34823 +               hcd->core_if->hc_xfer_timer[i] =
34824 +                   DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
34825 +                                   &hcd->core_if->hc_xfer_info[i]);
34826 +#endif
34827 +               DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
34828 +                           channel);
34829 +       }
34830 +
34831 +       /* Initialize the Connection timeout timer. */
34832 +       hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
34833 +                                         dwc_otg_hcd_connect_timeout, 0);
34834 +
34835 +       printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
34836 +       if (microframe_schedule)
34837 +               init_hcd_usecs(hcd);
34838 +
34839 +       /* Initialize reset tasklet. */
34840 +       hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
34841 +#ifdef DWC_DEV_SRPCAP
34842 +       if (hcd->core_if->power_down == 2) {
34843 +               /* Initialize Power on timer for Host power up in case hibernation */
34844 +               hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
34845 +                                                                       dwc_otg_hcd_power_up, core_if);
34846 +       }
34847 +#endif
34848 +
34849 +       /*
34850 +        * Allocate space for storing data on status transactions. Normally no
34851 +        * data is sent, but this space acts as a bit bucket. This must be
34852 +        * done after usb_add_hcd since that function allocates the DMA buffer
34853 +        * pool.
34854 +        */
34855 +       if (hcd->core_if->dma_enable) {
34856 +               hcd->status_buf =
34857 +                   DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
34858 +                                 &hcd->status_buf_dma);
34859 +       } else {
34860 +               hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
34861 +       }
34862 +       if (!hcd->status_buf) {
34863 +               retval = -DWC_E_NO_MEMORY;
34864 +               DWC_ERROR("%s: status_buf allocation failed\n", __func__);
34865 +               dwc_otg_hcd_free(hcd);
34866 +               goto out;
34867 +       }
34868 +
34869 +       hcd->otg_port = 1;
34870 +       hcd->frame_list = NULL;
34871 +       hcd->frame_list_dma = 0;
34872 +       hcd->periodic_qh_count = 0;
34873 +out:
34874 +       return retval;
34875 +}
34876 +
34877 +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
34878 +{
34879 +       /* Turn off all host-specific interrupts. */
34880 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34881 +
34882 +       dwc_otg_hcd_free(hcd);
34883 +}
34884 +
34885 +/**
34886 + * Initializes dynamic portions of the DWC_otg HCD state.
34887 + */
34888 +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
34889 +{
34890 +       int num_channels;
34891 +       int i;
34892 +       dwc_hc_t *channel;
34893 +       dwc_hc_t *channel_tmp;
34894 +
34895 +       hcd->flags.d32 = 0;
34896 +
34897 +       hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
34898 +       if (!microframe_schedule) {
34899 +               hcd->non_periodic_channels = 0;
34900 +               hcd->periodic_channels = 0;
34901 +       } else {
34902 +               hcd->available_host_channels = hcd->core_if->core_params->host_channels;
34903 +       }
34904 +       /*
34905 +        * Put all channels in the free channel list and clean up channel
34906 +        * states.
34907 +        */
34908 +       DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
34909 +                                &hcd->free_hc_list, hc_list_entry) {
34910 +               DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
34911 +       }
34912 +
34913 +       num_channels = hcd->core_if->core_params->host_channels;
34914 +       for (i = 0; i < num_channels; i++) {
34915 +               channel = hcd->hc_ptr_array[i];
34916 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
34917 +                                       hc_list_entry);
34918 +               dwc_otg_hc_cleanup(hcd->core_if, channel);
34919 +       }
34920 +
34921 +       /* Initialize the DWC core for host mode operation. */
34922 +       dwc_otg_core_host_init(hcd->core_if);
34923 +
34924 +       /* Set core_if's lock pointer to the hcd->lock */
34925 +       hcd->core_if->lock = hcd->lock;
34926 +}
34927 +
34928 +/**
34929 + * Assigns transactions from a QTD to a free host channel and initializes the
34930 + * host channel to perform the transactions. The host channel is removed from
34931 + * the free list.
34932 + *
34933 + * @param hcd The HCD state structure.
34934 + * @param qh Transactions from the first QTD for this QH are selected and
34935 + * assigned to a free host channel.
34936 + */
34937 +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34938 +{
34939 +       dwc_hc_t *hc;
34940 +       dwc_otg_qtd_t *qtd;
34941 +       dwc_otg_hcd_urb_t *urb;
34942 +       void* ptr = NULL;
34943 +
34944 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34945 +
34946 +       urb = qtd->urb;
34947 +
34948 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
34949 +
34950 +       if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
34951 +               urb->actual_length = urb->length;
34952 +
34953 +
34954 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
34955 +
34956 +       /* Remove the host channel from the free list. */
34957 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
34958 +
34959 +       qh->channel = hc;
34960 +
34961 +       qtd->in_process = 1;
34962 +
34963 +       /*
34964 +        * Use usb_pipedevice to determine device address. This address is
34965 +        * 0 before the SET_ADDRESS command and the correct address afterward.
34966 +        */
34967 +       hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
34968 +       hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
34969 +       hc->speed = qh->dev_speed;
34970 +       hc->max_packet = dwc_max_packet(qh->maxp);
34971 +
34972 +       hc->xfer_started = 0;
34973 +       hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
34974 +       hc->error_state = (qtd->error_count > 0);
34975 +       hc->halt_on_queue = 0;
34976 +       hc->halt_pending = 0;
34977 +       hc->requests = 0;
34978 +
34979 +       /*
34980 +        * The following values may be modified in the transfer type section
34981 +        * below. The xfer_len value may be reduced when the transfer is
34982 +        * started to accommodate the max widths of the XferSize and PktCnt
34983 +        * fields in the HCTSIZn register.
34984 +        */
34985 +
34986 +       hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
34987 +       if (hc->ep_is_in) {
34988 +               hc->do_ping = 0;
34989 +       } else {
34990 +               hc->do_ping = qh->ping_state;
34991 +       }
34992 +
34993 +       hc->data_pid_start = qh->data_toggle;
34994 +       hc->multi_count = 1;
34995 +
34996 +       if (hcd->core_if->dma_enable) {
34997 +               hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
34998 +
34999 +               /* For non-dword aligned case */
35000 +               if (((unsigned long)hc->xfer_buff & 0x3)
35001 +                   && !hcd->core_if->dma_desc_enable) {
35002 +                       ptr = (uint8_t *) urb->buf + urb->actual_length;
35003 +               }
35004 +       } else {
35005 +               hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
35006 +       }
35007 +       hc->xfer_len = urb->length - urb->actual_length;
35008 +       hc->xfer_count = 0;
35009 +
35010 +       /*
35011 +        * Set the split attributes
35012 +        */
35013 +       hc->do_split = 0;
35014 +       if (qh->do_split) {
35015 +               uint32_t hub_addr, port_addr;
35016 +               hc->do_split = 1;
35017 +               hc->xact_pos = qtd->isoc_split_pos;
35018 +               hc->complete_split = qtd->complete_split;
35019 +               hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
35020 +               hc->hub_addr = (uint8_t) hub_addr;
35021 +               hc->port_addr = (uint8_t) port_addr;
35022 +       }
35023 +
35024 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
35025 +       case UE_CONTROL:
35026 +               hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
35027 +               switch (qtd->control_phase) {
35028 +               case DWC_OTG_CONTROL_SETUP:
35029 +                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
35030 +                       hc->do_ping = 0;
35031 +                       hc->ep_is_in = 0;
35032 +                       hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
35033 +                       if (hcd->core_if->dma_enable) {
35034 +                               hc->xfer_buff = (uint8_t *) urb->setup_dma;
35035 +                       } else {
35036 +                               hc->xfer_buff = (uint8_t *) urb->setup_packet;
35037 +                       }
35038 +                       hc->xfer_len = 8;
35039 +                       ptr = NULL;
35040 +                       break;
35041 +               case DWC_OTG_CONTROL_DATA:
35042 +                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
35043 +                       hc->data_pid_start = qtd->data_toggle;
35044 +                       break;
35045 +               case DWC_OTG_CONTROL_STATUS:
35046 +                       /*
35047 +                        * Direction is opposite of data direction or IN if no
35048 +                        * data.
35049 +                        */
35050 +                       DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
35051 +                       if (urb->length == 0) {
35052 +                               hc->ep_is_in = 1;
35053 +                       } else {
35054 +                               hc->ep_is_in =
35055 +                                   dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
35056 +                       }
35057 +                       if (hc->ep_is_in) {
35058 +                               hc->do_ping = 0;
35059 +                       }
35060 +
35061 +                       hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
35062 +
35063 +                       hc->xfer_len = 0;
35064 +                       if (hcd->core_if->dma_enable) {
35065 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
35066 +                       } else {
35067 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf;
35068 +                       }
35069 +                       ptr = NULL;
35070 +                       break;
35071 +               }
35072 +               break;
35073 +       case UE_BULK:
35074 +               hc->ep_type = DWC_OTG_EP_TYPE_BULK;
35075 +               break;
35076 +       case UE_INTERRUPT:
35077 +               hc->ep_type = DWC_OTG_EP_TYPE_INTR;
35078 +               break;
35079 +       case UE_ISOCHRONOUS:
35080 +               {
35081 +                       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
35082 +
35083 +                       hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
35084 +
35085 +                       if (hcd->core_if->dma_desc_enable)
35086 +                               break;
35087 +
35088 +                       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
35089 +
35090 +                       frame_desc->status = 0;
35091 +
35092 +                       if (hcd->core_if->dma_enable) {
35093 +                               hc->xfer_buff = (uint8_t *) urb->dma;
35094 +                       } else {
35095 +                               hc->xfer_buff = (uint8_t *) urb->buf;
35096 +                       }
35097 +                       hc->xfer_buff +=
35098 +                           frame_desc->offset + qtd->isoc_split_offset;
35099 +                       hc->xfer_len =
35100 +                           frame_desc->length - qtd->isoc_split_offset;
35101 +
35102 +                       /* For non-dword aligned buffers */
35103 +                       if (((unsigned long)hc->xfer_buff & 0x3)
35104 +                           && hcd->core_if->dma_enable) {
35105 +                               ptr =
35106 +                                   (uint8_t *) urb->buf + frame_desc->offset +
35107 +                                   qtd->isoc_split_offset;
35108 +                       } else
35109 +                               ptr = NULL;
35110 +
35111 +                       if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
35112 +                               if (hc->xfer_len <= 188) {
35113 +                                       hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
35114 +                               } else {
35115 +                                       hc->xact_pos =
35116 +                                           DWC_HCSPLIT_XACTPOS_BEGIN;
35117 +                               }
35118 +                       }
35119 +               }
35120 +               break;
35121 +       }
35122 +       /* non DWORD-aligned buffer case */
35123 +       if (ptr) {
35124 +               uint32_t buf_size;
35125 +               if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
35126 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
35127 +               } else {
35128 +                       buf_size = 4096;
35129 +               }
35130 +               if (!qh->dw_align_buf) {
35131 +                       qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
35132 +                                                        &qh->dw_align_buf_dma);
35133 +                       if (!qh->dw_align_buf) {
35134 +                               DWC_ERROR
35135 +                                   ("%s: Failed to allocate memory to handle "
35136 +                                    "non-dword aligned buffer case\n",
35137 +                                    __func__);
35138 +                               return;
35139 +                       }
35140 +               }
35141 +               if (!hc->ep_is_in) {
35142 +                       dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
35143 +               }
35144 +               hc->align_buff = qh->dw_align_buf_dma;
35145 +       } else {
35146 +               hc->align_buff = 0;
35147 +       }
35148 +
35149 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
35150 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
35151 +               /*
35152 +                * This value may be modified when the transfer is started to
35153 +                * reflect the actual transfer length.
35154 +                */
35155 +               hc->multi_count = dwc_hb_mult(qh->maxp);
35156 +       }
35157 +
35158 +       if (hcd->core_if->dma_desc_enable)
35159 +               hc->desc_list_addr = qh->desc_list_dma;
35160 +
35161 +       dwc_otg_hc_init(hcd->core_if, hc);
35162 +       hc->qh = qh;
35163 +}
35164 +
35165 +/**
35166 + * This function selects transactions from the HCD transfer schedule and
35167 + * assigns them to available host channels. It is called from HCD interrupt
35168 + * handler functions.
35169 + *
35170 + * @param hcd The HCD state structure.
35171 + *
35172 + * @return The types of new transactions that were assigned to host channels.
35173 + */
35174 +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
35175 +{
35176 +       dwc_list_link_t *qh_ptr;
35177 +       dwc_otg_qh_t *qh;
35178 +       int num_channels;
35179 +       dwc_irqflags_t flags;
35180 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
35181 +       dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
35182 +
35183 +#ifdef DEBUG_SOF
35184 +       DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");
35185 +#endif
35186 +
35187 +#ifdef DEBUG_HOST_CHANNELS
35188 +       last_sel_trans_num_per_scheduled = 0;
35189 +       last_sel_trans_num_nonper_scheduled = 0;
35190 +       last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
35191 +#endif /* DEBUG_HOST_CHANNELS */
35192 +
35193 +       /* Process entries in the periodic ready list. */
35194 +       qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
35195 +
35196 +       while (qh_ptr != &hcd->periodic_sched_ready &&
35197 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35198 +               if (microframe_schedule) {
35199 +                       // Make sure we leave one channel for non periodic transactions.
35200 +                       DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35201 +                       if (hcd->available_host_channels <= 1) {
35202 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35203 +                               break;
35204 +                       }
35205 +                       hcd->available_host_channels--;
35206 +                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35207 +#ifdef DEBUG_HOST_CHANNELS
35208 +                       last_sel_trans_num_per_scheduled++;
35209 +#endif /* DEBUG_HOST_CHANNELS */
35210 +               }
35211 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35212 +               assign_and_init_hc(hcd, qh);
35213 +
35214 +               /*
35215 +                * Move the QH from the periodic ready schedule to the
35216 +                * periodic assigned schedule.
35217 +                */
35218 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35219 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35220 +               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
35221 +                                  &qh->qh_list_entry);
35222 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35223 +
35224 +               ret_val = DWC_OTG_TRANSACTION_PERIODIC;
35225 +       }
35226 +
35227 +       /*
35228 +        * Process entries in the inactive portion of the non-periodic
35229 +        * schedule. Some free host channels may not be used if they are
35230 +        * reserved for periodic transfers.
35231 +        */
35232 +       qh_ptr = hcd->non_periodic_sched_inactive.next;
35233 +       num_channels = hcd->core_if->core_params->host_channels;
35234 +       while (qh_ptr != &hcd->non_periodic_sched_inactive &&
35235 +              (microframe_schedule || hcd->non_periodic_channels <
35236 +               num_channels - hcd->periodic_channels) &&
35237 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35238 +
35239 +               if (microframe_schedule) {
35240 +                               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35241 +                               if (hcd->available_host_channels < 1) {
35242 +                                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35243 +                                       break;
35244 +                               }
35245 +                               hcd->available_host_channels--;
35246 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35247 +#ifdef DEBUG_HOST_CHANNELS
35248 +                               last_sel_trans_num_nonper_scheduled++;
35249 +#endif /* DEBUG_HOST_CHANNELS */
35250 +               }
35251 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35252 +
35253 +               assign_and_init_hc(hcd, qh);
35254 +
35255 +               /*
35256 +                * Move the QH from the non-periodic inactive schedule to the
35257 +                * non-periodic active schedule.
35258 +                */
35259 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35260 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35261 +               DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
35262 +                                  &qh->qh_list_entry);
35263 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35264 +
35265 +               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
35266 +                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
35267 +               } else {
35268 +                       ret_val = DWC_OTG_TRANSACTION_ALL;
35269 +               }
35270 +
35271 +               if (!microframe_schedule)
35272 +                       hcd->non_periodic_channels++;
35273 +       }
35274 +
35275 +#ifdef DEBUG_HOST_CHANNELS
35276 +       last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
35277 +#endif /* DEBUG_HOST_CHANNELS */
35278 +
35279 +       DWC_SPINLOCK_FREE(channel_lock);
35280 +       return ret_val;
35281 +}
35282 +
35283 +/**
35284 + * Attempts to queue a single transaction request for a host channel
35285 + * associated with either a periodic or non-periodic transfer. This function
35286 + * assumes that there is space available in the appropriate request queue. For
35287 + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
35288 + * is available in the appropriate Tx FIFO.
35289 + *
35290 + * @param hcd The HCD state structure.
35291 + * @param hc Host channel descriptor associated with either a periodic or
35292 + * non-periodic transfer.
35293 + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
35294 + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
35295 + * transfers.
35296 + *
35297 + * @return 1 if a request is queued and more requests may be needed to
35298 + * complete the transfer, 0 if no more requests are required for this
35299 + * transfer, -1 if there is insufficient space in the Tx FIFO.
35300 + */
35301 +static int queue_transaction(dwc_otg_hcd_t * hcd,
35302 +                            dwc_hc_t * hc, uint16_t fifo_dwords_avail)
35303 +{
35304 +       int retval;
35305 +
35306 +       if (hcd->core_if->dma_enable) {
35307 +               if (hcd->core_if->dma_desc_enable) {
35308 +                       if (!hc->xfer_started
35309 +                           || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
35310 +                               dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
35311 +                               hc->qh->ping_state = 0;
35312 +                       }
35313 +               } else if (!hc->xfer_started) {
35314 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35315 +                       hc->qh->ping_state = 0;
35316 +               }
35317 +               retval = 0;
35318 +       } else if (hc->halt_pending) {
35319 +               /* Don't queue a request if the channel has been halted. */
35320 +               retval = 0;
35321 +       } else if (hc->halt_on_queue) {
35322 +               dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
35323 +               retval = 0;
35324 +       } else if (hc->do_ping) {
35325 +               if (!hc->xfer_started) {
35326 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35327 +               }
35328 +               retval = 0;
35329 +       } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
35330 +               if ((fifo_dwords_avail * 4) >= hc->max_packet) {
35331 +                       if (!hc->xfer_started) {
35332 +                               dwc_otg_hc_start_transfer(hcd->core_if, hc);
35333 +                               retval = 1;
35334 +                       } else {
35335 +                               retval =
35336 +                                   dwc_otg_hc_continue_transfer(hcd->core_if,
35337 +                                                                hc);
35338 +                       }
35339 +               } else {
35340 +                       retval = -1;
35341 +               }
35342 +       } else {
35343 +               if (!hc->xfer_started) {
35344 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35345 +                       retval = 1;
35346 +               } else {
35347 +                       retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
35348 +               }
35349 +       }
35350 +
35351 +       return retval;
35352 +}
35353 +
35354 +/**
35355 + * Processes periodic channels for the next frame and queues transactions for
35356 + * these channels to the DWC_otg controller. After queueing transactions, the
35357 + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
35358 + * to queue as Periodic Tx FIFO or request queue space becomes available.
35359 + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
35360 + */
35361 +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
35362 +{
35363 +       hptxsts_data_t tx_status;
35364 +       dwc_list_link_t *qh_ptr;
35365 +       dwc_otg_qh_t *qh;
35366 +       int status;
35367 +       int no_queue_space = 0;
35368 +       int no_fifo_space = 0;
35369 +
35370 +       dwc_otg_host_global_regs_t *host_regs;
35371 +       host_regs = hcd->core_if->host_if->host_global_regs;
35372 +
35373 +       DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
35374 +#ifdef DEBUG
35375 +       tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35376 +       DWC_DEBUGPL(DBG_HCDV,
35377 +                   "  P Tx Req Queue Space Avail (before queue): %d\n",
35378 +                   tx_status.b.ptxqspcavail);
35379 +       DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
35380 +                   tx_status.b.ptxfspcavail);
35381 +#endif
35382 +
35383 +       qh_ptr = hcd->periodic_sched_assigned.next;
35384 +       while (qh_ptr != &hcd->periodic_sched_assigned) {
35385 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35386 +               if (tx_status.b.ptxqspcavail == 0) {
35387 +                       no_queue_space = 1;
35388 +                       break;
35389 +               }
35390 +
35391 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35392 +
35393 +               /*
35394 +                * Set a flag if we're queuing high-bandwidth in slave mode.
35395 +                * The flag prevents any halts to get into the request queue in
35396 +                * the middle of multiple high-bandwidth packets getting queued.
35397 +                */
35398 +               if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
35399 +                       hcd->core_if->queuing_high_bandwidth = 1;
35400 +               }
35401 +               status =
35402 +                   queue_transaction(hcd, qh->channel,
35403 +                                     tx_status.b.ptxfspcavail);
35404 +               if (status < 0) {
35405 +                       no_fifo_space = 1;
35406 +                       break;
35407 +               }
35408 +
35409 +               /*
35410 +                * In Slave mode, stay on the current transfer until there is
35411 +                * nothing more to do or the high-bandwidth request count is
35412 +                * reached. In DMA mode, only need to queue one request. The
35413 +                * controller automatically handles multiple packets for
35414 +                * high-bandwidth transfers.
35415 +                */
35416 +               if (hcd->core_if->dma_enable || status == 0 ||
35417 +                   qh->channel->requests == qh->channel->multi_count) {
35418 +                       qh_ptr = qh_ptr->next;
35419 +                       /*
35420 +                        * Move the QH from the periodic assigned schedule to
35421 +                        * the periodic queued schedule.
35422 +                        */
35423 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
35424 +                                          &qh->qh_list_entry);
35425 +
35426 +                       /* done queuing high bandwidth */
35427 +                       hcd->core_if->queuing_high_bandwidth = 0;
35428 +               }
35429 +       }
35430 +
35431 +       if (!hcd->core_if->dma_enable) {
35432 +               dwc_otg_core_global_regs_t *global_regs;
35433 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35434 +
35435 +               global_regs = hcd->core_if->core_global_regs;
35436 +               intr_mask.b.ptxfempty = 1;
35437 +#ifdef DEBUG
35438 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35439 +               DWC_DEBUGPL(DBG_HCDV,
35440 +                           "  P Tx Req Queue Space Avail (after queue): %d\n",
35441 +                           tx_status.b.ptxqspcavail);
35442 +               DWC_DEBUGPL(DBG_HCDV,
35443 +                           "  P Tx FIFO Space Avail (after queue): %d\n",
35444 +                           tx_status.b.ptxfspcavail);
35445 +#endif
35446 +               if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
35447 +                   no_queue_space || no_fifo_space) {
35448 +                       /*
35449 +                        * May need to queue more transactions as the request
35450 +                        * queue or Tx FIFO empties. Enable the periodic Tx
35451 +                        * FIFO empty interrupt. (Always use the half-empty
35452 +                        * level to ensure that new requests are loaded as
35453 +                        * soon as possible.)
35454 +                        */
35455 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35456 +                                        intr_mask.d32);
35457 +               } else {
35458 +                       /*
35459 +                        * Disable the Tx FIFO empty interrupt since there are
35460 +                        * no more transactions that need to be queued right
35461 +                        * now. This function is called from interrupt
35462 +                        * handlers to queue more transactions as transfer
35463 +                        * states change.
35464 +                        */
35465 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35466 +                                        0);
35467 +               }
35468 +       }
35469 +}
35470 +
35471 +/**
35472 + * Processes active non-periodic channels and queues transactions for these
35473 + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
35474 + * FIFO Empty interrupt is enabled if there are more transactions to queue as
35475 + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
35476 + * FIFO Empty interrupt is disabled.
35477 + */
35478 +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
35479 +{
35480 +       gnptxsts_data_t tx_status;
35481 +       dwc_list_link_t *orig_qh_ptr;
35482 +       dwc_otg_qh_t *qh;
35483 +       int status;
35484 +       int no_queue_space = 0;
35485 +       int no_fifo_space = 0;
35486 +       int more_to_do = 0;
35487 +
35488 +       dwc_otg_core_global_regs_t *global_regs =
35489 +           hcd->core_if->core_global_regs;
35490 +
35491 +       DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
35492 +#ifdef DEBUG
35493 +       tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35494 +       DWC_DEBUGPL(DBG_HCDV,
35495 +                   "  NP Tx Req Queue Space Avail (before queue): %d\n",
35496 +                   tx_status.b.nptxqspcavail);
35497 +       DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
35498 +                   tx_status.b.nptxfspcavail);
35499 +#endif
35500 +       /*
35501 +        * Keep track of the starting point. Skip over the start-of-list
35502 +        * entry.
35503 +        */
35504 +       if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35505 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35506 +       }
35507 +       orig_qh_ptr = hcd->non_periodic_qh_ptr;
35508 +
35509 +       /*
35510 +        * Process once through the active list or until no more space is
35511 +        * available in the request queue or the Tx FIFO.
35512 +        */
35513 +       do {
35514 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35515 +               if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
35516 +                       no_queue_space = 1;
35517 +                       break;
35518 +               }
35519 +
35520 +               qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
35521 +                                   qh_list_entry);
35522 +               status =
35523 +                   queue_transaction(hcd, qh->channel,
35524 +                                     tx_status.b.nptxfspcavail);
35525 +
35526 +               if (status > 0) {
35527 +                       more_to_do = 1;
35528 +               } else if (status < 0) {
35529 +                       no_fifo_space = 1;
35530 +                       break;
35531 +               }
35532 +
35533 +               /* Advance to next QH, skipping start-of-list entry. */
35534 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35535 +               if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35536 +                       hcd->non_periodic_qh_ptr =
35537 +                           hcd->non_periodic_qh_ptr->next;
35538 +               }
35539 +
35540 +       } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
35541 +
35542 +       if (!hcd->core_if->dma_enable) {
35543 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35544 +               intr_mask.b.nptxfempty = 1;
35545 +
35546 +#ifdef DEBUG
35547 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35548 +               DWC_DEBUGPL(DBG_HCDV,
35549 +                           "  NP Tx Req Queue Space Avail (after queue): %d\n",
35550 +                           tx_status.b.nptxqspcavail);
35551 +               DWC_DEBUGPL(DBG_HCDV,
35552 +                           "  NP Tx FIFO Space Avail (after queue): %d\n",
35553 +                           tx_status.b.nptxfspcavail);
35554 +#endif
35555 +               if (more_to_do || no_queue_space || no_fifo_space) {
35556 +                       /*
35557 +                        * May need to queue more transactions as the request
35558 +                        * queue or Tx FIFO empties. Enable the non-periodic
35559 +                        * Tx FIFO empty interrupt. (Always use the half-empty
35560 +                        * level to ensure that new requests are loaded as
35561 +                        * soon as possible.)
35562 +                        */
35563 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35564 +                                        intr_mask.d32);
35565 +               } else {
35566 +                       /*
35567 +                        * Disable the Tx FIFO empty interrupt since there are
35568 +                        * no more transactions that need to be queued right
35569 +                        * now. This function is called from interrupt
35570 +                        * handlers to queue more transactions as transfer
35571 +                        * states change.
35572 +                        */
35573 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35574 +                                        0);
35575 +               }
35576 +       }
35577 +}
35578 +
35579 +/**
35580 + * This function processes the currently active host channels and queues
35581 + * transactions for these channels to the DWC_otg controller. It is called
35582 + * from HCD interrupt handler functions.
35583 + *
35584 + * @param hcd The HCD state structure.
35585 + * @param tr_type The type(s) of transactions to queue (non-periodic,
35586 + * periodic, or both).
35587 + */
35588 +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
35589 +                                   dwc_otg_transaction_type_e tr_type)
35590 +{
35591 +#ifdef DEBUG_SOF
35592 +       DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
35593 +#endif
35594 +       /* Process host channels associated with periodic transfers. */
35595 +       if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
35596 +            tr_type == DWC_OTG_TRANSACTION_ALL) &&
35597 +           !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
35598 +
35599 +               process_periodic_channels(hcd);
35600 +       }
35601 +
35602 +       /* Process host channels associated with non-periodic transfers. */
35603 +       if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
35604 +           tr_type == DWC_OTG_TRANSACTION_ALL) {
35605 +               if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
35606 +                       process_non_periodic_channels(hcd);
35607 +               } else {
35608 +                       /*
35609 +                        * Ensure NP Tx FIFO empty interrupt is disabled when
35610 +                        * there are no non-periodic transfers to process.
35611 +                        */
35612 +                       gintmsk_data_t gintmsk = {.d32 = 0 };
35613 +                       gintmsk.b.nptxfempty = 1;
35614 +                       DWC_MODIFY_REG32(&hcd->core_if->
35615 +                                        core_global_regs->gintmsk, gintmsk.d32,
35616 +                                        0);
35617 +               }
35618 +       }
35619 +}
35620 +
35621 +#ifdef DWC_HS_ELECT_TST
35622 +/*
35623 + * Quick and dirty hack to implement the HS Electrical Test
35624 + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
35625 + *
35626 + * This code was copied from our userspace app "hset". It sends a
35627 + * Get Device Descriptor control sequence in two parts, first the
35628 + * Setup packet by itself, followed some time later by the In and
35629 + * Ack packets. Rather than trying to figure out how to add this
35630 + * functionality to the normal driver code, we just hijack the
35631 + * hardware, using these two function to drive the hardware
35632 + * directly.
35633 + */
35634 +
35635 +static dwc_otg_core_global_regs_t *global_regs;
35636 +static dwc_otg_host_global_regs_t *hc_global_regs;
35637 +static dwc_otg_hc_regs_t *hc_regs;
35638 +static uint32_t *data_fifo;
35639 +
35640 +static void do_setup(void)
35641 +{
35642 +       gintsts_data_t gintsts;
35643 +       hctsiz_data_t hctsiz;
35644 +       hcchar_data_t hcchar;
35645 +       haint_data_t haint;
35646 +       hcint_data_t hcint;
35647 +
35648 +       /* Enable HAINTs */
35649 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35650 +
35651 +       /* Enable HCINTs */
35652 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35653 +
35654 +       /* Read GINTSTS */
35655 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35656 +
35657 +       /* Read HAINT */
35658 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35659 +
35660 +       /* Read HCINT */
35661 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35662 +
35663 +       /* Read HCCHAR */
35664 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35665 +
35666 +       /* Clear HCINT */
35667 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35668 +
35669 +       /* Clear HAINT */
35670 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35671 +
35672 +       /* Clear GINTSTS */
35673 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35674 +
35675 +       /* Read GINTSTS */
35676 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35677 +
35678 +       /*
35679 +        * Send Setup packet (Get Device Descriptor)
35680 +        */
35681 +
35682 +       /* Make sure channel is disabled */
35683 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35684 +       if (hcchar.b.chen) {
35685 +               hcchar.b.chdis = 1;
35686 +//              hcchar.b.chen = 1;
35687 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35688 +               //sleep(1);
35689 +               dwc_mdelay(1000);
35690 +
35691 +               /* Read GINTSTS */
35692 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35693 +
35694 +               /* Read HAINT */
35695 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35696 +
35697 +               /* Read HCINT */
35698 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35699 +
35700 +               /* Read HCCHAR */
35701 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35702 +
35703 +               /* Clear HCINT */
35704 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35705 +
35706 +               /* Clear HAINT */
35707 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35708 +
35709 +               /* Clear GINTSTS */
35710 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35711 +
35712 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35713 +       }
35714 +
35715 +       /* Set HCTSIZ */
35716 +       hctsiz.d32 = 0;
35717 +       hctsiz.b.xfersize = 8;
35718 +       hctsiz.b.pktcnt = 1;
35719 +       hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
35720 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35721 +
35722 +       /* Set HCCHAR */
35723 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35724 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35725 +       hcchar.b.epdir = 0;
35726 +       hcchar.b.epnum = 0;
35727 +       hcchar.b.mps = 8;
35728 +       hcchar.b.chen = 1;
35729 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35730 +
35731 +       /* Fill FIFO with Setup data for Get Device Descriptor */
35732 +       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35733 +       DWC_WRITE_REG32(data_fifo++, 0x01000680);
35734 +       DWC_WRITE_REG32(data_fifo++, 0x00080000);
35735 +
35736 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35737 +
35738 +       /* Wait for host channel interrupt */
35739 +       do {
35740 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35741 +       } while (gintsts.b.hcintr == 0);
35742 +
35743 +       /* Disable HCINTs */
35744 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35745 +
35746 +       /* Disable HAINTs */
35747 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35748 +
35749 +       /* Read HAINT */
35750 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35751 +
35752 +       /* Read HCINT */
35753 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35754 +
35755 +       /* Read HCCHAR */
35756 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35757 +
35758 +       /* Clear HCINT */
35759 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35760 +
35761 +       /* Clear HAINT */
35762 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35763 +
35764 +       /* Clear GINTSTS */
35765 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35766 +
35767 +       /* Read GINTSTS */
35768 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35769 +}
35770 +
35771 +static void do_in_ack(void)
35772 +{
35773 +       gintsts_data_t gintsts;
35774 +       hctsiz_data_t hctsiz;
35775 +       hcchar_data_t hcchar;
35776 +       haint_data_t haint;
35777 +       hcint_data_t hcint;
35778 +       host_grxsts_data_t grxsts;
35779 +
35780 +       /* Enable HAINTs */
35781 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35782 +
35783 +       /* Enable HCINTs */
35784 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35785 +
35786 +       /* Read GINTSTS */
35787 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35788 +
35789 +       /* Read HAINT */
35790 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35791 +
35792 +       /* Read HCINT */
35793 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35794 +
35795 +       /* Read HCCHAR */
35796 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35797 +
35798 +       /* Clear HCINT */
35799 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35800 +
35801 +       /* Clear HAINT */
35802 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35803 +
35804 +       /* Clear GINTSTS */
35805 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35806 +
35807 +       /* Read GINTSTS */
35808 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35809 +
35810 +       /*
35811 +        * Receive Control In packet
35812 +        */
35813 +
35814 +       /* Make sure channel is disabled */
35815 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35816 +       if (hcchar.b.chen) {
35817 +               hcchar.b.chdis = 1;
35818 +               hcchar.b.chen = 1;
35819 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35820 +               //sleep(1);
35821 +               dwc_mdelay(1000);
35822 +
35823 +               /* Read GINTSTS */
35824 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35825 +
35826 +               /* Read HAINT */
35827 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35828 +
35829 +               /* Read HCINT */
35830 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35831 +
35832 +               /* Read HCCHAR */
35833 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35834 +
35835 +               /* Clear HCINT */
35836 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35837 +
35838 +               /* Clear HAINT */
35839 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35840 +
35841 +               /* Clear GINTSTS */
35842 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35843 +
35844 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35845 +       }
35846 +
35847 +       /* Set HCTSIZ */
35848 +       hctsiz.d32 = 0;
35849 +       hctsiz.b.xfersize = 8;
35850 +       hctsiz.b.pktcnt = 1;
35851 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35852 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35853 +
35854 +       /* Set HCCHAR */
35855 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35856 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35857 +       hcchar.b.epdir = 1;
35858 +       hcchar.b.epnum = 0;
35859 +       hcchar.b.mps = 8;
35860 +       hcchar.b.chen = 1;
35861 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35862 +
35863 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35864 +
35865 +       /* Wait for receive status queue interrupt */
35866 +       do {
35867 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35868 +       } while (gintsts.b.rxstsqlvl == 0);
35869 +
35870 +       /* Read RXSTS */
35871 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35872 +
35873 +       /* Clear RXSTSQLVL in GINTSTS */
35874 +       gintsts.d32 = 0;
35875 +       gintsts.b.rxstsqlvl = 1;
35876 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35877 +
35878 +       switch (grxsts.b.pktsts) {
35879 +       case DWC_GRXSTS_PKTSTS_IN:
35880 +               /* Read the data into the host buffer */
35881 +               if (grxsts.b.bcnt > 0) {
35882 +                       int i;
35883 +                       int word_count = (grxsts.b.bcnt + 3) / 4;
35884 +
35885 +                       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35886 +
35887 +                       for (i = 0; i < word_count; i++) {
35888 +                               (void)DWC_READ_REG32(data_fifo++);
35889 +                       }
35890 +               }
35891 +               break;
35892 +
35893 +       default:
35894 +               break;
35895 +       }
35896 +
35897 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35898 +
35899 +       /* Wait for receive status queue interrupt */
35900 +       do {
35901 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35902 +       } while (gintsts.b.rxstsqlvl == 0);
35903 +
35904 +       /* Read RXSTS */
35905 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35906 +
35907 +       /* Clear RXSTSQLVL in GINTSTS */
35908 +       gintsts.d32 = 0;
35909 +       gintsts.b.rxstsqlvl = 1;
35910 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35911 +
35912 +       switch (grxsts.b.pktsts) {
35913 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
35914 +               break;
35915 +
35916 +       default:
35917 +               break;
35918 +       }
35919 +
35920 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35921 +
35922 +       /* Wait for host channel interrupt */
35923 +       do {
35924 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35925 +       } while (gintsts.b.hcintr == 0);
35926 +
35927 +       /* Read HAINT */
35928 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35929 +
35930 +       /* Read HCINT */
35931 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35932 +
35933 +       /* Read HCCHAR */
35934 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35935 +
35936 +       /* Clear HCINT */
35937 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35938 +
35939 +       /* Clear HAINT */
35940 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35941 +
35942 +       /* Clear GINTSTS */
35943 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35944 +
35945 +       /* Read GINTSTS */
35946 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35947 +
35948 +//      usleep(100000);
35949 +//      mdelay(100);
35950 +       dwc_mdelay(1);
35951 +
35952 +       /*
35953 +        * Send handshake packet
35954 +        */
35955 +
35956 +       /* Read HAINT */
35957 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35958 +
35959 +       /* Read HCINT */
35960 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35961 +
35962 +       /* Read HCCHAR */
35963 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35964 +
35965 +       /* Clear HCINT */
35966 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35967 +
35968 +       /* Clear HAINT */
35969 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35970 +
35971 +       /* Clear GINTSTS */
35972 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35973 +
35974 +       /* Read GINTSTS */
35975 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35976 +
35977 +       /* Make sure channel is disabled */
35978 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35979 +       if (hcchar.b.chen) {
35980 +               hcchar.b.chdis = 1;
35981 +               hcchar.b.chen = 1;
35982 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35983 +               //sleep(1);
35984 +               dwc_mdelay(1000);
35985 +
35986 +               /* Read GINTSTS */
35987 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35988 +
35989 +               /* Read HAINT */
35990 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35991 +
35992 +               /* Read HCINT */
35993 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35994 +
35995 +               /* Read HCCHAR */
35996 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35997 +
35998 +               /* Clear HCINT */
35999 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
36000 +
36001 +               /* Clear HAINT */
36002 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
36003 +
36004 +               /* Clear GINTSTS */
36005 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
36006 +
36007 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36008 +       }
36009 +
36010 +       /* Set HCTSIZ */
36011 +       hctsiz.d32 = 0;
36012 +       hctsiz.b.xfersize = 0;
36013 +       hctsiz.b.pktcnt = 1;
36014 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
36015 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
36016 +
36017 +       /* Set HCCHAR */
36018 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36019 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36020 +       hcchar.b.epdir = 0;
36021 +       hcchar.b.epnum = 0;
36022 +       hcchar.b.mps = 8;
36023 +       hcchar.b.chen = 1;
36024 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
36025 +
36026 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36027 +
36028 +       /* Wait for host channel interrupt */
36029 +       do {
36030 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36031 +       } while (gintsts.b.hcintr == 0);
36032 +
36033 +       /* Disable HCINTs */
36034 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
36035 +
36036 +       /* Disable HAINTs */
36037 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
36038 +
36039 +       /* Read HAINT */
36040 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
36041 +
36042 +       /* Read HCINT */
36043 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
36044 +
36045 +       /* Read HCCHAR */
36046 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
36047 +
36048 +       /* Clear HCINT */
36049 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
36050 +
36051 +       /* Clear HAINT */
36052 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
36053 +
36054 +       /* Clear GINTSTS */
36055 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
36056 +
36057 +       /* Read GINTSTS */
36058 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
36059 +}
36060 +#endif
36061 +
36062 +/** Handles hub class-specific requests. */
36063 +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
36064 +                           uint16_t typeReq,
36065 +                           uint16_t wValue,
36066 +                           uint16_t wIndex, uint8_t * buf, uint16_t wLength)
36067 +{
36068 +       int retval = 0;
36069 +
36070 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
36071 +       usb_hub_descriptor_t *hub_desc;
36072 +       hprt0_data_t hprt0 = {.d32 = 0 };
36073 +
36074 +       uint32_t port_status;
36075 +
36076 +       switch (typeReq) {
36077 +       case UCR_CLEAR_HUB_FEATURE:
36078 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36079 +                           "ClearHubFeature 0x%x\n", wValue);
36080 +               switch (wValue) {
36081 +               case UHF_C_HUB_LOCAL_POWER:
36082 +               case UHF_C_HUB_OVER_CURRENT:
36083 +                       /* Nothing required here */
36084 +                       break;
36085 +               default:
36086 +                       retval = -DWC_E_INVALID;
36087 +                       DWC_ERROR("DWC OTG HCD - "
36088 +                                 "ClearHubFeature request %xh unknown\n",
36089 +                                 wValue);
36090 +               }
36091 +               break;
36092 +       case UCR_CLEAR_PORT_FEATURE:
36093 +#ifdef CONFIG_USB_DWC_OTG_LPM
36094 +               if (wValue != UHF_PORT_L1)
36095 +#endif
36096 +                       if (!wIndex || wIndex > 1)
36097 +                               goto error;
36098 +
36099 +               switch (wValue) {
36100 +               case UHF_PORT_ENABLE:
36101 +                       DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
36102 +                                   "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
36103 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36104 +                       hprt0.b.prtena = 1;
36105 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36106 +                       break;
36107 +               case UHF_PORT_SUSPEND:
36108 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36109 +                                   "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
36110 +
36111 +                       if (core_if->power_down == 2) {
36112 +                               dwc_otg_host_hibernation_restore(core_if, 0, 0);
36113 +                       } else {
36114 +                               DWC_WRITE_REG32(core_if->pcgcctl, 0);
36115 +                               dwc_mdelay(5);
36116 +
36117 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36118 +                               hprt0.b.prtres = 1;
36119 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36120 +                               hprt0.b.prtsusp = 0;
36121 +                               /* Clear Resume bit */
36122 +                               dwc_mdelay(100);
36123 +                               hprt0.b.prtres = 0;
36124 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36125 +                       }
36126 +                       break;
36127 +#ifdef CONFIG_USB_DWC_OTG_LPM
36128 +               case UHF_PORT_L1:
36129 +                       {
36130 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36131 +                               glpmcfg_data_t lpmcfg = {.d32 = 0 };
36132 +
36133 +                               lpmcfg.d32 =
36134 +                                   DWC_READ_REG32(&core_if->
36135 +                                                  core_global_regs->glpmcfg);
36136 +                               lpmcfg.b.en_utmi_sleep = 0;
36137 +                               lpmcfg.b.hird_thres &= (~(1 << 4));
36138 +                               lpmcfg.b.prt_sleep_sts = 1;
36139 +                               DWC_WRITE_REG32(&core_if->
36140 +                                               core_global_regs->glpmcfg,
36141 +                                               lpmcfg.d32);
36142 +
36143 +                               /* Clear Enbl_L1Gating bit. */
36144 +                               pcgcctl.b.enbl_sleep_gating = 1;
36145 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
36146 +                                                0);
36147 +
36148 +                               dwc_mdelay(5);
36149 +
36150 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36151 +                               hprt0.b.prtres = 1;
36152 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36153 +                                               hprt0.d32);
36154 +                               /* This bit will be cleared in wakeup interrupt handle */
36155 +                               break;
36156 +                       }
36157 +#endif
36158 +               case UHF_PORT_POWER:
36159 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36160 +                                   "ClearPortFeature USB_PORT_FEAT_POWER\n");
36161 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36162 +                       hprt0.b.prtpwr = 0;
36163 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36164 +                       break;
36165 +               case UHF_PORT_INDICATOR:
36166 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36167 +                                   "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
36168 +                       /* Port inidicator not supported */
36169 +                       break;
36170 +               case UHF_C_PORT_CONNECTION:
36171 +                       /* Clears drivers internal connect status change
36172 +                        * flag */
36173 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36174 +                                   "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
36175 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 0;
36176 +                       break;
36177 +               case UHF_C_PORT_RESET:
36178 +                       /* Clears the driver's internal Port Reset Change
36179 +                        * flag */
36180 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36181 +                                   "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
36182 +                       dwc_otg_hcd->flags.b.port_reset_change = 0;
36183 +                       break;
36184 +               case UHF_C_PORT_ENABLE:
36185 +                       /* Clears the driver's internal Port
36186 +                        * Enable/Disable Change flag */
36187 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36188 +                                   "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
36189 +                       dwc_otg_hcd->flags.b.port_enable_change = 0;
36190 +                       break;
36191 +               case UHF_C_PORT_SUSPEND:
36192 +                       /* Clears the driver's internal Port Suspend
36193 +                        * Change flag, which is set when resume signaling on
36194 +                        * the host port is complete */
36195 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36196 +                                   "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
36197 +                       dwc_otg_hcd->flags.b.port_suspend_change = 0;
36198 +                       break;
36199 +#ifdef CONFIG_USB_DWC_OTG_LPM
36200 +               case UHF_C_PORT_L1:
36201 +                       dwc_otg_hcd->flags.b.port_l1_change = 0;
36202 +                       break;
36203 +#endif
36204 +               case UHF_C_PORT_OVER_CURRENT:
36205 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36206 +                                   "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
36207 +                       dwc_otg_hcd->flags.b.port_over_current_change = 0;
36208 +                       break;
36209 +               default:
36210 +                       retval = -DWC_E_INVALID;
36211 +                       DWC_ERROR("DWC OTG HCD - "
36212 +                                 "ClearPortFeature request %xh "
36213 +                                 "unknown or unsupported\n", wValue);
36214 +               }
36215 +               break;
36216 +       case UCR_GET_HUB_DESCRIPTOR:
36217 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36218 +                           "GetHubDescriptor\n");
36219 +               hub_desc = (usb_hub_descriptor_t *) buf;
36220 +               hub_desc->bDescLength = 9;
36221 +               hub_desc->bDescriptorType = 0x29;
36222 +               hub_desc->bNbrPorts = 1;
36223 +               USETW(hub_desc->wHubCharacteristics, 0x08);
36224 +               hub_desc->bPwrOn2PwrGood = 1;
36225 +               hub_desc->bHubContrCurrent = 0;
36226 +               hub_desc->DeviceRemovable[0] = 0;
36227 +               hub_desc->DeviceRemovable[1] = 0xff;
36228 +               break;
36229 +       case UCR_GET_HUB_STATUS:
36230 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36231 +                           "GetHubStatus\n");
36232 +               DWC_MEMSET(buf, 0, 4);
36233 +               break;
36234 +       case UCR_GET_PORT_STATUS:
36235 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36236 +                           "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
36237 +                           wIndex, dwc_otg_hcd->flags.d32);
36238 +               if (!wIndex || wIndex > 1)
36239 +                       goto error;
36240 +
36241 +               port_status = 0;
36242 +
36243 +               if (dwc_otg_hcd->flags.b.port_connect_status_change)
36244 +                       port_status |= (1 << UHF_C_PORT_CONNECTION);
36245 +
36246 +               if (dwc_otg_hcd->flags.b.port_enable_change)
36247 +                       port_status |= (1 << UHF_C_PORT_ENABLE);
36248 +
36249 +               if (dwc_otg_hcd->flags.b.port_suspend_change)
36250 +                       port_status |= (1 << UHF_C_PORT_SUSPEND);
36251 +
36252 +               if (dwc_otg_hcd->flags.b.port_l1_change)
36253 +                       port_status |= (1 << UHF_C_PORT_L1);
36254 +
36255 +               if (dwc_otg_hcd->flags.b.port_reset_change) {
36256 +                       port_status |= (1 << UHF_C_PORT_RESET);
36257 +               }
36258 +
36259 +               if (dwc_otg_hcd->flags.b.port_over_current_change) {
36260 +                       DWC_WARN("Overcurrent change detected\n");
36261 +                       port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
36262 +               }
36263 +
36264 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36265 +                       /*
36266 +                        * The port is disconnected, which means the core is
36267 +                        * either in device mode or it soon will be. Just
36268 +                        * return 0's for the remainder of the port status
36269 +                        * since the port register can't be read if the core
36270 +                        * is in device mode.
36271 +                        */
36272 +                       *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36273 +                       break;
36274 +               }
36275 +
36276 +               hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
36277 +               DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
36278 +
36279 +               if (hprt0.b.prtconnsts)
36280 +                       port_status |= (1 << UHF_PORT_CONNECTION);
36281 +
36282 +               if (hprt0.b.prtena)
36283 +                       port_status |= (1 << UHF_PORT_ENABLE);
36284 +
36285 +               if (hprt0.b.prtsusp)
36286 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36287 +
36288 +               if (hprt0.b.prtovrcurract)
36289 +                       port_status |= (1 << UHF_PORT_OVER_CURRENT);
36290 +
36291 +               if (hprt0.b.prtrst)
36292 +                       port_status |= (1 << UHF_PORT_RESET);
36293 +
36294 +               if (hprt0.b.prtpwr)
36295 +                       port_status |= (1 << UHF_PORT_POWER);
36296 +
36297 +               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
36298 +                       port_status |= (1 << UHF_PORT_HIGH_SPEED);
36299 +               else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
36300 +                       port_status |= (1 << UHF_PORT_LOW_SPEED);
36301 +
36302 +               if (hprt0.b.prttstctl)
36303 +                       port_status |= (1 << UHF_PORT_TEST);
36304 +               if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
36305 +                       port_status |= (1 << UHF_PORT_L1);
36306 +               }
36307 +               /*
36308 +                  For Synopsys HW emulation of Power down wkup_control asserts the
36309 +                  hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
36310 +                  We intentionally tell the software that port is in L2Suspend state.
36311 +                  Only for STE.
36312 +               */
36313 +               if ((core_if->power_down == 2)
36314 +                   && (core_if->hibernation_suspend == 1)) {
36315 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36316 +               }
36317 +               /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
36318 +
36319 +               *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36320 +
36321 +               break;
36322 +       case UCR_SET_HUB_FEATURE:
36323 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36324 +                           "SetHubFeature\n");
36325 +               /* No HUB features supported */
36326 +               break;
36327 +       case UCR_SET_PORT_FEATURE:
36328 +               if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
36329 +                       goto error;
36330 +
36331 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36332 +                       /*
36333 +                        * The port is disconnected, which means the core is
36334 +                        * either in device mode or it soon will be. Just
36335 +                        * return without doing anything since the port
36336 +                        * register can't be written if the core is in device
36337 +                        * mode.
36338 +                        */
36339 +                       break;
36340 +               }
36341 +
36342 +               switch (wValue) {
36343 +               case UHF_PORT_SUSPEND:
36344 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36345 +                                   "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
36346 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
36347 +                               goto error;
36348 +                       }
36349 +                       if (core_if->power_down == 2) {
36350 +                               int timeout = 300;
36351 +                               dwc_irqflags_t flags;
36352 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36353 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
36354 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
36355 +#ifdef DWC_DEV_SRPCAP
36356 +                               int32_t otg_cap_param = core_if->core_params->otg_cap;
36357 +#endif
36358 +                               DWC_PRINTF("Preparing for complete power-off\n");
36359 +
36360 +                               /* Save registers before hibernation */
36361 +                               dwc_otg_save_global_regs(core_if);
36362 +                               dwc_otg_save_host_regs(core_if);
36363 +
36364 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36365 +                               hprt0.b.prtsusp = 1;
36366 +                               hprt0.b.prtena = 0;
36367 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36368 +                               /* Spin hprt0.b.prtsusp to became 1 */
36369 +                               do {
36370 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36371 +                                       if (hprt0.b.prtsusp) {
36372 +                                               break;
36373 +                                       }
36374 +                                       dwc_mdelay(1);
36375 +                               } while (--timeout);
36376 +                               if (!timeout) {
36377 +                                       DWC_WARN("Suspend wasn't genereted\n");
36378 +                               }
36379 +                               dwc_udelay(10);
36380 +
36381 +                               /*
36382 +                                * We need to disable interrupts to prevent servicing of any IRQ
36383 +                                * during going to hibernation
36384 +                                */
36385 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36386 +                               core_if->lx_state = DWC_OTG_L2;
36387 +#ifdef DWC_DEV_SRPCAP
36388 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36389 +                               hprt0.b.prtpwr = 0;
36390 +                               hprt0.b.prtena = 0;
36391 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36392 +                                               hprt0.d32);
36393 +#endif
36394 +                               gusbcfg.d32 =
36395 +                                   DWC_READ_REG32(&core_if->core_global_regs->
36396 +                                                  gusbcfg);
36397 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
36398 +                                       /* ULPI interface */
36399 +                                       /* Suspend the Phy Clock */
36400 +                                       pcgcctl.d32 = 0;
36401 +                                       pcgcctl.b.stoppclk = 1;
36402 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36403 +                                                        pcgcctl.d32);
36404 +                                       dwc_udelay(10);
36405 +                                       gpwrdn.b.pmuactv = 1;
36406 +                                       DWC_MODIFY_REG32(&core_if->
36407 +                                                        core_global_regs->
36408 +                                                        gpwrdn, 0, gpwrdn.d32);
36409 +                               } else {
36410 +                                       /* UTMI+ Interface */
36411 +                                       gpwrdn.b.pmuactv = 1;
36412 +                                       DWC_MODIFY_REG32(&core_if->
36413 +                                                        core_global_regs->
36414 +                                                        gpwrdn, 0, gpwrdn.d32);
36415 +                                       dwc_udelay(10);
36416 +                                       pcgcctl.b.stoppclk = 1;
36417 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
36418 +                                       dwc_udelay(10);
36419 +                               }
36420 +#ifdef DWC_DEV_SRPCAP
36421 +                               gpwrdn.d32 = 0;
36422 +                               gpwrdn.b.dis_vbus = 1;
36423 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36424 +                                                gpwrdn, 0, gpwrdn.d32);
36425 +#endif
36426 +                               gpwrdn.d32 = 0;
36427 +                               gpwrdn.b.pmuintsel = 1;
36428 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36429 +                                                gpwrdn, 0, gpwrdn.d32);
36430 +                               dwc_udelay(10);
36431 +
36432 +                               gpwrdn.d32 = 0;
36433 +#ifdef DWC_DEV_SRPCAP
36434 +                               gpwrdn.b.srp_det_msk = 1;
36435 +#endif
36436 +                               gpwrdn.b.disconn_det_msk = 1;
36437 +                               gpwrdn.b.lnstchng_msk = 1;
36438 +                               gpwrdn.b.sts_chngint_msk = 1;
36439 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36440 +                                                gpwrdn, 0, gpwrdn.d32);
36441 +                               dwc_udelay(10);
36442 +
36443 +                               /* Enable Power Down Clamp and all interrupts in GPWRDN */
36444 +                               gpwrdn.d32 = 0;
36445 +                               gpwrdn.b.pwrdnclmp = 1;
36446 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36447 +                                                gpwrdn, 0, gpwrdn.d32);
36448 +                               dwc_udelay(10);
36449 +
36450 +                               /* Switch off VDD */
36451 +                               gpwrdn.d32 = 0;
36452 +                               gpwrdn.b.pwrdnswtch = 1;
36453 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36454 +                                                gpwrdn, 0, gpwrdn.d32);
36455 +
36456 +#ifdef DWC_DEV_SRPCAP
36457 +                               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
36458 +                               {
36459 +                                       core_if->pwron_timer_started = 1;
36460 +                                       DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
36461 +                               }
36462 +#endif
36463 +                               /* Save gpwrdn register for further usage if stschng interrupt */
36464 +                               core_if->gr_backup->gpwrdn_local =
36465 +                                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
36466 +
36467 +                               /* Set flag to indicate that we are in hibernation */
36468 +                               core_if->hibernation_suspend = 1;
36469 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
36470 +
36471 +                               DWC_PRINTF("Host hibernation completed\n");
36472 +                               // Exit from case statement
36473 +                               break;
36474 +
36475 +                       }
36476 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
36477 +                           dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36478 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36479 +                               gotgctl.b.hstsethnpen = 1;
36480 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36481 +                                                gotgctl, 0, gotgctl.d32);
36482 +                               core_if->op_state = A_SUSPEND;
36483 +                       }
36484 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36485 +                       hprt0.b.prtsusp = 1;
36486 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36487 +                       {
36488 +                               dwc_irqflags_t flags;
36489 +                               /* Update lx_state */
36490 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36491 +                               core_if->lx_state = DWC_OTG_L2;
36492 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
36493 +                       }
36494 +                       /* Suspend the Phy Clock */
36495 +                       {
36496 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36497 +                               pcgcctl.b.stoppclk = 1;
36498 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36499 +                                                pcgcctl.d32);
36500 +                               dwc_udelay(10);
36501 +                       }
36502 +
36503 +                       /* For HNP the bus must be suspended for at least 200ms. */
36504 +                       if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36505 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36506 +                               pcgcctl.b.stoppclk = 1;
36507 +                DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36508 +                               dwc_mdelay(200);
36509 +                       }
36510 +
36511 +                       /** @todo - check how sw can wait for 1 sec to check asesvld??? */
36512 +#if 0 //vahrama !!!!!!!!!!!!!!!!!!
36513 +                       if (core_if->adp_enable) {
36514 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36515 +                               gpwrdn_data_t gpwrdn;
36516 +
36517 +                               while (gotgctl.b.asesvld == 1) {
36518 +                                       gotgctl.d32 =
36519 +                                           DWC_READ_REG32(&core_if->
36520 +                                                          core_global_regs->
36521 +                                                          gotgctl);
36522 +                                       dwc_mdelay(100);
36523 +                               }
36524 +
36525 +                               /* Enable Power Down Logic */
36526 +                               gpwrdn.d32 = 0;
36527 +                               gpwrdn.b.pmuactv = 1;
36528 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36529 +                                                gpwrdn, 0, gpwrdn.d32);
36530 +
36531 +                               /* Unmask SRP detected interrupt from Power Down Logic */
36532 +                               gpwrdn.d32 = 0;
36533 +                               gpwrdn.b.srp_det_msk = 1;
36534 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36535 +                                                gpwrdn, 0, gpwrdn.d32);
36536 +
36537 +                               dwc_otg_adp_probe_start(core_if);
36538 +                       }
36539 +#endif
36540 +                       break;
36541 +               case UHF_PORT_POWER:
36542 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36543 +                                   "SetPortFeature - USB_PORT_FEAT_POWER\n");
36544 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36545 +                       hprt0.b.prtpwr = 1;
36546 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36547 +                       break;
36548 +               case UHF_PORT_RESET:
36549 +                       if ((core_if->power_down == 2)
36550 +                           && (core_if->hibernation_suspend == 1)) {
36551 +                               /* If we are going to exit from Hibernated
36552 +                                * state via USB RESET.
36553 +                                */
36554 +                               dwc_otg_host_hibernation_restore(core_if, 0, 1);
36555 +                       } else {
36556 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36557 +
36558 +                               DWC_DEBUGPL(DBG_HCD,
36559 +                                           "DWC OTG HCD HUB CONTROL - "
36560 +                                           "SetPortFeature - USB_PORT_FEAT_RESET\n");
36561 +                               {
36562 +                                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36563 +                                       pcgcctl.b.enbl_sleep_gating = 1;
36564 +                                       pcgcctl.b.stoppclk = 1;
36565 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36566 +                                       DWC_WRITE_REG32(core_if->pcgcctl, 0);
36567 +                               }
36568 +#ifdef CONFIG_USB_DWC_OTG_LPM
36569 +                               {
36570 +                                       glpmcfg_data_t lpmcfg;
36571 +                                       lpmcfg.d32 =
36572 +                                               DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36573 +                                       if (lpmcfg.b.prt_sleep_sts) {
36574 +                                               lpmcfg.b.en_utmi_sleep = 0;
36575 +                                               lpmcfg.b.hird_thres &= (~(1 << 4));
36576 +                                               DWC_WRITE_REG32
36577 +                                                   (&core_if->core_global_regs->glpmcfg,
36578 +                                                    lpmcfg.d32);
36579 +                                               dwc_mdelay(1);
36580 +                                       }
36581 +                               }
36582 +#endif
36583 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36584 +                               /* Clear suspend bit if resetting from suspended state. */
36585 +                               hprt0.b.prtsusp = 0;
36586 +                               /* When B-Host the Port reset bit is set in
36587 +                                * the Start HCD Callback function, so that
36588 +                                * the reset is started within 1ms of the HNP
36589 +                                * success interrupt. */
36590 +                               if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
36591 +                                       hprt0.b.prtpwr = 1;
36592 +                                       hprt0.b.prtrst = 1;
36593 +                                       DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
36594 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36595 +                                                       hprt0.d32);
36596 +                               }
36597 +                               /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
36598 +                               dwc_mdelay(60);
36599 +                               hprt0.b.prtrst = 0;
36600 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36601 +                               core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
36602 +                       }
36603 +                       break;
36604 +#ifdef DWC_HS_ELECT_TST
36605 +               case UHF_PORT_TEST:
36606 +                       {
36607 +                               uint32_t t;
36608 +                               gintmsk_data_t gintmsk;
36609 +
36610 +                               t = (wIndex >> 8);      /* MSB wIndex USB */
36611 +                               DWC_DEBUGPL(DBG_HCD,
36612 +                                           "DWC OTG HCD HUB CONTROL - "
36613 +                                           "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
36614 +                                           t);
36615 +                               DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
36616 +                               if (t < 6) {
36617 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36618 +                                       hprt0.b.prttstctl = t;
36619 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36620 +                                                       hprt0.d32);
36621 +                               } else {
36622 +                                       /* Setup global vars with reg addresses (quick and
36623 +                                        * dirty hack, should be cleaned up)
36624 +                                        */
36625 +                                       global_regs = core_if->core_global_regs;
36626 +                                       hc_global_regs =
36627 +                                           core_if->host_if->host_global_regs;
36628 +                                       hc_regs =
36629 +                                           (dwc_otg_hc_regs_t *) ((char *)
36630 +                                                                  global_regs +
36631 +                                                                  0x500);
36632 +                                       data_fifo =
36633 +                                           (uint32_t *) ((char *)global_regs +
36634 +                                                         0x1000);
36635 +
36636 +                                       if (t == 6) {   /* HS_HOST_PORT_SUSPEND_RESUME */
36637 +                                               /* Save current interrupt mask */
36638 +                                               gintmsk.d32 =
36639 +                                                   DWC_READ_REG32
36640 +                                                   (&global_regs->gintmsk);
36641 +
36642 +                                               /* Disable all interrupts while we muck with
36643 +                                                * the hardware directly
36644 +                                                */
36645 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36646 +
36647 +                                               /* 15 second delay per the test spec */
36648 +                                               dwc_mdelay(15000);
36649 +
36650 +                                               /* Drive suspend on the root port */
36651 +                                               hprt0.d32 =
36652 +                                                   dwc_otg_read_hprt0(core_if);
36653 +                                               hprt0.b.prtsusp = 1;
36654 +                                               hprt0.b.prtres = 0;
36655 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36656 +
36657 +                                               /* 15 second delay per the test spec */
36658 +                                               dwc_mdelay(15000);
36659 +
36660 +                                               /* Drive resume on the root port */
36661 +                                               hprt0.d32 =
36662 +                                                   dwc_otg_read_hprt0(core_if);
36663 +                                               hprt0.b.prtsusp = 0;
36664 +                                               hprt0.b.prtres = 1;
36665 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36666 +                                               dwc_mdelay(100);
36667 +
36668 +                                               /* Clear the resume bit */
36669 +                                               hprt0.b.prtres = 0;
36670 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36671 +
36672 +                                               /* Restore interrupts */
36673 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36674 +                                       } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
36675 +                                               /* Save current interrupt mask */
36676 +                                               gintmsk.d32 =
36677 +                                                   DWC_READ_REG32
36678 +                                                   (&global_regs->gintmsk);
36679 +
36680 +                                               /* Disable all interrupts while we muck with
36681 +                                                * the hardware directly
36682 +                                                */
36683 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36684 +
36685 +                                               /* 15 second delay per the test spec */
36686 +                                               dwc_mdelay(15000);
36687 +
36688 +                                               /* Send the Setup packet */
36689 +                                               do_setup();
36690 +
36691 +                                               /* 15 second delay so nothing else happens for awhile */
36692 +                                               dwc_mdelay(15000);
36693 +
36694 +                                               /* Restore interrupts */
36695 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36696 +                                       } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
36697 +                                               /* Save current interrupt mask */
36698 +                                               gintmsk.d32 =
36699 +                                                   DWC_READ_REG32
36700 +                                                   (&global_regs->gintmsk);
36701 +
36702 +                                               /* Disable all interrupts while we muck with
36703 +                                                * the hardware directly
36704 +                                                */
36705 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36706 +
36707 +                                               /* Send the Setup packet */
36708 +                                               do_setup();
36709 +
36710 +                                               /* 15 second delay so nothing else happens for awhile */
36711 +                                               dwc_mdelay(15000);
36712 +
36713 +                                               /* Send the In and Ack packets */
36714 +                                               do_in_ack();
36715 +
36716 +                                               /* 15 second delay so nothing else happens for awhile */
36717 +                                               dwc_mdelay(15000);
36718 +
36719 +                                               /* Restore interrupts */
36720 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36721 +                                       }
36722 +                               }
36723 +                               break;
36724 +                       }
36725 +#endif /* DWC_HS_ELECT_TST */
36726 +
36727 +               case UHF_PORT_INDICATOR:
36728 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36729 +                                   "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
36730 +                       /* Not supported */
36731 +                       break;
36732 +               default:
36733 +                       retval = -DWC_E_INVALID;
36734 +                       DWC_ERROR("DWC OTG HCD - "
36735 +                                 "SetPortFeature request %xh "
36736 +                                 "unknown or unsupported\n", wValue);
36737 +                       break;
36738 +               }
36739 +               break;
36740 +#ifdef CONFIG_USB_DWC_OTG_LPM
36741 +       case UCR_SET_AND_TEST_PORT_FEATURE:
36742 +               if (wValue != UHF_PORT_L1) {
36743 +                       goto error;
36744 +               }
36745 +               {
36746 +                       int portnum, hird, devaddr, remwake;
36747 +                       glpmcfg_data_t lpmcfg;
36748 +                       uint32_t time_usecs;
36749 +                       gintsts_data_t gintsts;
36750 +                       gintmsk_data_t gintmsk;
36751 +
36752 +                       if (!dwc_otg_get_param_lpm_enable(core_if)) {
36753 +                               goto error;
36754 +                       }
36755 +                       if (wValue != UHF_PORT_L1 || wLength != 1) {
36756 +                               goto error;
36757 +                       }
36758 +                       /* Check if the port currently is in SLEEP state */
36759 +                       lpmcfg.d32 =
36760 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36761 +                       if (lpmcfg.b.prt_sleep_sts) {
36762 +                               DWC_INFO("Port is already in sleep mode\n");
36763 +                               buf[0] = 0;     /* Return success */
36764 +                               break;
36765 +                       }
36766 +
36767 +                       portnum = wIndex & 0xf;
36768 +                       hird = (wIndex >> 4) & 0xf;
36769 +                       devaddr = (wIndex >> 8) & 0x7f;
36770 +                       remwake = (wIndex >> 15);
36771 +
36772 +                       if (portnum != 1) {
36773 +                               retval = -DWC_E_INVALID;
36774 +                               DWC_WARN
36775 +                                   ("Wrong port number(%d) in SetandTestPortFeature request\n",
36776 +                                    portnum);
36777 +                               break;
36778 +                       }
36779 +
36780 +                       DWC_PRINTF
36781 +                           ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
36782 +                            portnum, hird, devaddr, remwake);
36783 +                       /* Disable LPM interrupt */
36784 +                       gintmsk.d32 = 0;
36785 +                       gintmsk.b.lpmtranrcvd = 1;
36786 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
36787 +                                        gintmsk.d32, 0);
36788 +
36789 +                       if (dwc_otg_hcd_send_lpm
36790 +                           (dwc_otg_hcd, devaddr, hird, remwake)) {
36791 +                               retval = -DWC_E_INVALID;
36792 +                               break;
36793 +                       }
36794 +
36795 +                       time_usecs = 10 * (lpmcfg.b.retry_count + 1);
36796 +                       /* We will consider timeout if time_usecs microseconds pass,
36797 +                        * and we don't receive LPM transaction status.
36798 +                        * After receiving non-error responce(ACK/NYET/STALL) from device,
36799 +                        *  core will set lpmtranrcvd bit.
36800 +                        */
36801 +                       do {
36802 +                               gintsts.d32 =
36803 +                                   DWC_READ_REG32(&core_if->core_global_regs->gintsts);
36804 +                               if (gintsts.b.lpmtranrcvd) {
36805 +                                       break;
36806 +                               }
36807 +                               dwc_udelay(1);
36808 +                       } while (--time_usecs);
36809 +                       /* lpm_int bit will be cleared in LPM interrupt handler */
36810 +
36811 +                       /* Now fill status
36812 +                        * 0x00 - Success
36813 +                        * 0x10 - NYET
36814 +                        * 0x11 - Timeout
36815 +                        */
36816 +                       if (!gintsts.b.lpmtranrcvd) {
36817 +                               buf[0] = 0x3;   /* Completion code is Timeout */
36818 +                               dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
36819 +                       } else {
36820 +                               lpmcfg.d32 =
36821 +                                   DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36822 +                               if (lpmcfg.b.lpm_resp == 0x3) {
36823 +                                       /* ACK responce from the device */
36824 +                                       buf[0] = 0x00;  /* Success */
36825 +                               } else if (lpmcfg.b.lpm_resp == 0x2) {
36826 +                                       /* NYET responce from the device */
36827 +                                       buf[0] = 0x2;
36828 +                               } else {
36829 +                                       /* Otherwise responce with Timeout */
36830 +                                       buf[0] = 0x3;
36831 +                               }
36832 +                       }
36833 +                       DWC_PRINTF("Device responce to LPM trans is %x\n",
36834 +                                  lpmcfg.b.lpm_resp);
36835 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
36836 +                                        gintmsk.d32);
36837 +
36838 +                       break;
36839 +               }
36840 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36841 +       default:
36842 +error:
36843 +               retval = -DWC_E_INVALID;
36844 +               DWC_WARN("DWC OTG HCD - "
36845 +                        "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
36846 +                        typeReq, wIndex, wValue);
36847 +               break;
36848 +       }
36849 +
36850 +       return retval;
36851 +}
36852 +
36853 +#ifdef CONFIG_USB_DWC_OTG_LPM
36854 +/** Returns index of host channel to perform LPM transaction. */
36855 +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
36856 +{
36857 +       dwc_otg_core_if_t *core_if = hcd->core_if;
36858 +       dwc_hc_t *hc;
36859 +       hcchar_data_t hcchar;
36860 +       gintmsk_data_t gintmsk = {.d32 = 0 };
36861 +
36862 +       if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
36863 +               DWC_PRINTF("No free channel to select for LPM transaction\n");
36864 +               return -1;
36865 +       }
36866 +
36867 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
36868 +
36869 +       /* Mask host channel interrupts. */
36870 +       gintmsk.b.hcintr = 1;
36871 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
36872 +
36873 +       /* Fill fields that core needs for LPM transaction */
36874 +       hcchar.b.devaddr = devaddr;
36875 +       hcchar.b.epnum = 0;
36876 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36877 +       hcchar.b.mps = 64;
36878 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
36879 +       hcchar.b.epdir = 0;     /* OUT */
36880 +       DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
36881 +                       hcchar.d32);
36882 +
36883 +       /* Remove the host channel from the free list. */
36884 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
36885 +
36886 +       DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
36887 +
36888 +       return hc->hc_num;
36889 +}
36890 +
36891 +/** Release hc after performing LPM transaction */
36892 +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
36893 +{
36894 +       dwc_hc_t *hc;
36895 +       glpmcfg_data_t lpmcfg;
36896 +       uint8_t hc_num;
36897 +
36898 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36899 +       hc_num = lpmcfg.b.lpm_chan_index;
36900 +
36901 +       hc = hcd->hc_ptr_array[hc_num];
36902 +
36903 +       DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
36904 +       /* Return host channel to free list */
36905 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
36906 +}
36907 +
36908 +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
36909 +                        uint8_t bRemoteWake)
36910 +{
36911 +       glpmcfg_data_t lpmcfg;
36912 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36913 +       int channel;
36914 +
36915 +       channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
36916 +       if (channel < 0) {
36917 +               return channel;
36918 +       }
36919 +
36920 +       pcgcctl.b.enbl_sleep_gating = 1;
36921 +       DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
36922 +
36923 +       /* Read LPM config register */
36924 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36925 +
36926 +       /* Program LPM transaction fields */
36927 +       lpmcfg.b.rem_wkup_en = bRemoteWake;
36928 +       lpmcfg.b.hird = hird;
36929 +       lpmcfg.b.hird_thres = 0x1c;
36930 +       lpmcfg.b.lpm_chan_index = channel;
36931 +       lpmcfg.b.en_utmi_sleep = 1;
36932 +       /* Program LPM config register */
36933 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36934 +
36935 +       /* Send LPM transaction */
36936 +       lpmcfg.b.send_lpm = 1;
36937 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36938 +
36939 +       return 0;
36940 +}
36941 +
36942 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36943 +
36944 +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
36945 +{
36946 +       int retval;
36947 +
36948 +       if (port != 1) {
36949 +               return -DWC_E_INVALID;
36950 +       }
36951 +
36952 +       retval = (hcd->flags.b.port_connect_status_change ||
36953 +                 hcd->flags.b.port_reset_change ||
36954 +                 hcd->flags.b.port_enable_change ||
36955 +                 hcd->flags.b.port_suspend_change ||
36956 +                 hcd->flags.b.port_over_current_change);
36957 +#ifdef DEBUG
36958 +       if (retval) {
36959 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
36960 +                           " Root port status changed\n");
36961 +               DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
36962 +                           hcd->flags.b.port_connect_status_change);
36963 +               DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
36964 +                           hcd->flags.b.port_reset_change);
36965 +               DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
36966 +                           hcd->flags.b.port_enable_change);
36967 +               DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
36968 +                           hcd->flags.b.port_suspend_change);
36969 +               DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
36970 +                           hcd->flags.b.port_over_current_change);
36971 +       }
36972 +#endif
36973 +       return retval;
36974 +}
36975 +
36976 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
36977 +{
36978 +       hfnum_data_t hfnum;
36979 +       hfnum.d32 =
36980 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
36981 +                          hfnum);
36982 +
36983 +#ifdef DEBUG_SOF
36984 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
36985 +                   hfnum.b.frnum);
36986 +#endif
36987 +       return hfnum.b.frnum;
36988 +}
36989 +
36990 +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
36991 +                     struct dwc_otg_hcd_function_ops *fops)
36992 +{
36993 +       int retval = 0;
36994 +
36995 +       hcd->fops = fops;
36996 +       if (!dwc_otg_is_device_mode(hcd->core_if) &&
36997 +               (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
36998 +               dwc_otg_hcd_reinit(hcd);
36999 +       } else {
37000 +               retval = -DWC_E_NO_DEVICE;
37001 +       }
37002 +
37003 +       return retval;
37004 +}
37005 +
37006 +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
37007 +{
37008 +       return hcd->priv;
37009 +}
37010 +
37011 +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
37012 +{
37013 +       hcd->priv = priv_data;
37014 +}
37015 +
37016 +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
37017 +{
37018 +       return hcd->otg_port;
37019 +}
37020 +
37021 +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
37022 +{
37023 +       uint32_t is_b_host;
37024 +       if (hcd->core_if->op_state == B_HOST) {
37025 +               is_b_host = 1;
37026 +       } else {
37027 +               is_b_host = 0;
37028 +       }
37029 +
37030 +       return is_b_host;
37031 +}
37032 +
37033 +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
37034 +                                        int iso_desc_count, int atomic_alloc)
37035 +{
37036 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
37037 +       uint32_t size;
37038 +
37039 +       size =
37040 +           sizeof(*dwc_otg_urb) +
37041 +           iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
37042 +       if (atomic_alloc)
37043 +               dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
37044 +       else
37045 +               dwc_otg_urb = DWC_ALLOC(size);
37046 +
37047 +        if (NULL != dwc_otg_urb)
37048 +                dwc_otg_urb->packet_count = iso_desc_count;
37049 +        else {
37050 +                dwc_otg_urb->packet_count = 0;
37051 +                if (size != 0) {
37052 +                        DWC_ERROR("**** DWC OTG HCD URB alloc - "
37053 +                                  "%salloc of %db failed\n",
37054 +                                  atomic_alloc?"atomic ":"", size);
37055 +                }
37056 +        }
37057 +
37058 +       return dwc_otg_urb;
37059 +}
37060 +
37061 +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
37062 +                                 uint8_t dev_addr, uint8_t ep_num,
37063 +                                 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
37064 +{
37065 +       dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
37066 +                             ep_type, ep_dir, mps);
37067 +#if 0
37068 +       DWC_PRINTF
37069 +           ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
37070 +            dev_addr, ep_num, ep_dir, ep_type, mps);
37071 +#endif
37072 +}
37073 +
37074 +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
37075 +                               void *urb_handle, void *buf, dwc_dma_t dma,
37076 +                               uint32_t buflen, void *setup_packet,
37077 +                               dwc_dma_t setup_dma, uint32_t flags,
37078 +                               uint16_t interval)
37079 +{
37080 +       dwc_otg_urb->priv = urb_handle;
37081 +       dwc_otg_urb->buf = buf;
37082 +       dwc_otg_urb->dma = dma;
37083 +       dwc_otg_urb->length = buflen;
37084 +       dwc_otg_urb->setup_packet = setup_packet;
37085 +       dwc_otg_urb->setup_dma = setup_dma;
37086 +       dwc_otg_urb->flags = flags;
37087 +       dwc_otg_urb->interval = interval;
37088 +       dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
37089 +}
37090 +
37091 +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
37092 +{
37093 +       return dwc_otg_urb->status;
37094 +}
37095 +
37096 +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
37097 +{
37098 +       return dwc_otg_urb->actual_length;
37099 +}
37100 +
37101 +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
37102 +{
37103 +       return dwc_otg_urb->error_count;
37104 +}
37105 +
37106 +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
37107 +                                        int desc_num, uint32_t offset,
37108 +                                        uint32_t length)
37109 +{
37110 +       dwc_otg_urb->iso_descs[desc_num].offset = offset;
37111 +       dwc_otg_urb->iso_descs[desc_num].length = length;
37112 +}
37113 +
37114 +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
37115 +                                            int desc_num)
37116 +{
37117 +       return dwc_otg_urb->iso_descs[desc_num].status;
37118 +}
37119 +
37120 +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
37121 +                                                   dwc_otg_urb, int desc_num)
37122 +{
37123 +       return dwc_otg_urb->iso_descs[desc_num].actual_length;
37124 +}
37125 +
37126 +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
37127 +{
37128 +       int allocated = 0;
37129 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37130 +
37131 +       if (qh) {
37132 +               if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37133 +                       allocated = 1;
37134 +               }
37135 +       }
37136 +       return allocated;
37137 +}
37138 +
37139 +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
37140 +{
37141 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37142 +       int freed = 0;
37143 +       DWC_ASSERT(qh, "qh is not allocated\n");
37144 +
37145 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37146 +               freed = 1;
37147 +       }
37148 +
37149 +       return freed;
37150 +}
37151 +
37152 +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
37153 +{
37154 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37155 +       DWC_ASSERT(qh, "qh is not allocated\n");
37156 +       return qh->usecs;
37157 +}
37158 +
37159 +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
37160 +{
37161 +#ifdef DEBUG
37162 +       int num_channels;
37163 +       int i;
37164 +       gnptxsts_data_t np_tx_status;
37165 +       hptxsts_data_t p_tx_status;
37166 +
37167 +       num_channels = hcd->core_if->core_params->host_channels;
37168 +       DWC_PRINTF("\n");
37169 +       DWC_PRINTF
37170 +           ("************************************************************\n");
37171 +       DWC_PRINTF("HCD State:\n");
37172 +       DWC_PRINTF("  Num channels: %d\n", num_channels);
37173 +       for (i = 0; i < num_channels; i++) {
37174 +               dwc_hc_t *hc = hcd->hc_ptr_array[i];
37175 +               DWC_PRINTF("  Channel %d:\n", i);
37176 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
37177 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
37178 +               DWC_PRINTF("    speed: %d\n", hc->speed);
37179 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
37180 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
37181 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
37182 +               DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
37183 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
37184 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
37185 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
37186 +               DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
37187 +               DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
37188 +               DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
37189 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
37190 +               DWC_PRINTF("    do_split: %d\n", hc->do_split);
37191 +               DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
37192 +               DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
37193 +               DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
37194 +               DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
37195 +               DWC_PRINTF("    requests: %d\n", hc->requests);
37196 +               DWC_PRINTF("    qh: %p\n", hc->qh);
37197 +               if (hc->xfer_started) {
37198 +                       hfnum_data_t hfnum;
37199 +                       hcchar_data_t hcchar;
37200 +                       hctsiz_data_t hctsiz;
37201 +                       hcint_data_t hcint;
37202 +                       hcintmsk_data_t hcintmsk;
37203 +                       hfnum.d32 =
37204 +                           DWC_READ_REG32(&hcd->core_if->
37205 +                                          host_if->host_global_regs->hfnum);
37206 +                       hcchar.d32 =
37207 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37208 +                                          hc_regs[i]->hcchar);
37209 +                       hctsiz.d32 =
37210 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37211 +                                          hc_regs[i]->hctsiz);
37212 +                       hcint.d32 =
37213 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37214 +                                          hc_regs[i]->hcint);
37215 +                       hcintmsk.d32 =
37216 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37217 +                                          hc_regs[i]->hcintmsk);
37218 +                       DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
37219 +                       DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
37220 +                       DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
37221 +                       DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
37222 +                       DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
37223 +               }
37224 +               if (hc->xfer_started && hc->qh) {
37225 +                       dwc_otg_qtd_t *qtd;
37226 +                       dwc_otg_hcd_urb_t *urb;
37227 +
37228 +                       DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
37229 +                               if (!qtd->in_process)
37230 +                                       break;
37231 +
37232 +                               urb = qtd->urb;
37233 +                       DWC_PRINTF("    URB Info:\n");
37234 +                       DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
37235 +                       if (urb) {
37236 +                               DWC_PRINTF("      Dev: %d, EP: %d %s\n",
37237 +                                          dwc_otg_hcd_get_dev_addr(&urb->
37238 +                                                                   pipe_info),
37239 +                                          dwc_otg_hcd_get_ep_num(&urb->
37240 +                                                                 pipe_info),
37241 +                                          dwc_otg_hcd_is_pipe_in(&urb->
37242 +                                                                 pipe_info) ?
37243 +                                          "IN" : "OUT");
37244 +                               DWC_PRINTF("      Max packet size: %d\n",
37245 +                                          dwc_otg_hcd_get_mps(&urb->
37246 +                                                              pipe_info));
37247 +                               DWC_PRINTF("      transfer_buffer: %p\n",
37248 +                                          urb->buf);
37249 +                               DWC_PRINTF("      transfer_dma: %p\n",
37250 +                                          (void *)urb->dma);
37251 +                               DWC_PRINTF("      transfer_buffer_length: %d\n",
37252 +                                          urb->length);
37253 +                                       DWC_PRINTF("      actual_length: %d\n",
37254 +                                                  urb->actual_length);
37255 +                               }
37256 +                       }
37257 +               }
37258 +       }
37259 +       DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
37260 +       DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
37261 +       DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
37262 +       np_tx_status.d32 =
37263 +           DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
37264 +       DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
37265 +                  np_tx_status.b.nptxqspcavail);
37266 +       DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
37267 +                  np_tx_status.b.nptxfspcavail);
37268 +       p_tx_status.d32 =
37269 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
37270 +       DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
37271 +                  p_tx_status.b.ptxqspcavail);
37272 +       DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
37273 +       dwc_otg_hcd_dump_frrem(hcd);
37274 +       dwc_otg_dump_global_registers(hcd->core_if);
37275 +       dwc_otg_dump_host_registers(hcd->core_if);
37276 +       DWC_PRINTF
37277 +           ("************************************************************\n");
37278 +       DWC_PRINTF("\n");
37279 +#endif
37280 +}
37281 +
37282 +#ifdef DEBUG
37283 +void dwc_print_setup_data(uint8_t * setup)
37284 +{
37285 +       int i;
37286 +       if (CHK_DEBUG_LEVEL(DBG_HCD)) {
37287 +               DWC_PRINTF("Setup Data = MSB ");
37288 +               for (i = 7; i >= 0; i--)
37289 +                       DWC_PRINTF("%02x ", setup[i]);
37290 +               DWC_PRINTF("\n");
37291 +               DWC_PRINTF("  bmRequestType Tranfer = %s\n",
37292 +                          (setup[0] & 0x80) ? "Device-to-Host" :
37293 +                          "Host-to-Device");
37294 +               DWC_PRINTF("  bmRequestType Type = ");
37295 +               switch ((setup[0] & 0x60) >> 5) {
37296 +               case 0:
37297 +                       DWC_PRINTF("Standard\n");
37298 +                       break;
37299 +               case 1:
37300 +                       DWC_PRINTF("Class\n");
37301 +                       break;
37302 +               case 2:
37303 +                       DWC_PRINTF("Vendor\n");
37304 +                       break;
37305 +               case 3:
37306 +                       DWC_PRINTF("Reserved\n");
37307 +                       break;
37308 +               }
37309 +               DWC_PRINTF("  bmRequestType Recipient = ");
37310 +               switch (setup[0] & 0x1f) {
37311 +               case 0:
37312 +                       DWC_PRINTF("Device\n");
37313 +                       break;
37314 +               case 1:
37315 +                       DWC_PRINTF("Interface\n");
37316 +                       break;
37317 +               case 2:
37318 +                       DWC_PRINTF("Endpoint\n");
37319 +                       break;
37320 +               case 3:
37321 +                       DWC_PRINTF("Other\n");
37322 +                       break;
37323 +               default:
37324 +                       DWC_PRINTF("Reserved\n");
37325 +                       break;
37326 +               }
37327 +               DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
37328 +               DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
37329 +               DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
37330 +               DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
37331 +       }
37332 +}
37333 +#endif
37334 +
37335 +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
37336 +{
37337 +#if 0
37338 +       DWC_PRINTF("Frame remaining at SOF:\n");
37339 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37340 +                  hcd->frrem_samples, hcd->frrem_accum,
37341 +                  (hcd->frrem_samples > 0) ?
37342 +                  hcd->frrem_accum / hcd->frrem_samples : 0);
37343 +
37344 +       DWC_PRINTF("\n");
37345 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
37346 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37347 +                  hcd->core_if->hfnum_7_samples,
37348 +                  hcd->core_if->hfnum_7_frrem_accum,
37349 +                  (hcd->core_if->hfnum_7_samples >
37350 +                   0) ? hcd->core_if->hfnum_7_frrem_accum /
37351 +                  hcd->core_if->hfnum_7_samples : 0);
37352 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
37353 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37354 +                  hcd->core_if->hfnum_0_samples,
37355 +                  hcd->core_if->hfnum_0_frrem_accum,
37356 +                  (hcd->core_if->hfnum_0_samples >
37357 +                   0) ? hcd->core_if->hfnum_0_frrem_accum /
37358 +                  hcd->core_if->hfnum_0_samples : 0);
37359 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
37360 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37361 +                  hcd->core_if->hfnum_other_samples,
37362 +                  hcd->core_if->hfnum_other_frrem_accum,
37363 +                  (hcd->core_if->hfnum_other_samples >
37364 +                   0) ? hcd->core_if->hfnum_other_frrem_accum /
37365 +                  hcd->core_if->hfnum_other_samples : 0);
37366 +
37367 +       DWC_PRINTF("\n");
37368 +       DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
37369 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37370 +                  hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
37371 +                  (hcd->hfnum_7_samples_a > 0) ?
37372 +                  hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
37373 +       DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
37374 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37375 +                  hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
37376 +                  (hcd->hfnum_0_samples_a > 0) ?
37377 +                  hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
37378 +       DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
37379 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37380 +                  hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
37381 +                  (hcd->hfnum_other_samples_a > 0) ?
37382 +                  hcd->hfnum_other_frrem_accum_a /
37383 +                  hcd->hfnum_other_samples_a : 0);
37384 +
37385 +       DWC_PRINTF("\n");
37386 +       DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
37387 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37388 +                  hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
37389 +                  (hcd->hfnum_7_samples_b > 0) ?
37390 +                  hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
37391 +       DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
37392 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37393 +                  hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
37394 +                  (hcd->hfnum_0_samples_b > 0) ?
37395 +                  hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
37396 +       DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
37397 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37398 +                  hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
37399 +                  (hcd->hfnum_other_samples_b > 0) ?
37400 +                  hcd->hfnum_other_frrem_accum_b /
37401 +                  hcd->hfnum_other_samples_b : 0);
37402 +#endif
37403 +}
37404 +
37405 +#endif /* DWC_DEVICE_ONLY */
37406 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
37407 new file mode 100644
37408 index 0000000..bb4f67a
37409 --- /dev/null
37410 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
37411 @@ -0,0 +1,824 @@
37412 +/* ==========================================================================
37413 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
37414 + * $Revision: #58 $
37415 + * $Date: 2011/09/15 $
37416 + * $Change: 1846647 $
37417 + *
37418 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
37419 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
37420 + * otherwise expressly agreed to in writing between Synopsys and you.
37421 + *
37422 + * The Software IS NOT an item of Licensed Software or Licensed Product under
37423 + * any End User Software License Agreement or Agreement for Licensed Product
37424 + * with Synopsys or any supplement thereto. You are permitted to use and
37425 + * redistribute this Software in source and binary forms, with or without
37426 + * modification, provided that redistributions of source code must retain this
37427 + * notice. You may not view, use, disclose, copy or distribute this file or
37428 + * any information contained herein except pursuant to this license grant from
37429 + * Synopsys. If you do not agree with this notice, including the disclaimer
37430 + * below, then you are not authorized to use the Software.
37431 + *
37432 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
37433 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37434 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37435 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
37436 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37437 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37438 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37439 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37440 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37441 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
37442 + * DAMAGE.
37443 + * ========================================================================== */
37444 +#ifndef DWC_DEVICE_ONLY
37445 +#ifndef __DWC_HCD_H__
37446 +#define __DWC_HCD_H__
37447 +
37448 +#include "dwc_otg_os_dep.h"
37449 +#include "usb.h"
37450 +#include "dwc_otg_hcd_if.h"
37451 +#include "dwc_otg_core_if.h"
37452 +#include "dwc_list.h"
37453 +#include "dwc_otg_cil.h"
37454 +
37455 +/**
37456 + * @file
37457 + *
37458 + * This file contains the structures, constants, and interfaces for
37459 + * the Host Contoller Driver (HCD).
37460 + *
37461 + * The Host Controller Driver (HCD) is responsible for translating requests
37462 + * from the USB Driver into the appropriate actions on the DWC_otg controller.
37463 + * It isolates the USBD from the specifics of the controller by providing an
37464 + * API to the USBD.
37465 + */
37466 +
37467 +struct dwc_otg_hcd_pipe_info {
37468 +       uint8_t dev_addr;
37469 +       uint8_t ep_num;
37470 +       uint8_t pipe_type;
37471 +       uint8_t pipe_dir;
37472 +       uint16_t mps;
37473 +};
37474 +
37475 +struct dwc_otg_hcd_iso_packet_desc {
37476 +       uint32_t offset;
37477 +       uint32_t length;
37478 +       uint32_t actual_length;
37479 +       uint32_t status;
37480 +};
37481 +
37482 +struct dwc_otg_qtd;
37483 +
37484 +struct dwc_otg_hcd_urb {
37485 +       void *priv;
37486 +       struct dwc_otg_qtd *qtd;
37487 +       void *buf;
37488 +       dwc_dma_t dma;
37489 +       void *setup_packet;
37490 +       dwc_dma_t setup_dma;
37491 +       uint32_t length;
37492 +       uint32_t actual_length;
37493 +       uint32_t status;
37494 +       uint32_t error_count;
37495 +       uint32_t packet_count;
37496 +       uint32_t flags;
37497 +       uint16_t interval;
37498 +       struct dwc_otg_hcd_pipe_info pipe_info;
37499 +       struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
37500 +};
37501 +
37502 +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
37503 +{
37504 +       return pipe->ep_num;
37505 +}
37506 +
37507 +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
37508 +                                               *pipe)
37509 +{
37510 +       return pipe->pipe_type;
37511 +}
37512 +
37513 +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
37514 +{
37515 +       return pipe->mps;
37516 +}
37517 +
37518 +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
37519 +                                              *pipe)
37520 +{
37521 +       return pipe->dev_addr;
37522 +}
37523 +
37524 +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
37525 +                                              *pipe)
37526 +{
37527 +       return (pipe->pipe_type == UE_ISOCHRONOUS);
37528 +}
37529 +
37530 +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
37531 +                                             *pipe)
37532 +{
37533 +       return (pipe->pipe_type == UE_INTERRUPT);
37534 +}
37535 +
37536 +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
37537 +                                              *pipe)
37538 +{
37539 +       return (pipe->pipe_type == UE_BULK);
37540 +}
37541 +
37542 +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
37543 +                                                 *pipe)
37544 +{
37545 +       return (pipe->pipe_type == UE_CONTROL);
37546 +}
37547 +
37548 +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
37549 +{
37550 +       return (pipe->pipe_dir == UE_DIR_IN);
37551 +}
37552 +
37553 +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
37554 +                                             *pipe)
37555 +{
37556 +       return (!dwc_otg_hcd_is_pipe_in(pipe));
37557 +}
37558 +
37559 +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
37560 +                                        uint8_t devaddr, uint8_t ep_num,
37561 +                                        uint8_t pipe_type, uint8_t pipe_dir,
37562 +                                        uint16_t mps)
37563 +{
37564 +       pipe->dev_addr = devaddr;
37565 +       pipe->ep_num = ep_num;
37566 +       pipe->pipe_type = pipe_type;
37567 +       pipe->pipe_dir = pipe_dir;
37568 +       pipe->mps = mps;
37569 +}
37570 +
37571 +/**
37572 + * Phases for control transfers.
37573 + */
37574 +typedef enum dwc_otg_control_phase {
37575 +       DWC_OTG_CONTROL_SETUP,
37576 +       DWC_OTG_CONTROL_DATA,
37577 +       DWC_OTG_CONTROL_STATUS
37578 +} dwc_otg_control_phase_e;
37579 +
37580 +/** Transaction types. */
37581 +typedef enum dwc_otg_transaction_type {
37582 +       DWC_OTG_TRANSACTION_NONE,
37583 +       DWC_OTG_TRANSACTION_PERIODIC,
37584 +       DWC_OTG_TRANSACTION_NON_PERIODIC,
37585 +       DWC_OTG_TRANSACTION_ALL
37586 +} dwc_otg_transaction_type_e;
37587 +
37588 +struct dwc_otg_qh;
37589 +
37590 +/**
37591 + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
37592 + * interrupt, or isochronous transfer. A single QTD is created for each URB
37593 + * (of one of these types) submitted to the HCD. The transfer associated with
37594 + * a QTD may require one or multiple transactions.
37595 + *
37596 + * A QTD is linked to a Queue Head, which is entered in either the
37597 + * non-periodic or periodic schedule for execution. When a QTD is chosen for
37598 + * execution, some or all of its transactions may be executed. After
37599 + * execution, the state of the QTD is updated. The QTD may be retired if all
37600 + * its transactions are complete or if an error occurred. Otherwise, it
37601 + * remains in the schedule so more transactions can be executed later.
37602 + */
37603 +typedef struct dwc_otg_qtd {
37604 +       /**
37605 +        * Determines the PID of the next data packet for the data phase of
37606 +        * control transfers. Ignored for other transfer types.<br>
37607 +        * One of the following values:
37608 +        *      - DWC_OTG_HC_PID_DATA0
37609 +        *      - DWC_OTG_HC_PID_DATA1
37610 +        */
37611 +       uint8_t data_toggle;
37612 +
37613 +       /** Current phase for control transfers (Setup, Data, or Status). */
37614 +       dwc_otg_control_phase_e control_phase;
37615 +
37616 +       /** Keep track of the current split type
37617 +        * for FS/LS endpoints on a HS Hub */
37618 +       uint8_t complete_split;
37619 +
37620 +       /** How many bytes transferred during SSPLIT OUT */
37621 +       uint32_t ssplit_out_xfer_count;
37622 +
37623 +       /**
37624 +        * Holds the number of bus errors that have occurred for a transaction
37625 +        * within this transfer.
37626 +        */
37627 +       uint8_t error_count;
37628 +
37629 +       /**
37630 +        * Index of the next frame descriptor for an isochronous transfer. A
37631 +        * frame descriptor describes the buffer position and length of the
37632 +        * data to be transferred in the next scheduled (micro)frame of an
37633 +        * isochronous transfer. It also holds status for that transaction.
37634 +        * The frame index starts at 0.
37635 +        */
37636 +       uint16_t isoc_frame_index;
37637 +
37638 +       /** Position of the ISOC split on full/low speed */
37639 +       uint8_t isoc_split_pos;
37640 +
37641 +       /** Position of the ISOC split in the buffer for the current frame */
37642 +       uint16_t isoc_split_offset;
37643 +
37644 +       /** URB for this transfer */
37645 +       struct dwc_otg_hcd_urb *urb;
37646 +
37647 +       struct dwc_otg_qh *qh;
37648 +
37649 +       /** This list of QTDs */
37650 +        DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
37651 +
37652 +       /** Indicates if this QTD is currently processed by HW. */
37653 +       uint8_t in_process;
37654 +
37655 +       /** Number of DMA descriptors for this QTD */
37656 +       uint8_t n_desc;
37657 +
37658 +       /**
37659 +        * Last activated frame(packet) index.
37660 +        * Used in Descriptor DMA mode only.
37661 +        */
37662 +       uint16_t isoc_frame_index_last;
37663 +
37664 +} dwc_otg_qtd_t;
37665 +
37666 +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
37667 +
37668 +/**
37669 + * A Queue Head (QH) holds the static characteristics of an endpoint and
37670 + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
37671 + * be entered in either the non-periodic or periodic schedule.
37672 + */
37673 +typedef struct dwc_otg_qh {
37674 +       /**
37675 +        * Endpoint type.
37676 +        * One of the following values:
37677 +        *      - UE_CONTROL
37678 +        *      - UE_BULK
37679 +        *      - UE_INTERRUPT
37680 +        *      - UE_ISOCHRONOUS
37681 +        */
37682 +       uint8_t ep_type;
37683 +       uint8_t ep_is_in;
37684 +
37685 +       /** wMaxPacketSize Field of Endpoint Descriptor. */
37686 +       uint16_t maxp;
37687 +
37688 +       /**
37689 +        * Device speed.
37690 +        * One of the following values:
37691 +        *      - DWC_OTG_EP_SPEED_LOW
37692 +        *      - DWC_OTG_EP_SPEED_FULL
37693 +        *      - DWC_OTG_EP_SPEED_HIGH
37694 +        */
37695 +       uint8_t dev_speed;
37696 +
37697 +       /**
37698 +        * Determines the PID of the next data packet for non-control
37699 +        * transfers. Ignored for control transfers.<br>
37700 +        * One of the following values:
37701 +        *      - DWC_OTG_HC_PID_DATA0
37702 +        *      - DWC_OTG_HC_PID_DATA1
37703 +        */
37704 +       uint8_t data_toggle;
37705 +
37706 +       /** Ping state if 1. */
37707 +       uint8_t ping_state;
37708 +
37709 +       /**
37710 +        * List of QTDs for this QH.
37711 +        */
37712 +       struct dwc_otg_qtd_list qtd_list;
37713 +
37714 +       /** Host channel currently processing transfers for this QH. */
37715 +       struct dwc_hc *channel;
37716 +
37717 +       /** Full/low speed endpoint on high-speed hub requires split. */
37718 +       uint8_t do_split;
37719 +
37720 +       /** @name Periodic schedule information */
37721 +       /** @{ */
37722 +
37723 +       /** Bandwidth in microseconds per (micro)frame. */
37724 +       uint16_t usecs;
37725 +
37726 +       /** Interval between transfers in (micro)frames. */
37727 +       uint16_t interval;
37728 +
37729 +       /**
37730 +        * (micro)frame to initialize a periodic transfer. The transfer
37731 +        * executes in the following (micro)frame.
37732 +        */
37733 +       uint16_t sched_frame;
37734 +
37735 +       /** (micro)frame at which last start split was initialized. */
37736 +       uint16_t start_split_frame;
37737 +
37738 +       /** @} */
37739 +
37740 +       /**
37741 +        * Used instead of original buffer if
37742 +        * it(physical address) is not dword-aligned.
37743 +        */
37744 +       uint8_t *dw_align_buf;
37745 +       dwc_dma_t dw_align_buf_dma;
37746 +
37747 +       /** Entry for QH in either the periodic or non-periodic schedule. */
37748 +       dwc_list_link_t qh_list_entry;
37749 +
37750 +       /** @name Descriptor DMA support */
37751 +       /** @{ */
37752 +
37753 +       /** Descriptor List. */
37754 +       dwc_otg_host_dma_desc_t *desc_list;
37755 +
37756 +       /** Descriptor List physical address. */
37757 +       dwc_dma_t desc_list_dma;
37758 +
37759 +       /**
37760 +        * Xfer Bytes array.
37761 +        * Each element corresponds to a descriptor and indicates
37762 +        * original XferSize size value for the descriptor.
37763 +        */
37764 +       uint32_t *n_bytes;
37765 +
37766 +       /** Actual number of transfer descriptors in a list. */
37767 +       uint16_t ntd;
37768 +
37769 +       /** First activated isochronous transfer descriptor index. */
37770 +       uint8_t td_first;
37771 +       /** Last activated isochronous transfer descriptor index. */
37772 +       uint8_t td_last;
37773 +
37774 +       /** @} */
37775 +
37776 +
37777 +       uint16_t speed;
37778 +       uint16_t frame_usecs[8];
37779 +} dwc_otg_qh_t;
37780 +
37781 +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
37782 +
37783 +/**
37784 + * This structure holds the state of the HCD, including the non-periodic and
37785 + * periodic schedules.
37786 + */
37787 +struct dwc_otg_hcd {
37788 +       /** The DWC otg device pointer */
37789 +       struct dwc_otg_device *otg_dev;
37790 +       /** DWC OTG Core Interface Layer */
37791 +       dwc_otg_core_if_t *core_if;
37792 +
37793 +       /** Function HCD driver callbacks */
37794 +       struct dwc_otg_hcd_function_ops *fops;
37795 +
37796 +       /** Internal DWC HCD Flags */
37797 +       volatile union dwc_otg_hcd_internal_flags {
37798 +               uint32_t d32;
37799 +               struct {
37800 +                       unsigned port_connect_status_change:1;
37801 +                       unsigned port_connect_status:1;
37802 +                       unsigned port_reset_change:1;
37803 +                       unsigned port_enable_change:1;
37804 +                       unsigned port_suspend_change:1;
37805 +                       unsigned port_over_current_change:1;
37806 +                       unsigned port_l1_change:1;
37807 +                       unsigned reserved:26;
37808 +               } b;
37809 +       } flags;
37810 +
37811 +       /**
37812 +        * Inactive items in the non-periodic schedule. This is a list of
37813 +        * Queue Heads. Transfers associated with these Queue Heads are not
37814 +        * currently assigned to a host channel.
37815 +        */
37816 +       dwc_list_link_t non_periodic_sched_inactive;
37817 +
37818 +       /**
37819 +        * Active items in the non-periodic schedule. This is a list of
37820 +        * Queue Heads. Transfers associated with these Queue Heads are
37821 +        * currently assigned to a host channel.
37822 +        */
37823 +       dwc_list_link_t non_periodic_sched_active;
37824 +
37825 +       /**
37826 +        * Pointer to the next Queue Head to process in the active
37827 +        * non-periodic schedule.
37828 +        */
37829 +       dwc_list_link_t *non_periodic_qh_ptr;
37830 +
37831 +       /**
37832 +        * Inactive items in the periodic schedule. This is a list of QHs for
37833 +        * periodic transfers that are _not_ scheduled for the next frame.
37834 +        * Each QH in the list has an interval counter that determines when it
37835 +        * needs to be scheduled for execution. This scheduling mechanism
37836 +        * allows only a simple calculation for periodic bandwidth used (i.e.
37837 +        * must assume that all periodic transfers may need to execute in the
37838 +        * same frame). However, it greatly simplifies scheduling and should
37839 +        * be sufficient for the vast majority of OTG hosts, which need to
37840 +        * connect to a small number of peripherals at one time.
37841 +        *
37842 +        * Items move from this list to periodic_sched_ready when the QH
37843 +        * interval counter is 0 at SOF.
37844 +        */
37845 +       dwc_list_link_t periodic_sched_inactive;
37846 +
37847 +       /**
37848 +        * List of periodic QHs that are ready for execution in the next
37849 +        * frame, but have not yet been assigned to host channels.
37850 +        *
37851 +        * Items move from this list to periodic_sched_assigned as host
37852 +        * channels become available during the current frame.
37853 +        */
37854 +       dwc_list_link_t periodic_sched_ready;
37855 +
37856 +       /**
37857 +        * List of periodic QHs to be executed in the next frame that are
37858 +        * assigned to host channels.
37859 +        *
37860 +        * Items move from this list to periodic_sched_queued as the
37861 +        * transactions for the QH are queued to the DWC_otg controller.
37862 +        */
37863 +       dwc_list_link_t periodic_sched_assigned;
37864 +
37865 +       /**
37866 +        * List of periodic QHs that have been queued for execution.
37867 +        *
37868 +        * Items move from this list to either periodic_sched_inactive or
37869 +        * periodic_sched_ready when the channel associated with the transfer
37870 +        * is released. If the interval for the QH is 1, the item moves to
37871 +        * periodic_sched_ready because it must be rescheduled for the next
37872 +        * frame. Otherwise, the item moves to periodic_sched_inactive.
37873 +        */
37874 +       dwc_list_link_t periodic_sched_queued;
37875 +
37876 +       /**
37877 +        * Total bandwidth claimed so far for periodic transfers. This value
37878 +        * is in microseconds per (micro)frame. The assumption is that all
37879 +        * periodic transfers may occur in the same (micro)frame.
37880 +        */
37881 +       uint16_t periodic_usecs;
37882 +
37883 +       /**
37884 +        * Total bandwidth claimed so far for all periodic transfers
37885 +        * in a frame.
37886 +        * This will include a mixture of HS and FS transfers.
37887 +        * Units are microseconds per (micro)frame.
37888 +        * We have a budget per frame and have to schedule
37889 +        * transactions accordingly.
37890 +        * Watch out for the fact that things are actually scheduled for the
37891 +        * "next frame".
37892 +        */
37893 +       uint16_t                frame_usecs[8];
37894 +
37895 +
37896 +       /**
37897 +        * Frame number read from the core at SOF. The value ranges from 0 to
37898 +        * DWC_HFNUM_MAX_FRNUM.
37899 +        */
37900 +       uint16_t frame_number;
37901 +
37902 +       /**
37903 +        * Count of periodic QHs, if using several eps. For SOF enable/disable.
37904 +        */
37905 +       uint16_t periodic_qh_count;
37906 +
37907 +       /**
37908 +        * Free host channels in the controller. This is a list of
37909 +        * dwc_hc_t items.
37910 +        */
37911 +       struct hc_list free_hc_list;
37912 +       /**
37913 +        * Number of host channels assigned to periodic transfers. Currently
37914 +        * assuming that there is a dedicated host channel for each periodic
37915 +        * transaction and at least one host channel available for
37916 +        * non-periodic transactions.
37917 +        */
37918 +       int periodic_channels; /* microframe_schedule==0 */
37919 +
37920 +       /**
37921 +        * Number of host channels assigned to non-periodic transfers.
37922 +        */
37923 +       int non_periodic_channels; /* microframe_schedule==0 */
37924 +
37925 +       /**
37926 +        * Number of host channels assigned to non-periodic transfers.
37927 +        */
37928 +       int available_host_channels;
37929 +
37930 +       /**
37931 +        * Array of pointers to the host channel descriptors. Allows accessing
37932 +        * a host channel descriptor given the host channel number. This is
37933 +        * useful in interrupt handlers.
37934 +        */
37935 +       struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
37936 +
37937 +       /**
37938 +        * Buffer to use for any data received during the status phase of a
37939 +        * control transfer. Normally no data is transferred during the status
37940 +        * phase. This buffer is used as a bit bucket.
37941 +        */
37942 +       uint8_t *status_buf;
37943 +
37944 +       /**
37945 +        * DMA address for status_buf.
37946 +        */
37947 +       dma_addr_t status_buf_dma;
37948 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
37949 +
37950 +       /**
37951 +        * Connection timer. An OTG host must display a message if the device
37952 +        * does not connect. Started when the VBus power is turned on via
37953 +        * sysfs attribute "buspower".
37954 +        */
37955 +       dwc_timer_t *conn_timer;
37956 +
37957 +       /* Tasket to do a reset */
37958 +       dwc_tasklet_t *reset_tasklet;
37959 +
37960 +       /*  */
37961 +       dwc_spinlock_t *lock;
37962 +
37963 +       /**
37964 +        * Private data that could be used by OS wrapper.
37965 +        */
37966 +       void *priv;
37967 +
37968 +       uint8_t otg_port;
37969 +
37970 +       /** Frame List */
37971 +       uint32_t *frame_list;
37972 +
37973 +       /** Frame List DMA address */
37974 +       dma_addr_t frame_list_dma;
37975 +
37976 +#ifdef DEBUG
37977 +       uint32_t frrem_samples;
37978 +       uint64_t frrem_accum;
37979 +
37980 +       uint32_t hfnum_7_samples_a;
37981 +       uint64_t hfnum_7_frrem_accum_a;
37982 +       uint32_t hfnum_0_samples_a;
37983 +       uint64_t hfnum_0_frrem_accum_a;
37984 +       uint32_t hfnum_other_samples_a;
37985 +       uint64_t hfnum_other_frrem_accum_a;
37986 +
37987 +       uint32_t hfnum_7_samples_b;
37988 +       uint64_t hfnum_7_frrem_accum_b;
37989 +       uint32_t hfnum_0_samples_b;
37990 +       uint64_t hfnum_0_frrem_accum_b;
37991 +       uint32_t hfnum_other_samples_b;
37992 +       uint64_t hfnum_other_frrem_accum_b;
37993 +#endif
37994 +};
37995 +
37996 +/** @name Transaction Execution Functions */
37997 +/** @{ */
37998 +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
37999 +                                                                 * hcd);
38000 +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
38001 +                                          dwc_otg_transaction_type_e tr_type);
38002 +
38003 +/** @} */
38004 +
38005 +/** @name Interrupt Handler Functions */
38006 +/** @{ */
38007 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38008 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38009 +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
38010 +                                                        dwc_otg_hcd);
38011 +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
38012 +                                                       dwc_otg_hcd);
38013 +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
38014 +                                                          dwc_otg_hcd);
38015 +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
38016 +                                                          dwc_otg_hcd);
38017 +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38018 +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
38019 +                                                            dwc_otg_hcd);
38020 +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38021 +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38022 +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
38023 +                                           uint32_t num);
38024 +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
38025 +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
38026 +                                                      dwc_otg_hcd);
38027 +/** @} */
38028 +
38029 +/** @name Schedule Queue Functions */
38030 +/** @{ */
38031 +
38032 +/* Implemented in dwc_otg_hcd_queue.c */
38033 +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
38034 +                                          dwc_otg_hcd_urb_t * urb, int atomic_alloc);
38035 +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38036 +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38037 +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38038 +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38039 +                                     int sched_csplit);
38040 +
38041 +/** Remove and free a QH */
38042 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
38043 +                                                 dwc_otg_qh_t * qh)
38044 +{
38045 +       dwc_irqflags_t flags;
38046 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
38047 +       dwc_otg_hcd_qh_remove(hcd, qh);
38048 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
38049 +       dwc_otg_hcd_qh_free(hcd, qh);
38050 +}
38051 +
38052 +/** Allocates memory for a QH structure.
38053 + * @return Returns the memory allocate or NULL on error. */
38054 +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
38055 +{
38056 +       if (atomic_alloc)
38057 +               return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
38058 +       else
38059 +               return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
38060 +}
38061 +
38062 +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
38063 +                                            int atomic_alloc);
38064 +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
38065 +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
38066 +                              dwc_otg_qh_t ** qh, int atomic_alloc);
38067 +
38068 +/** Allocates memory for a QTD structure.
38069 + * @return Returns the memory allocate or NULL on error. */
38070 +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
38071 +{
38072 +       if (atomic_alloc)
38073 +               return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
38074 +       else
38075 +               return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
38076 +}
38077 +
38078 +/** Frees the memory for a QTD structure.  QTD should already be removed from
38079 + * list.
38080 + * @param qtd QTD to free.*/
38081 +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
38082 +{
38083 +       DWC_FREE(qtd);
38084 +}
38085 +
38086 +/** Removes a QTD from list.
38087 + * @param hcd HCD instance.
38088 + * @param qtd QTD to remove from list.
38089 + * @param qh QTD belongs to.
38090 + */
38091 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
38092 +                                         dwc_otg_qtd_t * qtd,
38093 +                                         dwc_otg_qh_t * qh)
38094 +{
38095 +       DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
38096 +}
38097 +
38098 +/** Remove and free a QTD
38099 +  * Need to disable IRQ and hold hcd lock while calling this function out of
38100 +  * interrupt servicing chain */
38101 +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
38102 +                                                  dwc_otg_qtd_t * qtd,
38103 +                                                  dwc_otg_qh_t * qh)
38104 +{
38105 +       dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
38106 +       dwc_otg_hcd_qtd_free(qtd);
38107 +}
38108 +
38109 +/** @} */
38110 +
38111 +/** @name Descriptor DMA Supporting Functions */
38112 +/** @{ */
38113 +
38114 +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38115 +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
38116 +                                          dwc_hc_t * hc,
38117 +                                          dwc_otg_hc_regs_t * hc_regs,
38118 +                                          dwc_otg_halt_status_e halt_status);
38119 +
38120 +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38121 +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38122 +
38123 +/** @} */
38124 +
38125 +/** @name Internal Functions */
38126 +/** @{ */
38127 +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
38128 +/** @} */
38129 +
38130 +#ifdef CONFIG_USB_DWC_OTG_LPM
38131 +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
38132 +                                          uint8_t devaddr);
38133 +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
38134 +#endif
38135 +
38136 +/** Gets the QH that contains the list_head */
38137 +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
38138 +
38139 +/** Gets the QTD that contains the list_head */
38140 +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
38141 +
38142 +/** Check if QH is non-periodic  */
38143 +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
38144 +                                    (_qh_ptr_->ep_type == UE_CONTROL))
38145 +
38146 +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
38147 +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
38148 +
38149 +/** Packet size for any kind of endpoint descriptor */
38150 +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
38151 +
38152 +/**
38153 + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
38154 + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
38155 + * frame number when the max frame number is reached.
38156 + */
38157 +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
38158 +{
38159 +       return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
38160 +           (DWC_HFNUM_MAX_FRNUM >> 1);
38161 +}
38162 +
38163 +/**
38164 + * Returns true if _frame1 is greater than _frame2. The comparison is done
38165 + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
38166 + * number when the max frame number is reached.
38167 + */
38168 +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
38169 +{
38170 +       return (frame1 != frame2) &&
38171 +           (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
38172 +            (DWC_HFNUM_MAX_FRNUM >> 1));
38173 +}
38174 +
38175 +/**
38176 + * Increments _frame by the amount specified by _inc. The addition is done
38177 + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
38178 + */
38179 +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
38180 +{
38181 +       return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
38182 +}
38183 +
38184 +static inline uint16_t dwc_full_frame_num(uint16_t frame)
38185 +{
38186 +       return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
38187 +}
38188 +
38189 +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
38190 +{
38191 +       return frame & 0x7;
38192 +}
38193 +
38194 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
38195 +                                 dwc_otg_hc_regs_t * hc_regs,
38196 +                                 dwc_otg_qtd_t * qtd);
38197 +
38198 +#ifdef DEBUG
38199 +/**
38200 + * Macro to sample the remaining PHY clocks left in the current frame. This
38201 + * may be used during debugging to determine the average time it takes to
38202 + * execute sections of code. There are two possible sample points, "a" and
38203 + * "b", so the _letter argument must be one of these values.
38204 + *
38205 + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
38206 + * example, "cat /sys/devices/lm0/hcd_frrem".
38207 + */
38208 +#define dwc_sample_frrem(_hcd, _qh, _letter) \
38209 +{ \
38210 +       hfnum_data_t hfnum; \
38211 +       dwc_otg_qtd_t *qtd; \
38212 +       qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
38213 +       if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
38214 +               hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
38215 +               switch (hfnum.b.frnum & 0x7) { \
38216 +               case 7: \
38217 +                       _hcd->hfnum_7_samples_##_letter++; \
38218 +                       _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
38219 +                       break; \
38220 +               case 0: \
38221 +                       _hcd->hfnum_0_samples_##_letter++; \
38222 +                       _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
38223 +                       break; \
38224 +               default: \
38225 +                       _hcd->hfnum_other_samples_##_letter++; \
38226 +                       _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
38227 +                       break; \
38228 +               } \
38229 +       } \
38230 +}
38231 +#else
38232 +#define dwc_sample_frrem(_hcd, _qh, _letter)
38233 +#endif
38234 +#endif
38235 +#endif /* DWC_DEVICE_ONLY */
38236 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
38237 new file mode 100644
38238 index 0000000..274967b
38239 --- /dev/null
38240 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
38241 @@ -0,0 +1,1133 @@
38242 +/*==========================================================================
38243 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
38244 + * $Revision: #10 $
38245 + * $Date: 2011/10/20 $
38246 + * $Change: 1869464 $
38247 + *
38248 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
38249 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
38250 + * otherwise expressly agreed to in writing between Synopsys and you.
38251 + *
38252 + * The Software IS NOT an item of Licensed Software or Licensed Product under
38253 + * any End User Software License Agreement or Agreement for Licensed Product
38254 + * with Synopsys or any supplement thereto. You are permitted to use and
38255 + * redistribute this Software in source and binary forms, with or without
38256 + * modification, provided that redistributions of source code must retain this
38257 + * notice. You may not view, use, disclose, copy or distribute this file or
38258 + * any information contained herein except pursuant to this license grant from
38259 + * Synopsys. If you do not agree with this notice, including the disclaimer
38260 + * below, then you are not authorized to use the Software.
38261 + *
38262 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
38263 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38264 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38265 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
38266 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38267 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38268 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38269 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38270 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38271 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38272 + * DAMAGE.
38273 + * ========================================================================== */
38274 +#ifndef DWC_DEVICE_ONLY
38275 +
38276 +/** @file
38277 + * This file contains Descriptor DMA support implementation for host mode.
38278 + */
38279 +
38280 +#include "dwc_otg_hcd.h"
38281 +#include "dwc_otg_regs.h"
38282 +
38283 +extern bool microframe_schedule;
38284 +
38285 +static inline uint8_t frame_list_idx(uint16_t frame)
38286 +{
38287 +       return (frame & (MAX_FRLIST_EN_NUM - 1));
38288 +}
38289 +
38290 +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
38291 +{
38292 +       return (idx + inc) &
38293 +           (((speed ==
38294 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38295 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38296 +}
38297 +
38298 +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
38299 +{
38300 +       return (idx - inc) &
38301 +           (((speed ==
38302 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38303 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38304 +}
38305 +
38306 +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
38307 +{
38308 +       return (((qh->ep_type == UE_ISOCHRONOUS)
38309 +                && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))
38310 +               ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);
38311 +}
38312 +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
38313 +{
38314 +       return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)
38315 +               ? ((qh->interval + 8 - 1) / 8)
38316 +               : qh->interval);
38317 +}
38318 +
38319 +static int desc_list_alloc(dwc_otg_qh_t * qh)
38320 +{
38321 +       int retval = 0;
38322 +
38323 +       qh->desc_list = (dwc_otg_host_dma_desc_t *)
38324 +           DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
38325 +                         &qh->desc_list_dma);
38326 +
38327 +       if (!qh->desc_list) {
38328 +               retval = -DWC_E_NO_MEMORY;
38329 +               DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
38330 +
38331 +       }
38332 +
38333 +       dwc_memset(qh->desc_list, 0x00,
38334 +                  sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38335 +
38336 +       qh->n_bytes =
38337 +           (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));
38338 +
38339 +       if (!qh->n_bytes) {
38340 +               retval = -DWC_E_NO_MEMORY;
38341 +               DWC_ERROR
38342 +                   ("%s: Failed to allocate array for descriptors' size actual values\n",
38343 +                    __func__);
38344 +
38345 +       }
38346 +       return retval;
38347 +
38348 +}
38349 +
38350 +static void desc_list_free(dwc_otg_qh_t * qh)
38351 +{
38352 +       if (qh->desc_list) {
38353 +               DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,
38354 +                            qh->desc_list_dma);
38355 +               qh->desc_list = NULL;
38356 +       }
38357 +
38358 +       if (qh->n_bytes) {
38359 +               DWC_FREE(qh->n_bytes);
38360 +               qh->n_bytes = NULL;
38361 +       }
38362 +}
38363 +
38364 +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
38365 +{
38366 +       int retval = 0;
38367 +       if (hcd->frame_list)
38368 +               return 0;
38369 +
38370 +       hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,
38371 +                                       &hcd->frame_list_dma);
38372 +       if (!hcd->frame_list) {
38373 +               retval = -DWC_E_NO_MEMORY;
38374 +               DWC_ERROR("%s: Frame List allocation failed\n", __func__);
38375 +       }
38376 +
38377 +       dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
38378 +
38379 +       return retval;
38380 +}
38381 +
38382 +static void frame_list_free(dwc_otg_hcd_t * hcd)
38383 +{
38384 +       if (!hcd->frame_list)
38385 +               return;
38386 +
38387 +       DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
38388 +       hcd->frame_list = NULL;
38389 +}
38390 +
38391 +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
38392 +{
38393 +
38394 +       hcfg_data_t hcfg;
38395 +
38396 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38397 +
38398 +       if (hcfg.b.perschedena) {
38399 +               /* already enabled */
38400 +               return;
38401 +       }
38402 +
38403 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,
38404 +                       hcd->frame_list_dma);
38405 +
38406 +       switch (fr_list_en) {
38407 +       case 64:
38408 +               hcfg.b.frlisten = 3;
38409 +               break;
38410 +       case 32:
38411 +               hcfg.b.frlisten = 2;
38412 +               break;
38413 +       case 16:
38414 +               hcfg.b.frlisten = 1;
38415 +               break;
38416 +       case 8:
38417 +               hcfg.b.frlisten = 0;
38418 +               break;
38419 +       default:
38420 +               break;
38421 +       }
38422 +
38423 +       hcfg.b.perschedena = 1;
38424 +
38425 +       DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
38426 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38427 +
38428 +}
38429 +
38430 +static void per_sched_disable(dwc_otg_hcd_t * hcd)
38431 +{
38432 +       hcfg_data_t hcfg;
38433 +
38434 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38435 +
38436 +       if (!hcfg.b.perschedena) {
38437 +               /* already disabled */
38438 +               return;
38439 +       }
38440 +       hcfg.b.perschedena = 0;
38441 +
38442 +       DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
38443 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38444 +}
38445 +
38446 +/*
38447 + * Activates/Deactivates FrameList entries for the channel
38448 + * based on endpoint servicing period.
38449 + */
38450 +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
38451 +{
38452 +       uint16_t i, j, inc;
38453 +       dwc_hc_t *hc = NULL;
38454 +
38455 +       if (!qh->channel) {
38456 +               DWC_ERROR("qh->channel = %p", qh->channel);
38457 +               return;
38458 +       }
38459 +
38460 +       if (!hcd) {
38461 +               DWC_ERROR("------hcd = %p", hcd);
38462 +               return;
38463 +       }
38464 +
38465 +       if (!hcd->frame_list) {
38466 +               DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);
38467 +               return;
38468 +       }
38469 +
38470 +       hc = qh->channel;
38471 +       inc = frame_incr_val(qh);
38472 +       if (qh->ep_type == UE_ISOCHRONOUS)
38473 +               i = frame_list_idx(qh->sched_frame);
38474 +       else
38475 +               i = 0;
38476 +
38477 +       j = i;
38478 +       do {
38479 +               if (enable)
38480 +                       hcd->frame_list[j] |= (1 << hc->hc_num);
38481 +               else
38482 +                       hcd->frame_list[j] &= ~(1 << hc->hc_num);
38483 +               j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
38484 +       }
38485 +       while (j != i);
38486 +       if (!enable)
38487 +               return;
38488 +       hc->schinfo = 0;
38489 +       if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
38490 +               j = 1;
38491 +               /* TODO - check this */
38492 +               inc = (8 + qh->interval - 1) / qh->interval;
38493 +               for (i = 0; i < inc; i++) {
38494 +                       hc->schinfo |= j;
38495 +                       j = j << qh->interval;
38496 +               }
38497 +       } else {
38498 +               hc->schinfo = 0xff;
38499 +       }
38500 +}
38501 +
38502 +#if 1
38503 +void dump_frame_list(dwc_otg_hcd_t * hcd)
38504 +{
38505 +       int i = 0;
38506 +       DWC_PRINTF("--FRAME LIST (hex) --\n");
38507 +       for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
38508 +               DWC_PRINTF("%x\t", hcd->frame_list[i]);
38509 +               if (!(i % 8) && i)
38510 +                       DWC_PRINTF("\n");
38511 +       }
38512 +       DWC_PRINTF("\n----\n");
38513 +
38514 +}
38515 +#endif
38516 +
38517 +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38518 +{
38519 +       dwc_irqflags_t flags;
38520 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
38521 +
38522 +       dwc_hc_t *hc = qh->channel;
38523 +       if (dwc_qh_is_non_per(qh)) {
38524 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
38525 +               if (!microframe_schedule)
38526 +                       hcd->non_periodic_channels--;
38527 +               else
38528 +                       hcd->available_host_channels++;
38529 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
38530 +       } else
38531 +               update_frame_list(hcd, qh, 0);
38532 +
38533 +       /*
38534 +        * The condition is added to prevent double cleanup try in case of device
38535 +        * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
38536 +        */
38537 +       if (hc->qh) {
38538 +               dwc_otg_hc_cleanup(hcd->core_if, hc);
38539 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
38540 +               hc->qh = NULL;
38541 +       }
38542 +
38543 +       qh->channel = NULL;
38544 +       qh->ntd = 0;
38545 +
38546 +       if (qh->desc_list) {
38547 +               dwc_memset(qh->desc_list, 0x00,
38548 +                          sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38549 +       }
38550 +       DWC_SPINLOCK_FREE(channel_lock);
38551 +}
38552 +
38553 +/**
38554 + * Initializes a QH structure's Descriptor DMA related members.
38555 + * Allocates memory for descriptor list.
38556 + * On first periodic QH, allocates memory for FrameList
38557 + * and enables periodic scheduling.
38558 + *
38559 + * @param hcd The HCD state structure for the DWC OTG controller.
38560 + * @param qh The QH to init.
38561 + *
38562 + * @return 0 if successful, negative error code otherwise.
38563 + */
38564 +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38565 +{
38566 +       int retval = 0;
38567 +
38568 +       if (qh->do_split) {
38569 +               DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
38570 +               return -1;
38571 +       }
38572 +
38573 +       retval = desc_list_alloc(qh);
38574 +
38575 +       if ((retval == 0)
38576 +           && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
38577 +               if (!hcd->frame_list) {
38578 +                       retval = frame_list_alloc(hcd);
38579 +                       /* Enable periodic schedule on first periodic QH */
38580 +                       if (retval == 0)
38581 +                               per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
38582 +               }
38583 +       }
38584 +
38585 +       qh->ntd = 0;
38586 +
38587 +       return retval;
38588 +}
38589 +
38590 +/**
38591 + * Frees descriptor list memory associated with the QH.
38592 + * If QH is periodic and the last, frees FrameList memory
38593 + * and disables periodic scheduling.
38594 + *
38595 + * @param hcd The HCD state structure for the DWC OTG controller.
38596 + * @param qh The QH to init.
38597 + */
38598 +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38599 +{
38600 +       desc_list_free(qh);
38601 +
38602 +       /*
38603 +        * Channel still assigned due to some reasons.
38604 +        * Seen on Isoc URB dequeue. Channel halted but no subsequent
38605 +        * ChHalted interrupt to release the channel. Afterwards
38606 +        * when it comes here from endpoint disable routine
38607 +        * channel remains assigned.
38608 +        */
38609 +       if (qh->channel)
38610 +               release_channel_ddma(hcd, qh);
38611 +
38612 +       if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)
38613 +           && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {
38614 +
38615 +               per_sched_disable(hcd);
38616 +               frame_list_free(hcd);
38617 +       }
38618 +}
38619 +
38620 +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
38621 +{
38622 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38623 +               /*
38624 +                * Descriptor set(8 descriptors) index
38625 +                * which is 8-aligned.
38626 +                */
38627 +               return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
38628 +       } else {
38629 +               return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
38630 +       }
38631 +}
38632 +
38633 +/*
38634 + * Determine starting frame for Isochronous transfer.
38635 + * Few frames skipped to prevent race condition with HC.
38636 + */
38637 +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38638 +                                  uint8_t * skip_frames)
38639 +{
38640 +       uint16_t frame = 0;
38641 +       hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
38642 +
38643 +       /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
38644 +
38645 +       /*
38646 +        * skip_frames is used to limit activated descriptors number
38647 +        * to avoid the situation when HC services the last activated
38648 +        * descriptor firstly.
38649 +        * Example for FS:
38650 +        * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
38651 +        * corresponding to curr_frame+1, the descriptor corresponding to frame 2
38652 +        * will be fetched. If the number of descriptors is max=64 (or greather) the
38653 +        * list will be fully programmed with Active descriptors and it is possible
38654 +        * case(rare) that the latest descriptor(considering rollback) corresponding
38655 +        * to frame 2 will be serviced first. HS case is more probable because, in fact,
38656 +        * up to 11 uframes(16 in the code) may be skipped.
38657 +        */
38658 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38659 +               /*
38660 +                * Consider uframe counter also, to start xfer asap.
38661 +                * If half of the frame elapsed skip 2 frames otherwise
38662 +                * just 1 frame.
38663 +                * Starting descriptor index must be 8-aligned, so
38664 +                * if the current frame is near to complete the next one
38665 +                * is skipped as well.
38666 +                */
38667 +
38668 +               if (dwc_micro_frame_num(hcd->frame_number) >= 5) {
38669 +                       *skip_frames = 2 * 8;
38670 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38671 +               } else {
38672 +                       *skip_frames = 1 * 8;
38673 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38674 +               }
38675 +
38676 +               frame = dwc_full_frame_num(frame);
38677 +       } else {
38678 +               /*
38679 +                * Two frames are skipped for FS - the current and the next.
38680 +                * But for descriptor programming, 1 frame(descriptor) is enough,
38681 +                * see example above.
38682 +                */
38683 +               *skip_frames = 1;
38684 +               frame = dwc_frame_num_inc(hcd->frame_number, 2);
38685 +       }
38686 +
38687 +       return frame;
38688 +}
38689 +
38690 +/*
38691 + * Calculate initial descriptor index for isochronous transfer
38692 + * based on scheduled frame.
38693 + */
38694 +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38695 +{
38696 +       uint16_t frame = 0, fr_idx, fr_idx_tmp;
38697 +       uint8_t skip_frames = 0;
38698 +       /*
38699 +        * With current ISOC processing algorithm the channel is being
38700 +        * released when no more QTDs in the list(qh->ntd == 0).
38701 +        * Thus this function is called only when qh->ntd == 0 and qh->channel == 0.
38702 +        *
38703 +        * So qh->channel != NULL branch is not used and just not removed from the
38704 +        * source file. It is required for another possible approach which is,
38705 +        * do not disable and release the channel when ISOC session completed,
38706 +        * just move QH to inactive schedule until new QTD arrives.
38707 +        * On new QTD, the QH moved back to 'ready' schedule,
38708 +        * starting frame and therefore starting desc_index are recalculated.
38709 +        * In this case channel is released only on ep_disable.
38710 +        */
38711 +
38712 +       /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
38713 +       if (qh->channel) {
38714 +               frame = calc_starting_frame(hcd, qh, &skip_frames);
38715 +               /*
38716 +                * Calculate initial descriptor index based on FrameList current bitmap
38717 +                * and servicing period.
38718 +                */
38719 +               fr_idx_tmp = frame_list_idx(frame);
38720 +               fr_idx =
38721 +                   (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -
38722 +                    fr_idx_tmp)
38723 +                   % frame_incr_val(qh);
38724 +               fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
38725 +       } else {
38726 +               qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);
38727 +               fr_idx = frame_list_idx(qh->sched_frame);
38728 +       }
38729 +
38730 +       qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);
38731 +
38732 +       return skip_frames;
38733 +}
38734 +
38735 +#define        ISOC_URB_GIVEBACK_ASAP
38736 +
38737 +#define MAX_ISOC_XFER_SIZE_FS 1023
38738 +#define MAX_ISOC_XFER_SIZE_HS 3072
38739 +#define DESCNUM_THRESHOLD 4
38740 +
38741 +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38742 +                              uint8_t skip_frames)
38743 +{
38744 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
38745 +       dwc_otg_qtd_t *qtd;
38746 +       dwc_otg_host_dma_desc_t *dma_desc;
38747 +       uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
38748 +
38749 +       idx = qh->td_last;
38750 +       inc = qh->interval;
38751 +       n_desc = 0;
38752 +
38753 +       ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
38754 +       if (skip_frames && !qh->channel)
38755 +               ntd_max = ntd_max - skip_frames / qh->interval;
38756 +
38757 +       max_xfer_size =
38758 +           (qh->dev_speed ==
38759 +            DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :
38760 +           MAX_ISOC_XFER_SIZE_FS;
38761 +
38762 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38763 +               while ((qh->ntd < ntd_max)
38764 +                      && (qtd->isoc_frame_index_last <
38765 +                          qtd->urb->packet_count)) {
38766 +
38767 +                       dma_desc = &qh->desc_list[idx];
38768 +                       dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
38769 +
38770 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
38771 +
38772 +                       if (frame_desc->length > max_xfer_size)
38773 +                               qh->n_bytes[idx] = max_xfer_size;
38774 +                       else
38775 +                               qh->n_bytes[idx] = frame_desc->length;
38776 +                       dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
38777 +                       dma_desc->status.b_isoc.a = 1;
38778 +                       dma_desc->status.b_isoc.sts = 0;
38779 +
38780 +                       dma_desc->buf = qtd->urb->dma + frame_desc->offset;
38781 +
38782 +                       qh->ntd++;
38783 +
38784 +                       qtd->isoc_frame_index_last++;
38785 +
38786 +#ifdef ISOC_URB_GIVEBACK_ASAP
38787 +                       /*
38788 +                        * Set IOC for each descriptor corresponding to the
38789 +                        * last frame of the URB.
38790 +                        */
38791 +                       if (qtd->isoc_frame_index_last ==
38792 +                           qtd->urb->packet_count)
38793 +                               dma_desc->status.b_isoc.ioc = 1;
38794 +
38795 +#endif
38796 +                       idx = desclist_idx_inc(idx, inc, qh->dev_speed);
38797 +                       n_desc++;
38798 +
38799 +               }
38800 +               qtd->in_process = 1;
38801 +       }
38802 +
38803 +       qh->td_last = idx;
38804 +
38805 +#ifdef ISOC_URB_GIVEBACK_ASAP
38806 +       /* Set IOC for the last descriptor if descriptor list is full */
38807 +       if (qh->ntd == ntd_max) {
38808 +               idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38809 +               qh->desc_list[idx].status.b_isoc.ioc = 1;
38810 +       }
38811 +#else
38812 +       /*
38813 +        * Set IOC bit only for one descriptor.
38814 +        * Always try to be ahead of HW processing,
38815 +        * i.e. on IOC generation driver activates next descriptors but
38816 +        * core continues to process descriptors followed the one with IOC set.
38817 +        */
38818 +
38819 +       if (n_desc > DESCNUM_THRESHOLD) {
38820 +               /*
38821 +                * Move IOC "up". Required even if there is only one QTD
38822 +                * in the list, cause QTDs migth continue to be queued,
38823 +                * but during the activation it was only one queued.
38824 +                * Actually more than one QTD might be in the list if this function called
38825 +                * from XferCompletion - QTDs was queued during HW processing of the previous
38826 +                * descriptor chunk.
38827 +                */
38828 +               idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
38829 +       } else {
38830 +               /*
38831 +                * Set the IOC for the latest descriptor
38832 +                * if either number of descriptor is not greather than threshold
38833 +                * or no more new descriptors activated.
38834 +                */
38835 +               idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38836 +       }
38837 +
38838 +       qh->desc_list[idx].status.b_isoc.ioc = 1;
38839 +#endif
38840 +}
38841 +
38842 +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38843 +{
38844 +
38845 +       dwc_hc_t *hc;
38846 +       dwc_otg_host_dma_desc_t *dma_desc;
38847 +       dwc_otg_qtd_t *qtd;
38848 +       int num_packets, len, n_desc = 0;
38849 +
38850 +       hc = qh->channel;
38851 +
38852 +       /*
38853 +        * Start with hc->xfer_buff initialized in
38854 +        * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
38855 +        * this pointer re-assigned to the buffer of the currently processed QTD.
38856 +        * For non-SG request there is always one QTD active.
38857 +        */
38858 +
38859 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38860 +
38861 +               if (n_desc) {
38862 +                       /* SG request - more than 1 QTDs */
38863 +                       hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
38864 +                       hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
38865 +               }
38866 +
38867 +               qtd->n_desc = 0;
38868 +
38869 +               do {
38870 +                       dma_desc = &qh->desc_list[n_desc];
38871 +                       len = hc->xfer_len;
38872 +
38873 +                       if (len > MAX_DMA_DESC_SIZE)
38874 +                               len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
38875 +
38876 +                       if (hc->ep_is_in) {
38877 +                               if (len > 0) {
38878 +                                       num_packets = (len + hc->max_packet - 1) / hc->max_packet;
38879 +                               } else {
38880 +                                       /* Need 1 packet for transfer length of 0. */
38881 +                                       num_packets = 1;
38882 +                               }
38883 +                               /* Always program an integral # of max packets for IN transfers. */
38884 +                               len = num_packets * hc->max_packet;
38885 +                       }
38886 +
38887 +                       dma_desc->status.b.n_bytes = len;
38888 +
38889 +                       qh->n_bytes[n_desc] = len;
38890 +
38891 +                       if ((qh->ep_type == UE_CONTROL)
38892 +                           && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
38893 +                               dma_desc->status.b.sup = 1;     /* Setup Packet */
38894 +
38895 +                       dma_desc->status.b.a = 1;       /* Active descriptor */
38896 +                       dma_desc->status.b.sts = 0;
38897 +
38898 +                       dma_desc->buf =
38899 +                           ((unsigned long)hc->xfer_buff & 0xffffffff);
38900 +
38901 +                       /*
38902 +                        * Last descriptor(or single) of IN transfer
38903 +                        * with actual size less than MaxPacket.
38904 +                        */
38905 +                       if (len > hc->xfer_len) {
38906 +                               hc->xfer_len = 0;
38907 +                       } else {
38908 +                               hc->xfer_buff += len;
38909 +                               hc->xfer_len -= len;
38910 +                       }
38911 +
38912 +                       qtd->n_desc++;
38913 +                       n_desc++;
38914 +               }
38915 +               while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
38916 +
38917 +
38918 +               qtd->in_process = 1;
38919 +
38920 +               if (qh->ep_type == UE_CONTROL)
38921 +                       break;
38922 +
38923 +               if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
38924 +                       break;
38925 +       }
38926 +
38927 +       if (n_desc) {
38928 +               /* Request Transfer Complete interrupt for the last descriptor */
38929 +               qh->desc_list[n_desc - 1].status.b.ioc = 1;
38930 +               /* End of List indicator */
38931 +               qh->desc_list[n_desc - 1].status.b.eol = 1;
38932 +
38933 +               hc->ntd = n_desc;
38934 +       }
38935 +}
38936 +
38937 +/**
38938 + * For Control and Bulk endpoints initializes descriptor list
38939 + * and starts the transfer.
38940 + *
38941 + * For Interrupt and Isochronous endpoints initializes descriptor list
38942 + * then updates FrameList, marking appropriate entries as active.
38943 + * In case of Isochronous, the starting descriptor index is calculated based
38944 + * on the scheduled frame, but only on the first transfer descriptor within a session.
38945 + * Then starts the transfer via enabling the channel.
38946 + * For Isochronous endpoint the channel is not halted on XferComplete
38947 + * interrupt so remains assigned to the endpoint(QH) until session is done.
38948 + *
38949 + * @param hcd The HCD state structure for the DWC OTG controller.
38950 + * @param qh The QH to init.
38951 + *
38952 + * @return 0 if successful, negative error code otherwise.
38953 + */
38954 +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38955 +{
38956 +       /* Channel is already assigned */
38957 +       dwc_hc_t *hc = qh->channel;
38958 +       uint8_t skip_frames = 0;
38959 +
38960 +       switch (hc->ep_type) {
38961 +       case DWC_OTG_EP_TYPE_CONTROL:
38962 +       case DWC_OTG_EP_TYPE_BULK:
38963 +               init_non_isoc_dma_desc(hcd, qh);
38964 +
38965 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38966 +               break;
38967 +       case DWC_OTG_EP_TYPE_INTR:
38968 +               init_non_isoc_dma_desc(hcd, qh);
38969 +
38970 +               update_frame_list(hcd, qh, 1);
38971 +
38972 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38973 +               break;
38974 +       case DWC_OTG_EP_TYPE_ISOC:
38975 +
38976 +               if (!qh->ntd)
38977 +                       skip_frames = recalc_initial_desc_idx(hcd, qh);
38978 +
38979 +               init_isoc_dma_desc(hcd, qh, skip_frames);
38980 +
38981 +               if (!hc->xfer_started) {
38982 +
38983 +                       update_frame_list(hcd, qh, 1);
38984 +
38985 +                       /*
38986 +                        * Always set to max, instead of actual size.
38987 +                        * Otherwise ntd will be changed with
38988 +                        * channel being enabled. Not recommended.
38989 +                        *
38990 +                        */
38991 +                       hc->ntd = max_desc_num(qh);
38992 +                       /* Enable channel only once for ISOC */
38993 +                       dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38994 +               }
38995 +
38996 +               break;
38997 +       default:
38998 +
38999 +               break;
39000 +       }
39001 +}
39002 +
39003 +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
39004 +                                   dwc_hc_t * hc,
39005 +                                   dwc_otg_hc_regs_t * hc_regs,
39006 +                                   dwc_otg_halt_status_e halt_status)
39007 +{
39008 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
39009 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
39010 +       dwc_otg_qh_t *qh;
39011 +       dwc_otg_host_dma_desc_t *dma_desc;
39012 +       uint16_t idx, remain;
39013 +       uint8_t urb_compl;
39014 +
39015 +       qh = hc->qh;
39016 +       idx = qh->td_first;
39017 +
39018 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39019 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
39020 +                   qtd->in_process = 0;
39021 +               return;
39022 +       } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||
39023 +                  (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
39024 +               /*
39025 +                * Channel is halted in these error cases.
39026 +                * Considered as serious issues.
39027 +                * Complete all URBs marking all frames as failed,
39028 +                * irrespective whether some of the descriptors(frames) succeeded or no.
39029 +                * Pass error code to completion routine as well, to
39030 +                * update urb->status, some of class drivers might use it to stop
39031 +                * queing transfer requests.
39032 +                */
39033 +               int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)
39034 +                   ? (-DWC_E_IO)
39035 +                   : (-DWC_E_OVERFLOW);
39036 +
39037 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39038 +                       for (idx = 0; idx < qtd->urb->packet_count; idx++) {
39039 +                               frame_desc = &qtd->urb->iso_descs[idx];
39040 +                               frame_desc->status = err;
39041 +                       }
39042 +                       hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
39043 +                       dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39044 +               }
39045 +               return;
39046 +       }
39047 +
39048 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39049 +
39050 +               if (!qtd->in_process)
39051 +                       break;
39052 +
39053 +               urb_compl = 0;
39054 +
39055 +               do {
39056 +
39057 +                       dma_desc = &qh->desc_list[idx];
39058 +
39059 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
39060 +                       remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
39061 +
39062 +                       if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
39063 +                               /*
39064 +                                * XactError or, unable to complete all the transactions
39065 +                                * in the scheduled micro-frame/frame,
39066 +                                * both indicated by DMA_DESC_STS_PKTERR.
39067 +                                */
39068 +                               qtd->urb->error_count++;
39069 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
39070 +                               frame_desc->status = -DWC_E_PROTOCOL;
39071 +                       } else {
39072 +                               /* Success */
39073 +
39074 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
39075 +                               frame_desc->status = 0;
39076 +                       }
39077 +
39078 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
39079 +                               /*
39080 +                                * urb->status is not used for isoc transfers here.
39081 +                                * The individual frame_desc status are used instead.
39082 +                                */
39083 +
39084 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
39085 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39086 +
39087 +                               /*
39088 +                                * This check is necessary because urb_dequeue can be called
39089 +                                * from urb complete callback(sound driver example).
39090 +                                * All pending URBs are dequeued there, so no need for
39091 +                                * further processing.
39092 +                                */
39093 +                               if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39094 +                                       return;
39095 +                               }
39096 +
39097 +                               urb_compl = 1;
39098 +
39099 +                       }
39100 +
39101 +                       qh->ntd--;
39102 +
39103 +                       /* Stop if IOC requested descriptor reached */
39104 +                       if (dma_desc->status.b_isoc.ioc) {
39105 +                               idx = desclist_idx_inc(idx, qh->interval, hc->speed);
39106 +                               goto stop_scan;
39107 +                       }
39108 +
39109 +                       idx = desclist_idx_inc(idx, qh->interval, hc->speed);
39110 +
39111 +                       if (urb_compl)
39112 +                               break;
39113 +               }
39114 +               while (idx != qh->td_first);
39115 +       }
39116 +stop_scan:
39117 +       qh->td_first = idx;
39118 +}
39119 +
39120 +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
39121 +                                      dwc_hc_t * hc,
39122 +                                      dwc_otg_qtd_t * qtd,
39123 +                                      dwc_otg_host_dma_desc_t * dma_desc,
39124 +                                      dwc_otg_halt_status_e halt_status,
39125 +                                      uint32_t n_bytes, uint8_t * xfer_done)
39126 +{
39127 +
39128 +       uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
39129 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
39130 +
39131 +       if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
39132 +               urb->status = -DWC_E_IO;
39133 +               return 1;
39134 +       }
39135 +       if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
39136 +               switch (halt_status) {
39137 +               case DWC_OTG_HC_XFER_STALL:
39138 +                       urb->status = -DWC_E_PIPE;
39139 +                       break;
39140 +               case DWC_OTG_HC_XFER_BABBLE_ERR:
39141 +                       urb->status = -DWC_E_OVERFLOW;
39142 +                       break;
39143 +               case DWC_OTG_HC_XFER_XACT_ERR:
39144 +                       urb->status = -DWC_E_PROTOCOL;
39145 +                       break;
39146 +               default:
39147 +                       DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
39148 +                                 halt_status);
39149 +                       break;
39150 +               }
39151 +               return 1;
39152 +       }
39153 +
39154 +       if (dma_desc->status.b.a == 1) {
39155 +               DWC_DEBUGPL(DBG_HCDV,
39156 +                           "Active descriptor encountered on channel %d\n",
39157 +                           hc->hc_num);
39158 +               return 0;
39159 +       }
39160 +
39161 +       if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
39162 +               if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39163 +                       urb->actual_length += n_bytes - remain;
39164 +                       if (remain || urb->actual_length == urb->length) {
39165 +                               /*
39166 +                                * For Control Data stage do not set urb->status=0 to prevent
39167 +                                * URB callback. Set it when Status phase done. See below.
39168 +                                */
39169 +                               *xfer_done = 1;
39170 +                       }
39171 +
39172 +               } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
39173 +                       urb->status = 0;
39174 +                       *xfer_done = 1;
39175 +               }
39176 +               /* No handling for SETUP stage */
39177 +       } else {
39178 +               /* BULK and INTR */
39179 +               urb->actual_length += n_bytes - remain;
39180 +               if (remain || urb->actual_length == urb->length) {
39181 +                       urb->status = 0;
39182 +                       *xfer_done = 1;
39183 +               }
39184 +       }
39185 +
39186 +       return 0;
39187 +}
39188 +
39189 +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
39190 +                                       dwc_hc_t * hc,
39191 +                                       dwc_otg_hc_regs_t * hc_regs,
39192 +                                       dwc_otg_halt_status_e halt_status)
39193 +{
39194 +       dwc_otg_hcd_urb_t *urb = NULL;
39195 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
39196 +       dwc_otg_qh_t *qh;
39197 +       dwc_otg_host_dma_desc_t *dma_desc;
39198 +       uint32_t n_bytes, n_desc, i;
39199 +       uint8_t failed = 0, xfer_done;
39200 +
39201 +       n_desc = 0;
39202 +
39203 +       qh = hc->qh;
39204 +
39205 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39206 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39207 +                       qtd->in_process = 0;
39208 +               }
39209 +               return;
39210 +       }
39211 +
39212 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
39213 +
39214 +               urb = qtd->urb;
39215 +
39216 +               n_bytes = 0;
39217 +               xfer_done = 0;
39218 +
39219 +               for (i = 0; i < qtd->n_desc; i++) {
39220 +                       dma_desc = &qh->desc_list[n_desc];
39221 +
39222 +                       n_bytes = qh->n_bytes[n_desc];
39223 +
39224 +                       failed =
39225 +                           update_non_isoc_urb_state_ddma(hcd, hc, qtd,
39226 +                                                          dma_desc,
39227 +                                                          halt_status, n_bytes,
39228 +                                                          &xfer_done);
39229 +
39230 +                       if (failed
39231 +                           || (xfer_done
39232 +                               && (urb->status != -DWC_E_IN_PROGRESS))) {
39233 +
39234 +                               hcd->fops->complete(hcd, urb->priv, urb,
39235 +                                                   urb->status);
39236 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39237 +
39238 +                               if (failed)
39239 +                                       goto stop_scan;
39240 +                       } else if (qh->ep_type == UE_CONTROL) {
39241 +                               if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
39242 +                                       if (urb->length > 0) {
39243 +                                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
39244 +                                       } else {
39245 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39246 +                                       }
39247 +                                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction done\n");
39248 +                               } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39249 +                                       if (xfer_done) {
39250 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39251 +                                               DWC_DEBUGPL(DBG_HCDV, "  Control data transfer done\n");
39252 +                                       } else if (i + 1 == qtd->n_desc) {
39253 +                                               /*
39254 +                                                * Last descriptor for Control data stage which is
39255 +                                                * not completed yet.
39256 +                                                */
39257 +                                               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39258 +                                       }
39259 +                               }
39260 +                       }
39261 +
39262 +                       n_desc++;
39263 +               }
39264 +
39265 +       }
39266 +
39267 +stop_scan:
39268 +
39269 +       if (qh->ep_type != UE_CONTROL) {
39270 +               /*
39271 +                * Resetting the data toggle for bulk
39272 +                * and interrupt endpoints in case of stall. See handle_hc_stall_intr()
39273 +                */
39274 +               if (halt_status == DWC_OTG_HC_XFER_STALL)
39275 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
39276 +               else
39277 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39278 +       }
39279 +
39280 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39281 +               hcint_data_t hcint;
39282 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
39283 +               if (hcint.b.nyet) {
39284 +                       /*
39285 +                        * Got a NYET on the last transaction of the transfer. It
39286 +                        * means that the endpoint should be in the PING state at the
39287 +                        * beginning of the next transfer.
39288 +                        */
39289 +                       qh->ping_state = 1;
39290 +                       clear_hc_int(hc_regs, nyet);
39291 +               }
39292 +
39293 +       }
39294 +
39295 +}
39296 +
39297 +/**
39298 + * This function is called from interrupt handlers.
39299 + * Scans the descriptor list, updates URB's status and
39300 + * calls completion routine for the URB if it's done.
39301 + * Releases the channel to be used by other transfers.
39302 + * In case of Isochronous endpoint the channel is not halted until
39303 + * the end of the session, i.e. QTD list is empty.
39304 + * If periodic channel released the FrameList is updated accordingly.
39305 + *
39306 + * Calls transaction selection routines to activate pending transfers.
39307 + *
39308 + * @param hcd The HCD state structure for the DWC OTG controller.
39309 + * @param hc Host channel, the transfer is completed on.
39310 + * @param hc_regs Host channel registers.
39311 + * @param halt_status Reason the channel is being halted,
39312 + *                   or just XferComplete for isochronous transfer
39313 + */
39314 +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
39315 +                                   dwc_hc_t * hc,
39316 +                                   dwc_otg_hc_regs_t * hc_regs,
39317 +                                   dwc_otg_halt_status_e halt_status)
39318 +{
39319 +       uint8_t continue_isoc_xfer = 0;
39320 +       dwc_otg_transaction_type_e tr_type;
39321 +       dwc_otg_qh_t *qh = hc->qh;
39322 +
39323 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
39324 +
39325 +               complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39326 +
39327 +               /* Release the channel if halted or session completed */
39328 +               if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
39329 +                   DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39330 +
39331 +                       /* Halt the channel if session completed */
39332 +                       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39333 +                               dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
39334 +                       }
39335 +
39336 +                       release_channel_ddma(hcd, qh);
39337 +                       dwc_otg_hcd_qh_remove(hcd, qh);
39338 +               } else {
39339 +                       /* Keep in assigned schedule to continue transfer */
39340 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
39341 +                                          &qh->qh_list_entry);
39342 +                       continue_isoc_xfer = 1;
39343 +
39344 +               }
39345 +               /** @todo Consider the case when period exceeds FrameList size.
39346 +                *  Frame Rollover interrupt should be used.
39347 +                */
39348 +       } else {
39349 +               /* Scan descriptor list to complete the URB(s), then release the channel */
39350 +               complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39351 +
39352 +               release_channel_ddma(hcd, qh);
39353 +               dwc_otg_hcd_qh_remove(hcd, qh);
39354 +
39355 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39356 +                       /* Add back to inactive non-periodic schedule on normal completion */
39357 +                       dwc_otg_hcd_qh_add(hcd, qh);
39358 +               }
39359 +
39360 +       }
39361 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
39362 +       if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
39363 +               if (continue_isoc_xfer) {
39364 +                       if (tr_type == DWC_OTG_TRANSACTION_NONE) {
39365 +                               tr_type = DWC_OTG_TRANSACTION_PERIODIC;
39366 +                       } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
39367 +                               tr_type = DWC_OTG_TRANSACTION_ALL;
39368 +                       }
39369 +               }
39370 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
39371 +       }
39372 +}
39373 +
39374 +#endif /* DWC_DEVICE_ONLY */
39375 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39376 new file mode 100644
39377 index 0000000..4823167
39378 --- /dev/null
39379 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39380 @@ -0,0 +1,412 @@
39381 +/* ==========================================================================
39382 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
39383 + * $Revision: #12 $
39384 + * $Date: 2011/10/26 $
39385 + * $Change: 1873028 $
39386 + *
39387 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39388 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39389 + * otherwise expressly agreed to in writing between Synopsys and you.
39390 + *
39391 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39392 + * any End User Software License Agreement or Agreement for Licensed Product
39393 + * with Synopsys or any supplement thereto. You are permitted to use and
39394 + * redistribute this Software in source and binary forms, with or without
39395 + * modification, provided that redistributions of source code must retain this
39396 + * notice. You may not view, use, disclose, copy or distribute this file or
39397 + * any information contained herein except pursuant to this license grant from
39398 + * Synopsys. If you do not agree with this notice, including the disclaimer
39399 + * below, then you are not authorized to use the Software.
39400 + *
39401 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39402 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39403 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39404 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39405 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39406 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39407 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39408 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39409 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39410 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39411 + * DAMAGE.
39412 + * ========================================================================== */
39413 +#ifndef DWC_DEVICE_ONLY
39414 +#ifndef __DWC_HCD_IF_H__
39415 +#define __DWC_HCD_IF_H__
39416 +
39417 +#include "dwc_otg_core_if.h"
39418 +
39419 +/** @file
39420 + * This file defines DWC_OTG HCD Core API.
39421 + */
39422 +
39423 +struct dwc_otg_hcd;
39424 +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
39425 +
39426 +struct dwc_otg_hcd_urb;
39427 +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
39428 +
39429 +/** @name HCD Function Driver Callbacks */
39430 +/** @{ */
39431 +
39432 +/** This function is called whenever core switches to host mode. */
39433 +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
39434 +
39435 +/** This function is called when device has been disconnected */
39436 +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
39437 +
39438 +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
39439 +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39440 +                                                  void *urb_handle,
39441 +                                                  uint32_t * hub_addr,
39442 +                                                  uint32_t * port_addr);
39443 +/** Via this function HCD core gets device speed */
39444 +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39445 +                                               void *urb_handle);
39446 +
39447 +/** This function is called when urb is completed */
39448 +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
39449 +                                             void *urb_handle,
39450 +                                             dwc_otg_hcd_urb_t * dwc_otg_urb,
39451 +                                             int32_t status);
39452 +
39453 +/** Via this function HCD core gets b_hnp_enable parameter */
39454 +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
39455 +
39456 +struct dwc_otg_hcd_function_ops {
39457 +       dwc_otg_hcd_start_cb_t start;
39458 +       dwc_otg_hcd_disconnect_cb_t disconnect;
39459 +       dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
39460 +       dwc_otg_hcd_speed_from_urb_cb_t speed;
39461 +       dwc_otg_hcd_complete_urb_cb_t complete;
39462 +       dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
39463 +};
39464 +/** @} */
39465 +
39466 +/** @name HCD Core API */
39467 +/** @{ */
39468 +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
39469 +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
39470 +
39471 +/** This function should be called to initiate HCD Core.
39472 + *
39473 + * @param hcd The HCD
39474 + * @param core_if The DWC_OTG Core
39475 + *
39476 + * Returns -DWC_E_NO_MEMORY if no enough memory.
39477 + * Returns 0 on success
39478 + */
39479 +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
39480 +
39481 +/** Frees HCD
39482 + *
39483 + * @param hcd The HCD
39484 + */
39485 +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
39486 +
39487 +/** This function should be called on every hardware interrupt.
39488 + *
39489 + * @param dwc_otg_hcd The HCD
39490 + *
39491 + * Returns non zero if interrupt is handled
39492 + * Return 0 if interrupt is not handled
39493 + */
39494 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
39495 +
39496 +/**
39497 + * Returns private data set by
39498 + * dwc_otg_hcd_set_priv_data function.
39499 + *
39500 + * @param hcd The HCD
39501 + */
39502 +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
39503 +
39504 +/**
39505 + * Set private data.
39506 + *
39507 + * @param hcd The HCD
39508 + * @param priv_data pointer to be stored in private data
39509 + */
39510 +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
39511 +
39512 +/**
39513 + * This function initializes the HCD Core.
39514 + *
39515 + * @param hcd The HCD
39516 + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
39517 + *
39518 + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
39519 + * Returns 0 on success
39520 + */
39521 +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
39522 +                            struct dwc_otg_hcd_function_ops *fops);
39523 +
39524 +/**
39525 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
39526 + * stopped.
39527 + *
39528 + * @param hcd The HCD
39529 + */
39530 +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
39531 +
39532 +/**
39533 + * Handles hub class-specific requests.
39534 + *
39535 + * @param dwc_otg_hcd The HCD
39536 + * @param typeReq Request Type
39537 + * @param wValue wValue from control request
39538 + * @param wIndex wIndex from control request
39539 + * @param buf data buffer
39540 + * @param wLength data buffer length
39541 + *
39542 + * Returns -DWC_E_INVALID if invalid argument is passed
39543 + * Returns 0 on success
39544 + */
39545 +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
39546 +                                  uint16_t typeReq, uint16_t wValue,
39547 +                                  uint16_t wIndex, uint8_t * buf,
39548 +                                  uint16_t wLength);
39549 +
39550 +/**
39551 + * Returns otg port number.
39552 + *
39553 + * @param hcd The HCD
39554 + */
39555 +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
39556 +
39557 +/**
39558 + * Returns OTG version - either 1.3 or 2.0.
39559 + *
39560 + * @param core_if The core_if structure pointer
39561 + */
39562 +extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
39563 +
39564 +/**
39565 + * Returns 1 if currently core is acting as B host, and 0 otherwise.
39566 + *
39567 + * @param hcd The HCD
39568 + */
39569 +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
39570 +
39571 +/**
39572 + * Returns current frame number.
39573 + *
39574 + * @param hcd The HCD
39575 + */
39576 +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
39577 +
39578 +/**
39579 + * Dumps hcd state.
39580 + *
39581 + * @param hcd The HCD
39582 + */
39583 +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
39584 +
39585 +/**
39586 + * Dump the average frame remaining at SOF. This can be used to
39587 + * determine average interrupt latency. Frame remaining is also shown for
39588 + * start transfer and two additional sample points.
39589 + * Currently this function is not implemented.
39590 + *
39591 + * @param hcd The HCD
39592 + */
39593 +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
39594 +
39595 +/**
39596 + * Sends LPM transaction to the local device.
39597 + *
39598 + * @param hcd The HCD
39599 + * @param devaddr Device Address
39600 + * @param hird Host initiated resume duration
39601 + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
39602 + *
39603 + * Returns negative value if sending LPM transaction was not succeeded.
39604 + * Returns 0 on success.
39605 + */
39606 +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
39607 +                               uint8_t hird, uint8_t bRemoteWake);
39608 +
39609 +/* URB interface */
39610 +
39611 +/**
39612 + * Allocates memory for dwc_otg_hcd_urb structure.
39613 + * Allocated memory should be freed by call of DWC_FREE.
39614 + *
39615 + * @param hcd The HCD
39616 + * @param iso_desc_count Count of ISOC descriptors
39617 + * @param atomic_alloc Specefies whether to perform atomic allocation.
39618 + */
39619 +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
39620 +                                               int iso_desc_count,
39621 +                                               int atomic_alloc);
39622 +
39623 +/**
39624 + * Set pipe information in URB.
39625 + *
39626 + * @param hcd_urb DWC_OTG URB
39627 + * @param devaddr Device Address
39628 + * @param ep_num Endpoint Number
39629 + * @param ep_type Endpoint Type
39630 + * @param ep_dir Endpoint Direction
39631 + * @param mps Max Packet Size
39632 + */
39633 +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
39634 +                                        uint8_t devaddr, uint8_t ep_num,
39635 +                                        uint8_t ep_type, uint8_t ep_dir,
39636 +                                        uint16_t mps);
39637 +
39638 +/* Transfer flags */
39639 +#define URB_GIVEBACK_ASAP 0x1
39640 +#define URB_SEND_ZERO_PACKET 0x2
39641 +
39642 +/**
39643 + * Sets dwc_otg_hcd_urb parameters.
39644 + *
39645 + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
39646 + * @param urb_handle Unique handle for request, this will be passed back
39647 + * to function driver in completion callback.
39648 + * @param buf The buffer for the data
39649 + * @param dma The DMA buffer for the data
39650 + * @param buflen Transfer length
39651 + * @param sp Buffer for setup data
39652 + * @param sp_dma DMA address of setup data buffer
39653 + * @param flags Transfer flags
39654 + * @param interval Polling interval for interrupt or isochronous transfers.
39655 + */
39656 +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
39657 +                                      void *urb_handle, void *buf,
39658 +                                      dwc_dma_t dma, uint32_t buflen, void *sp,
39659 +                                      dwc_dma_t sp_dma, uint32_t flags,
39660 +                                      uint16_t interval);
39661 +
39662 +/** Gets status from dwc_otg_hcd_urb
39663 + *
39664 + * @param dwc_otg_urb DWC_OTG URB
39665 + */
39666 +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
39667 +
39668 +/** Gets actual length from dwc_otg_hcd_urb
39669 + *
39670 + * @param dwc_otg_urb DWC_OTG URB
39671 + */
39672 +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
39673 +                                                 dwc_otg_urb);
39674 +
39675 +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
39676 + *
39677 + * @param dwc_otg_urb DWC_OTG URB
39678 + */
39679 +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
39680 +                                               dwc_otg_urb);
39681 +
39682 +/** Set ISOC descriptor offset and length
39683 + *
39684 + * @param dwc_otg_urb DWC_OTG URB
39685 + * @param desc_num ISOC descriptor number
39686 + * @param offset Offset from beginig of buffer.
39687 + * @param length Transaction length
39688 + */
39689 +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
39690 +                                               int desc_num, uint32_t offset,
39691 +                                               uint32_t length);
39692 +
39693 +/** Get status of ISOC descriptor, specified by desc_num
39694 + *
39695 + * @param dwc_otg_urb DWC_OTG URB
39696 + * @param desc_num ISOC descriptor number
39697 + */
39698 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
39699 +                                                   dwc_otg_urb, int desc_num);
39700 +
39701 +/** Get actual length of ISOC descriptor, specified by desc_num
39702 + *
39703 + * @param dwc_otg_urb DWC_OTG URB
39704 + * @param desc_num ISOC descriptor number
39705 + */
39706 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
39707 +                                                          dwc_otg_urb,
39708 +                                                          int desc_num);
39709 +
39710 +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
39711 + *
39712 + * @param dwc_otg_hcd The HCD
39713 + * @param dwc_otg_urb DWC_OTG URB
39714 + * @param ep_handle Out parameter for returning endpoint handle
39715 + * @param atomic_alloc Flag to do atomic allocation if needed
39716 + *
39717 + * Returns -DWC_E_NO_DEVICE if no device is connected.
39718 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
39719 + * Returns 0 on success.
39720 + */
39721 +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
39722 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb,
39723 +                                  void **ep_handle, int atomic_alloc);
39724 +
39725 +/** De-queue the specified URB
39726 + *
39727 + * @param dwc_otg_hcd The HCD
39728 + * @param dwc_otg_urb DWC_OTG URB
39729 + */
39730 +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
39731 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb);
39732 +
39733 +/** Frees resources in the DWC_otg controller related to a given endpoint.
39734 + * Any URBs for the endpoint must already be dequeued.
39735 + *
39736 + * @param hcd The HCD
39737 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39738 + * @param retry Number of retries if there are queued transfers.
39739 + *
39740 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39741 + * Returns 0 on success
39742 + */
39743 +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
39744 +                                       int retry);
39745 +
39746 +/* Resets the data toggle in qh structure. This function can be called from
39747 + * usb_clear_halt routine.
39748 + *
39749 + * @param hcd The HCD
39750 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39751 + *
39752 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39753 + * Returns 0 on success
39754 + */
39755 +extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);
39756 +
39757 +/** Returns 1 if status of specified port is changed and 0 otherwise.
39758 + *
39759 + * @param hcd The HCD
39760 + * @param port Port number
39761 + */
39762 +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
39763 +
39764 +/** Call this function to check if bandwidth was allocated for specified endpoint.
39765 + * Only for ISOC and INTERRUPT endpoints.
39766 + *
39767 + * @param hcd The HCD
39768 + * @param ep_handle Endpoint handle
39769 + */
39770 +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
39771 +                                             void *ep_handle);
39772 +
39773 +/** Call this function to check if bandwidth was freed for specified endpoint.
39774 + *
39775 + * @param hcd The HCD
39776 + * @param ep_handle Endpoint handle
39777 + */
39778 +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
39779 +
39780 +/** Returns bandwidth allocated for specified endpoint in microseconds.
39781 + * Only for ISOC and INTERRUPT endpoints.
39782 + *
39783 + * @param hcd The HCD
39784 + * @param ep_handle Endpoint handle
39785 + */
39786 +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
39787 +                                           void *ep_handle);
39788 +
39789 +/** @} */
39790 +
39791 +#endif /* __DWC_HCD_IF_H__ */
39792 +#endif /* DWC_DEVICE_ONLY */
39793 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39794 new file mode 100644
39795 index 0000000..b41e164
39796 --- /dev/null
39797 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39798 @@ -0,0 +1,2106 @@
39799 +/* ==========================================================================
39800 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
39801 + * $Revision: #89 $
39802 + * $Date: 2011/10/20 $
39803 + * $Change: 1869487 $
39804 + *
39805 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39806 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39807 + * otherwise expressly agreed to in writing between Synopsys and you.
39808 + *
39809 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39810 + * any End User Software License Agreement or Agreement for Licensed Product
39811 + * with Synopsys or any supplement thereto. You are permitted to use and
39812 + * redistribute this Software in source and binary forms, with or without
39813 + * modification, provided that redistributions of source code must retain this
39814 + * notice. You may not view, use, disclose, copy or distribute this file or
39815 + * any information contained herein except pursuant to this license grant from
39816 + * Synopsys. If you do not agree with this notice, including the disclaimer
39817 + * below, then you are not authorized to use the Software.
39818 + *
39819 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39820 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39821 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39822 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39823 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39824 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39825 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39826 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39827 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39828 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39829 + * DAMAGE.
39830 + * ========================================================================== */
39831 +#ifndef DWC_DEVICE_ONLY
39832 +
39833 +#include "dwc_otg_hcd.h"
39834 +#include "dwc_otg_regs.h"
39835 +
39836 +extern bool microframe_schedule;
39837 +
39838 +/** @file
39839 + * This file contains the implementation of the HCD Interrupt handlers.
39840 + */
39841 +
39842 +/** This function handles interrupts for the HCD. */
39843 +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39844 +{
39845 +       int retval = 0;
39846 +
39847 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
39848 +       gintsts_data_t gintsts;
39849 +#ifdef DEBUG
39850 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
39851 +
39852 +        //GRAYG: debugging
39853 +        if (NULL == global_regs) {
39854 +                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
39855 +                            "core_if=%p\n",
39856 +                            dwc_otg_hcd, global_regs);
39857 +                return retval;
39858 +        }
39859 +#endif
39860 +
39861 +       /* Exit from ISR if core is hibernated */
39862 +       if (core_if->hibernation_suspend == 1) {
39863 +               return retval;
39864 +       }
39865 +       DWC_SPINLOCK(dwc_otg_hcd->lock);
39866 +       /* Check if HOST Mode */
39867 +       if (dwc_otg_is_host_mode(core_if)) {
39868 +               gintsts.d32 = dwc_otg_read_core_intr(core_if);
39869 +               if (!gintsts.d32) {
39870 +                       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39871 +                       return 0;
39872 +               }
39873 +#ifdef DEBUG
39874 +               /* Don't print debug message in the interrupt handler on SOF */
39875 +#ifndef DEBUG_SOF
39876 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39877 +#endif
39878 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39879 +#endif
39880 +
39881 +#ifdef DEBUG
39882 +#ifndef DEBUG_SOF
39883 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39884 +#endif
39885 +                       DWC_DEBUGPL(DBG_HCDI,
39886 +                                   "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
39887 +                                   gintsts.d32, core_if);
39888 +#endif
39889 +
39890 +               if (gintsts.b.sofintr) {
39891 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
39892 +               }
39893 +               if (gintsts.b.rxstsqlvl) {
39894 +                       retval |=
39895 +                           dwc_otg_hcd_handle_rx_status_q_level_intr
39896 +                           (dwc_otg_hcd);
39897 +               }
39898 +               if (gintsts.b.nptxfempty) {
39899 +                       retval |=
39900 +                           dwc_otg_hcd_handle_np_tx_fifo_empty_intr
39901 +                           (dwc_otg_hcd);
39902 +               }
39903 +               if (gintsts.b.i2cintr) {
39904 +                       /** @todo Implement i2cintr handler. */
39905 +               }
39906 +               if (gintsts.b.portintr) {
39907 +                       retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
39908 +               }
39909 +               if (gintsts.b.hcintr) {
39910 +                       retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
39911 +               }
39912 +               if (gintsts.b.ptxfempty) {
39913 +                       retval |=
39914 +                           dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
39915 +                           (dwc_otg_hcd);
39916 +               }
39917 +#ifdef DEBUG
39918 +#ifndef DEBUG_SOF
39919 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39920 +#endif
39921 +               {
39922 +                       DWC_DEBUGPL(DBG_HCDI,
39923 +                                   "DWC OTG HCD Finished Servicing Interrupts\n");
39924 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
39925 +                                   DWC_READ_REG32(&global_regs->gintsts));
39926 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
39927 +                                   DWC_READ_REG32(&global_regs->gintmsk));
39928 +               }
39929 +#endif
39930 +
39931 +#ifdef DEBUG
39932 +#ifndef DEBUG_SOF
39933 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39934 +#endif
39935 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39936 +#endif
39937 +
39938 +       }
39939 +       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39940 +       return retval;
39941 +}
39942 +
39943 +#ifdef DWC_TRACK_MISSED_SOFS
39944 +#warning Compiling code to track missed SOFs
39945 +#define FRAME_NUM_ARRAY_SIZE 1000
39946 +/**
39947 + * This function is for debug only.
39948 + */
39949 +static inline void track_missed_sofs(uint16_t curr_frame_number)
39950 +{
39951 +       static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
39952 +       static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
39953 +       static int frame_num_idx = 0;
39954 +       static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
39955 +       static int dumped_frame_num_array = 0;
39956 +
39957 +       if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
39958 +               if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
39959 +                   curr_frame_number) {
39960 +                       frame_num_array[frame_num_idx] = curr_frame_number;
39961 +                       last_frame_num_array[frame_num_idx++] = last_frame_num;
39962 +               }
39963 +       } else if (!dumped_frame_num_array) {
39964 +               int i;
39965 +               DWC_PRINTF("Frame     Last Frame\n");
39966 +               DWC_PRINTF("-----     ----------\n");
39967 +               for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
39968 +                       DWC_PRINTF("0x%04x    0x%04x\n",
39969 +                                  frame_num_array[i], last_frame_num_array[i]);
39970 +               }
39971 +               dumped_frame_num_array = 1;
39972 +       }
39973 +       last_frame_num = curr_frame_number;
39974 +}
39975 +#endif
39976 +
39977 +/**
39978 + * Handles the start-of-frame interrupt in host mode. Non-periodic
39979 + * transactions may be queued to the DWC_otg controller for the current
39980 + * (micro)frame. Periodic transactions may be queued to the controller for the
39981 + * next (micro)frame.
39982 + */
39983 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
39984 +{
39985 +       hfnum_data_t hfnum;
39986 +       dwc_list_link_t *qh_entry;
39987 +       dwc_otg_qh_t *qh;
39988 +       dwc_otg_transaction_type_e tr_type;
39989 +       gintsts_data_t gintsts = {.d32 = 0 };
39990 +
39991 +       hfnum.d32 =
39992 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
39993 +
39994 +#ifdef DEBUG_SOF
39995 +       DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
39996 +#endif
39997 +       hcd->frame_number = hfnum.b.frnum;
39998 +
39999 +#ifdef DEBUG
40000 +       hcd->frrem_accum += hfnum.b.frrem;
40001 +       hcd->frrem_samples++;
40002 +#endif
40003 +
40004 +#ifdef DWC_TRACK_MISSED_SOFS
40005 +       track_missed_sofs(hcd->frame_number);
40006 +#endif
40007 +       /* Determine whether any periodic QHs should be executed. */
40008 +       qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
40009 +       while (qh_entry != &hcd->periodic_sched_inactive) {
40010 +               qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
40011 +               qh_entry = qh_entry->next;
40012 +               if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
40013 +                       /*
40014 +                        * Move QH to the ready list to be executed next
40015 +                        * (micro)frame.
40016 +                        */
40017 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
40018 +                                          &qh->qh_list_entry);
40019 +               }
40020 +       }
40021 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
40022 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40023 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
40024 +       }
40025 +
40026 +       /* Clear interrupt */
40027 +       gintsts.b.sofintr = 1;
40028 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
40029 +
40030 +       return 1;
40031 +}
40032 +
40033 +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
40034 + * least one packet in the Rx FIFO.  The packets are moved from the FIFO to
40035 + * memory if the DWC_otg controller is operating in Slave mode. */
40036 +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40037 +{
40038 +       host_grxsts_data_t grxsts;
40039 +       dwc_hc_t *hc = NULL;
40040 +
40041 +       DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
40042 +
40043 +       grxsts.d32 =
40044 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
40045 +
40046 +       hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
40047 +       if (!hc) {
40048 +               DWC_ERROR("Unable to get corresponding channel\n");
40049 +               return 0;
40050 +       }
40051 +
40052 +       /* Packet Status */
40053 +       DWC_DEBUGPL(DBG_HCDV, "    Ch num = %d\n", grxsts.b.chnum);
40054 +       DWC_DEBUGPL(DBG_HCDV, "    Count = %d\n", grxsts.b.bcnt);
40055 +       DWC_DEBUGPL(DBG_HCDV, "    DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
40056 +                   hc->data_pid_start);
40057 +       DWC_DEBUGPL(DBG_HCDV, "    PStatus = %d\n", grxsts.b.pktsts);
40058 +
40059 +       switch (grxsts.b.pktsts) {
40060 +       case DWC_GRXSTS_PKTSTS_IN:
40061 +               /* Read the data into the host buffer. */
40062 +               if (grxsts.b.bcnt > 0) {
40063 +                       dwc_otg_read_packet(dwc_otg_hcd->core_if,
40064 +                                           hc->xfer_buff, grxsts.b.bcnt);
40065 +
40066 +                       /* Update the HC fields for the next packet received. */
40067 +                       hc->xfer_count += grxsts.b.bcnt;
40068 +                       hc->xfer_buff += grxsts.b.bcnt;
40069 +               }
40070 +
40071 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
40072 +       case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
40073 +       case DWC_GRXSTS_PKTSTS_CH_HALTED:
40074 +               /* Handled in interrupt, just ignore data */
40075 +               break;
40076 +       default:
40077 +               DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
40078 +                         grxsts.b.pktsts);
40079 +               break;
40080 +       }
40081 +
40082 +       return 1;
40083 +}
40084 +
40085 +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
40086 + * data packets may be written to the FIFO for OUT transfers. More requests
40087 + * may be written to the non-periodic request queue for IN transfers. This
40088 + * interrupt is enabled only in Slave mode. */
40089 +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40090 +{
40091 +       DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
40092 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
40093 +                                      DWC_OTG_TRANSACTION_NON_PERIODIC);
40094 +       return 1;
40095 +}
40096 +
40097 +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
40098 + * packets may be written to the FIFO for OUT transfers. More requests may be
40099 + * written to the periodic request queue for IN transfers. This interrupt is
40100 + * enabled only in Slave mode. */
40101 +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40102 +{
40103 +       DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
40104 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
40105 +                                      DWC_OTG_TRANSACTION_PERIODIC);
40106 +       return 1;
40107 +}
40108 +
40109 +/** There are multiple conditions that can cause a port interrupt. This function
40110 + * determines which interrupt conditions have occurred and handles them
40111 + * appropriately. */
40112 +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40113 +{
40114 +       int retval = 0;
40115 +       hprt0_data_t hprt0;
40116 +       hprt0_data_t hprt0_modify;
40117 +
40118 +       hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40119 +       hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40120 +
40121 +       /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
40122 +        * GINTSTS */
40123 +
40124 +       hprt0_modify.b.prtena = 0;
40125 +       hprt0_modify.b.prtconndet = 0;
40126 +       hprt0_modify.b.prtenchng = 0;
40127 +       hprt0_modify.b.prtovrcurrchng = 0;
40128 +
40129 +       /* Port Connect Detected
40130 +        * Set flag and clear if detected */
40131 +       if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
40132 +               // Dont modify port status if we are in hibernation state
40133 +               hprt0_modify.b.prtconndet = 1;
40134 +               hprt0_modify.b.prtenchng = 1;
40135 +               DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40136 +               hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40137 +               return retval;
40138 +       }
40139 +
40140 +       if (hprt0.b.prtconndet) {
40141 +               /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
40142 +               if (dwc_otg_hcd->core_if->adp_enable &&
40143 +                               dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
40144 +                       DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
40145 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
40146 +                       dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40147 +                       /* TODO - check if this is required, as
40148 +                        * host initialization was already performed
40149 +                        * after initial ADP probing
40150 +                        */
40151 +                       /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40152 +                       dwc_otg_core_init(dwc_otg_hcd->core_if);
40153 +                       dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
40154 +                       cil_hcd_start(dwc_otg_hcd->core_if);*/
40155 +               } else {
40156 +
40157 +                       DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
40158 +                                   "Port Connect Detected--\n", hprt0.d32);
40159 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
40160 +                       dwc_otg_hcd->flags.b.port_connect_status = 1;
40161 +                       hprt0_modify.b.prtconndet = 1;
40162 +
40163 +                       /* B-Device has connected, Delete the connection timer. */
40164 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
40165 +               }
40166 +               /* The Hub driver asserts a reset when it sees port connect
40167 +                * status change flag */
40168 +               retval |= 1;
40169 +       }
40170 +
40171 +       /* Port Enable Changed
40172 +        * Clear if detected - Set internal flag if disabled */
40173 +       if (hprt0.b.prtenchng) {
40174 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40175 +                           "Port Enable Changed--\n", hprt0.d32);
40176 +               hprt0_modify.b.prtenchng = 1;
40177 +               if (hprt0.b.prtena == 1) {
40178 +                       hfir_data_t hfir;
40179 +                       int do_reset = 0;
40180 +                       dwc_otg_core_params_t *params =
40181 +                           dwc_otg_hcd->core_if->core_params;
40182 +                       dwc_otg_core_global_regs_t *global_regs =
40183 +                           dwc_otg_hcd->core_if->core_global_regs;
40184 +                       dwc_otg_host_if_t *host_if =
40185 +                           dwc_otg_hcd->core_if->host_if;
40186 +
40187 +                       /* Every time when port enables calculate
40188 +                        * HFIR.FrInterval
40189 +                        */
40190 +                       hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
40191 +                       hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
40192 +                       DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
40193 +
40194 +                       /* Check if we need to adjust the PHY clock speed for
40195 +                        * low power and adjust it */
40196 +                       if (params->host_support_fs_ls_low_power) {
40197 +                               gusbcfg_data_t usbcfg;
40198 +
40199 +                               usbcfg.d32 =
40200 +                                   DWC_READ_REG32(&global_regs->gusbcfg);
40201 +
40202 +                               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
40203 +                                   || hprt0.b.prtspd ==
40204 +                                   DWC_HPRT0_PRTSPD_FULL_SPEED) {
40205 +                                       /*
40206 +                                        * Low power
40207 +                                        */
40208 +                                       hcfg_data_t hcfg;
40209 +                                       if (usbcfg.b.phylpwrclksel == 0) {
40210 +                                               /* Set PHY low power clock select for FS/LS devices */
40211 +                                               usbcfg.b.phylpwrclksel = 1;
40212 +                                               DWC_WRITE_REG32
40213 +                                                   (&global_regs->gusbcfg,
40214 +                                                    usbcfg.d32);
40215 +                                               do_reset = 1;
40216 +                                       }
40217 +
40218 +                                       hcfg.d32 =
40219 +                                           DWC_READ_REG32
40220 +                                           (&host_if->host_global_regs->hcfg);
40221 +
40222 +                                       if (hprt0.b.prtspd ==
40223 +                                           DWC_HPRT0_PRTSPD_LOW_SPEED
40224 +                                           && params->host_ls_low_power_phy_clk
40225 +                                           ==
40226 +                                           DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
40227 +                                       {
40228 +                                               /* 6 MHZ */
40229 +                                               DWC_DEBUGPL(DBG_CIL,
40230 +                                                           "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
40231 +                                               if (hcfg.b.fslspclksel !=
40232 +                                                   DWC_HCFG_6_MHZ) {
40233 +                                                       hcfg.b.fslspclksel =
40234 +                                                           DWC_HCFG_6_MHZ;
40235 +                                                       DWC_WRITE_REG32
40236 +                                                           (&host_if->host_global_regs->hcfg,
40237 +                                                            hcfg.d32);
40238 +                                                       do_reset = 1;
40239 +                                               }
40240 +                                       } else {
40241 +                                               /* 48 MHZ */
40242 +                                               DWC_DEBUGPL(DBG_CIL,
40243 +                                                           "FS_PHY programming HCFG to 48 MHz ()\n");
40244 +                                               if (hcfg.b.fslspclksel !=
40245 +                                                   DWC_HCFG_48_MHZ) {
40246 +                                                       hcfg.b.fslspclksel =
40247 +                                                           DWC_HCFG_48_MHZ;
40248 +                                                       DWC_WRITE_REG32
40249 +                                                           (&host_if->host_global_regs->hcfg,
40250 +                                                            hcfg.d32);
40251 +                                                       do_reset = 1;
40252 +                                               }
40253 +                                       }
40254 +                               } else {
40255 +                                       /*
40256 +                                        * Not low power
40257 +                                        */
40258 +                                       if (usbcfg.b.phylpwrclksel == 1) {
40259 +                                               usbcfg.b.phylpwrclksel = 0;
40260 +                                               DWC_WRITE_REG32
40261 +                                                   (&global_regs->gusbcfg,
40262 +                                                    usbcfg.d32);
40263 +                                               do_reset = 1;
40264 +                                       }
40265 +                               }
40266 +
40267 +                               if (do_reset) {
40268 +                                       DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
40269 +                               }
40270 +                       }
40271 +
40272 +                       if (!do_reset) {
40273 +                               /* Port has been enabled set the reset change flag */
40274 +                               dwc_otg_hcd->flags.b.port_reset_change = 1;
40275 +                       }
40276 +               } else {
40277 +                       dwc_otg_hcd->flags.b.port_enable_change = 1;
40278 +               }
40279 +               retval |= 1;
40280 +       }
40281 +
40282 +       /** Overcurrent Change Interrupt */
40283 +       if (hprt0.b.prtovrcurrchng) {
40284 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40285 +                           "Port Overcurrent Changed--\n", hprt0.d32);
40286 +               dwc_otg_hcd->flags.b.port_over_current_change = 1;
40287 +               hprt0_modify.b.prtovrcurrchng = 1;
40288 +               retval |= 1;
40289 +       }
40290 +
40291 +       /* Clear Port Interrupts */
40292 +       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40293 +
40294 +       return retval;
40295 +}
40296 +
40297 +/** This interrupt indicates that one or more host channels has a pending
40298 + * interrupt. There are multiple conditions that can cause each host channel
40299 + * interrupt. This function determines which conditions have occurred for each
40300 + * host channel interrupt and handles them appropriately. */
40301 +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40302 +{
40303 +       int i;
40304 +       int retval = 0;
40305 +       haint_data_t haint;
40306 +
40307 +       /* Clear appropriate bits in HCINTn to clear the interrupt bit in
40308 +        * GINTSTS */
40309 +
40310 +       haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
40311 +
40312 +       for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
40313 +               if (haint.b2.chint & (1 << i)) {
40314 +                       retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
40315 +               }
40316 +       }
40317 +
40318 +       return retval;
40319 +}
40320 +
40321 +/**
40322 + * Gets the actual length of a transfer after the transfer halts. _halt_status
40323 + * holds the reason for the halt.
40324 + *
40325 + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
40326 + * *short_read is set to 1 upon return if less than the requested
40327 + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
40328 + * return. short_read may also be NULL on entry, in which case it remains
40329 + * unchanged.
40330 + */
40331 +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
40332 +                                      dwc_otg_hc_regs_t * hc_regs,
40333 +                                      dwc_otg_qtd_t * qtd,
40334 +                                      dwc_otg_halt_status_e halt_status,
40335 +                                      int *short_read)
40336 +{
40337 +       hctsiz_data_t hctsiz;
40338 +       uint32_t length;
40339 +
40340 +       if (short_read != NULL) {
40341 +               *short_read = 0;
40342 +       }
40343 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40344 +
40345 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
40346 +               if (hc->ep_is_in) {
40347 +                       length = hc->xfer_len - hctsiz.b.xfersize;
40348 +                       if (short_read != NULL) {
40349 +                               *short_read = (hctsiz.b.xfersize != 0);
40350 +                       }
40351 +               } else if (hc->qh->do_split) {
40352 +                       length = qtd->ssplit_out_xfer_count;
40353 +               } else {
40354 +                       length = hc->xfer_len;
40355 +               }
40356 +       } else {
40357 +               /*
40358 +                * Must use the hctsiz.pktcnt field to determine how much data
40359 +                * has been transferred. This field reflects the number of
40360 +                * packets that have been transferred via the USB. This is
40361 +                * always an integral number of packets if the transfer was
40362 +                * halted before its normal completion. (Can't use the
40363 +                * hctsiz.xfersize field because that reflects the number of
40364 +                * bytes transferred via the AHB, not the USB).
40365 +                */
40366 +               length =
40367 +                   (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
40368 +       }
40369 +
40370 +       return length;
40371 +}
40372 +
40373 +/**
40374 + * Updates the state of the URB after a Transfer Complete interrupt on the
40375 + * host channel. Updates the actual_length field of the URB based on the
40376 + * number of bytes transferred via the host channel. Sets the URB status
40377 + * if the data transfer is finished.
40378 + *
40379 + * @return 1 if the data transfer specified by the URB is completely finished,
40380 + * 0 otherwise.
40381 + */
40382 +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
40383 +                                     dwc_otg_hc_regs_t * hc_regs,
40384 +                                     dwc_otg_hcd_urb_t * urb,
40385 +                                     dwc_otg_qtd_t * qtd)
40386 +{
40387 +       int xfer_done = 0;
40388 +       int short_read = 0;
40389 +
40390 +       int xfer_length;
40391 +
40392 +       xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
40393 +                                            DWC_OTG_HC_XFER_COMPLETE,
40394 +                                            &short_read);
40395 +
40396 +
40397 +       /* non DWORD-aligned buffer case handling. */
40398 +       if (hc->align_buff && xfer_length && hc->ep_is_in) {
40399 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40400 +                          xfer_length);
40401 +       }
40402 +
40403 +       urb->actual_length += xfer_length;
40404 +
40405 +       if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
40406 +           (urb->flags & URB_SEND_ZERO_PACKET)
40407 +           && (urb->actual_length == urb->length)
40408 +           && !(urb->length % hc->max_packet)) {
40409 +               xfer_done = 0;
40410 +       } else if (short_read || urb->actual_length >= urb->length) {
40411 +               xfer_done = 1;
40412 +               urb->status = 0;
40413 +       }
40414 +
40415 +#ifdef DEBUG
40416 +       {
40417 +               hctsiz_data_t hctsiz;
40418 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40419 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40420 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
40421 +                           hc->hc_num);
40422 +               DWC_DEBUGPL(DBG_HCDV, "  hc->xfer_len %d\n", hc->xfer_len);
40423 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.xfersize %d\n",
40424 +                           hctsiz.b.xfersize);
40425 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
40426 +                           urb->length);
40427 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
40428 +                           urb->actual_length);
40429 +               DWC_DEBUGPL(DBG_HCDV, "  short_read %d, xfer_done %d\n",
40430 +                           short_read, xfer_done);
40431 +       }
40432 +#endif
40433 +
40434 +       return xfer_done;
40435 +}
40436 +
40437 +/*
40438 + * Save the starting data toggle for the next transfer. The data toggle is
40439 + * saved in the QH for non-control transfers and it's saved in the QTD for
40440 + * control transfers.
40441 + */
40442 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
40443 +                            dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
40444 +{
40445 +       hctsiz_data_t hctsiz;
40446 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40447 +
40448 +       if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
40449 +               dwc_otg_qh_t *qh = hc->qh;
40450 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40451 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
40452 +               } else {
40453 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA1;
40454 +               }
40455 +       } else {
40456 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40457 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
40458 +               } else {
40459 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
40460 +               }
40461 +       }
40462 +}
40463 +
40464 +/**
40465 + * Updates the state of an Isochronous URB when the transfer is stopped for
40466 + * any reason. The fields of the current entry in the frame descriptor array
40467 + * are set based on the transfer state and the input _halt_status. Completes
40468 + * the Isochronous URB if all the URB frames have been completed.
40469 + *
40470 + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
40471 + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
40472 + */
40473 +static dwc_otg_halt_status_e
40474 +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
40475 +                     dwc_hc_t * hc,
40476 +                     dwc_otg_hc_regs_t * hc_regs,
40477 +                     dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40478 +{
40479 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40480 +       dwc_otg_halt_status_e ret_val = halt_status;
40481 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40482 +
40483 +       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
40484 +       switch (halt_status) {
40485 +       case DWC_OTG_HC_XFER_COMPLETE:
40486 +               frame_desc->status = 0;
40487 +               frame_desc->actual_length =
40488 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40489 +
40490 +               /* non DWORD-aligned buffer case handling. */
40491 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40492 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40493 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40494 +               }
40495 +
40496 +               break;
40497 +       case DWC_OTG_HC_XFER_FRAME_OVERRUN:
40498 +               urb->error_count++;
40499 +               if (hc->ep_is_in) {
40500 +                       frame_desc->status = -DWC_E_NO_STREAM_RES;
40501 +               } else {
40502 +                       frame_desc->status = -DWC_E_COMMUNICATION;
40503 +               }
40504 +               frame_desc->actual_length = 0;
40505 +               break;
40506 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40507 +               urb->error_count++;
40508 +               frame_desc->status = -DWC_E_OVERFLOW;
40509 +               /* Don't need to update actual_length in this case. */
40510 +               break;
40511 +       case DWC_OTG_HC_XFER_XACT_ERR:
40512 +               urb->error_count++;
40513 +               frame_desc->status = -DWC_E_PROTOCOL;
40514 +               frame_desc->actual_length =
40515 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40516 +
40517 +               /* non DWORD-aligned buffer case handling. */
40518 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40519 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40520 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40521 +               }
40522 +               /* Skip whole frame */
40523 +               if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
40524 +                   hc->ep_is_in && hcd->core_if->dma_enable) {
40525 +                       qtd->complete_split = 0;
40526 +                       qtd->isoc_split_offset = 0;
40527 +               }
40528 +
40529 +               break;
40530 +       default:
40531 +               DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
40532 +               break;
40533 +       }
40534 +       if (++qtd->isoc_frame_index == urb->packet_count) {
40535 +               /*
40536 +                * urb->status is not used for isoc transfers.
40537 +                * The individual frame_desc statuses are used instead.
40538 +                */
40539 +               hcd->fops->complete(hcd, urb->priv, urb, 0);
40540 +               ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
40541 +       } else {
40542 +               ret_val = DWC_OTG_HC_XFER_COMPLETE;
40543 +       }
40544 +       return ret_val;
40545 +}
40546 +
40547 +/**
40548 + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
40549 + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
40550 + * still linked to the QH, the QH is added to the end of the inactive
40551 + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
40552 + * schedule if no more QTDs are linked to the QH.
40553 + */
40554 +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
40555 +{
40556 +       int continue_split = 0;
40557 +       dwc_otg_qtd_t *qtd;
40558 +
40559 +       DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
40560 +
40561 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
40562 +
40563 +       if (qtd->complete_split) {
40564 +               continue_split = 1;
40565 +       } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
40566 +                  qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
40567 +               continue_split = 1;
40568 +       }
40569 +
40570 +       if (free_qtd) {
40571 +               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
40572 +               continue_split = 0;
40573 +       }
40574 +
40575 +       qh->channel = NULL;
40576 +       dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
40577 +}
40578 +
40579 +/**
40580 + * Releases a host channel for use by other transfers. Attempts to select and
40581 + * queue more transactions since at least one host channel is available.
40582 + *
40583 + * @param hcd The HCD state structure.
40584 + * @param hc The host channel to release.
40585 + * @param qtd The QTD associated with the host channel. This QTD may be freed
40586 + * if the transfer is complete or an error has occurred.
40587 + * @param halt_status Reason the channel is being released. This status
40588 + * determines the actions taken by this function.
40589 + */
40590 +static void release_channel(dwc_otg_hcd_t * hcd,
40591 +                           dwc_hc_t * hc,
40592 +                           dwc_otg_qtd_t * qtd,
40593 +                           dwc_otg_halt_status_e halt_status)
40594 +{
40595 +       dwc_otg_transaction_type_e tr_type;
40596 +       int free_qtd;
40597 +       dwc_irqflags_t flags;
40598 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
40599 +
40600 +       DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
40601 +                   __func__, hc->hc_num, halt_status, hc->xfer_len);
40602 +
40603 +       switch (halt_status) {
40604 +       case DWC_OTG_HC_XFER_URB_COMPLETE:
40605 +               free_qtd = 1;
40606 +               break;
40607 +       case DWC_OTG_HC_XFER_AHB_ERR:
40608 +       case DWC_OTG_HC_XFER_STALL:
40609 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40610 +               free_qtd = 1;
40611 +               break;
40612 +       case DWC_OTG_HC_XFER_XACT_ERR:
40613 +               if (qtd->error_count >= 3) {
40614 +                       DWC_DEBUGPL(DBG_HCDV,
40615 +                                   "  Complete URB with transaction error\n");
40616 +                       free_qtd = 1;
40617 +                       qtd->urb->status = -DWC_E_PROTOCOL;
40618 +                       hcd->fops->complete(hcd, qtd->urb->priv,
40619 +                                           qtd->urb, -DWC_E_PROTOCOL);
40620 +               } else {
40621 +                       free_qtd = 0;
40622 +               }
40623 +               break;
40624 +       case DWC_OTG_HC_XFER_URB_DEQUEUE:
40625 +               /*
40626 +                * The QTD has already been removed and the QH has been
40627 +                * deactivated. Don't want to do anything except release the
40628 +                * host channel and try to queue more transfers.
40629 +                */
40630 +               goto cleanup;
40631 +       case DWC_OTG_HC_XFER_NO_HALT_STATUS:
40632 +               free_qtd = 0;
40633 +               break;
40634 +       case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
40635 +               DWC_DEBUGPL(DBG_HCDV,
40636 +                       "  Complete URB with I/O error\n");
40637 +               free_qtd = 1;
40638 +               qtd->urb->status = -DWC_E_IO;
40639 +               hcd->fops->complete(hcd, qtd->urb->priv,
40640 +                       qtd->urb, -DWC_E_IO);
40641 +               break;
40642 +       default:
40643 +               free_qtd = 0;
40644 +               break;
40645 +       }
40646 +
40647 +       deactivate_qh(hcd, hc->qh, free_qtd);
40648 +
40649 +cleanup:
40650 +       /*
40651 +        * Release the host channel for use by other transfers. The cleanup
40652 +        * function clears the channel interrupt enables and conditions, so
40653 +        * there's no need to clear the Channel Halted interrupt separately.
40654 +        */
40655 +       dwc_otg_hc_cleanup(hcd->core_if, hc);
40656 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
40657 +
40658 +       if (!microframe_schedule) {
40659 +               switch (hc->ep_type) {
40660 +               case DWC_OTG_EP_TYPE_CONTROL:
40661 +               case DWC_OTG_EP_TYPE_BULK:
40662 +                       hcd->non_periodic_channels--;
40663 +                       break;
40664 +
40665 +               default:
40666 +                       /*
40667 +                        * Don't release reservations for periodic channels here.
40668 +                        * That's done when a periodic transfer is descheduled (i.e.
40669 +                        * when the QH is removed from the periodic schedule).
40670 +                        */
40671 +                       break;
40672 +               }
40673 +       } else {
40674 +
40675 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
40676 +               hcd->available_host_channels++;
40677 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
40678 +       }
40679 +
40680 +       /* Try to queue more transfers now that there's a free channel. */
40681 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
40682 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40683 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
40684 +       }
40685 +       DWC_SPINLOCK_FREE(channel_lock);
40686 +}
40687 +
40688 +/**
40689 + * Halts a host channel. If the channel cannot be halted immediately because
40690 + * the request queue is full, this function ensures that the FIFO empty
40691 + * interrupt for the appropriate queue is enabled so that the halt request can
40692 + * be queued when there is space in the request queue.
40693 + *
40694 + * This function may also be called in DMA mode. In that case, the channel is
40695 + * simply released since the core always halts the channel automatically in
40696 + * DMA mode.
40697 + */
40698 +static void halt_channel(dwc_otg_hcd_t * hcd,
40699 +                        dwc_hc_t * hc,
40700 +                        dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40701 +{
40702 +       if (hcd->core_if->dma_enable) {
40703 +               release_channel(hcd, hc, qtd, halt_status);
40704 +               return;
40705 +       }
40706 +
40707 +       /* Slave mode processing... */
40708 +       dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
40709 +
40710 +       if (hc->halt_on_queue) {
40711 +               gintmsk_data_t gintmsk = {.d32 = 0 };
40712 +               dwc_otg_core_global_regs_t *global_regs;
40713 +               global_regs = hcd->core_if->core_global_regs;
40714 +
40715 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
40716 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
40717 +                       /*
40718 +                        * Make sure the Non-periodic Tx FIFO empty interrupt
40719 +                        * is enabled so that the non-periodic schedule will
40720 +                        * be processed.
40721 +                        */
40722 +                       gintmsk.b.nptxfempty = 1;
40723 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40724 +               } else {
40725 +                       /*
40726 +                        * Move the QH from the periodic queued schedule to
40727 +                        * the periodic assigned schedule. This allows the
40728 +                        * halt to be queued when the periodic schedule is
40729 +                        * processed.
40730 +                        */
40731 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
40732 +                                          &hc->qh->qh_list_entry);
40733 +
40734 +                       /*
40735 +                        * Make sure the Periodic Tx FIFO Empty interrupt is
40736 +                        * enabled so that the periodic schedule will be
40737 +                        * processed.
40738 +                        */
40739 +                       gintmsk.b.ptxfempty = 1;
40740 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40741 +               }
40742 +       }
40743 +}
40744 +
40745 +/**
40746 + * Performs common cleanup for non-periodic transfers after a Transfer
40747 + * Complete interrupt. This function should be called after any endpoint type
40748 + * specific handling is finished to release the host channel.
40749 + */
40750 +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
40751 +                                      dwc_hc_t * hc,
40752 +                                      dwc_otg_hc_regs_t * hc_regs,
40753 +                                      dwc_otg_qtd_t * qtd,
40754 +                                      dwc_otg_halt_status_e halt_status)
40755 +{
40756 +       hcint_data_t hcint;
40757 +
40758 +       qtd->error_count = 0;
40759 +
40760 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
40761 +       if (hcint.b.nyet) {
40762 +               /*
40763 +                * Got a NYET on the last transaction of the transfer. This
40764 +                * means that the endpoint should be in the PING state at the
40765 +                * beginning of the next transfer.
40766 +                */
40767 +               hc->qh->ping_state = 1;
40768 +               clear_hc_int(hc_regs, nyet);
40769 +       }
40770 +
40771 +       /*
40772 +        * Always halt and release the host channel to make it available for
40773 +        * more transfers. There may still be more phases for a control
40774 +        * transfer or more data packets for a bulk transfer at this point,
40775 +        * but the host channel is still halted. A channel will be reassigned
40776 +        * to the transfer when the non-periodic schedule is processed after
40777 +        * the channel is released. This allows transactions to be queued
40778 +        * properly via dwc_otg_hcd_queue_transactions, which also enables the
40779 +        * Tx FIFO Empty interrupt if necessary.
40780 +        */
40781 +       if (hc->ep_is_in) {
40782 +               /*
40783 +                * IN transfers in Slave mode require an explicit disable to
40784 +                * halt the channel. (In DMA mode, this call simply releases
40785 +                * the channel.)
40786 +                */
40787 +               halt_channel(hcd, hc, qtd, halt_status);
40788 +       } else {
40789 +               /*
40790 +                * The channel is automatically disabled by the core for OUT
40791 +                * transfers in Slave mode.
40792 +                */
40793 +               release_channel(hcd, hc, qtd, halt_status);
40794 +       }
40795 +}
40796 +
40797 +/**
40798 + * Performs common cleanup for periodic transfers after a Transfer Complete
40799 + * interrupt. This function should be called after any endpoint type specific
40800 + * handling is finished to release the host channel.
40801 + */
40802 +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
40803 +                                  dwc_hc_t * hc,
40804 +                                  dwc_otg_hc_regs_t * hc_regs,
40805 +                                  dwc_otg_qtd_t * qtd,
40806 +                                  dwc_otg_halt_status_e halt_status)
40807 +{
40808 +       hctsiz_data_t hctsiz;
40809 +       qtd->error_count = 0;
40810 +
40811 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40812 +       if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
40813 +               /* Core halts channel in these cases. */
40814 +               release_channel(hcd, hc, qtd, halt_status);
40815 +       } else {
40816 +               /* Flush any outstanding requests from the Tx queue. */
40817 +               halt_channel(hcd, hc, qtd, halt_status);
40818 +       }
40819 +}
40820 +
40821 +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
40822 +                                            dwc_hc_t * hc,
40823 +                                            dwc_otg_hc_regs_t * hc_regs,
40824 +                                            dwc_otg_qtd_t * qtd)
40825 +{
40826 +       uint32_t len;
40827 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40828 +       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
40829 +
40830 +       len = get_actual_xfer_length(hc, hc_regs, qtd,
40831 +                                    DWC_OTG_HC_XFER_COMPLETE, NULL);
40832 +
40833 +       if (!len) {
40834 +               qtd->complete_split = 0;
40835 +               qtd->isoc_split_offset = 0;
40836 +               return 0;
40837 +       }
40838 +       frame_desc->actual_length += len;
40839 +
40840 +       if (hc->align_buff && len)
40841 +               dwc_memcpy(qtd->urb->buf + frame_desc->offset +
40842 +                          qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
40843 +       qtd->isoc_split_offset += len;
40844 +
40845 +       if (frame_desc->length == frame_desc->actual_length) {
40846 +               frame_desc->status = 0;
40847 +               qtd->isoc_frame_index++;
40848 +               qtd->complete_split = 0;
40849 +               qtd->isoc_split_offset = 0;
40850 +       }
40851 +
40852 +       if (qtd->isoc_frame_index == qtd->urb->packet_count) {
40853 +               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
40854 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
40855 +       } else {
40856 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
40857 +       }
40858 +
40859 +       return 1;               /* Indicates that channel released */
40860 +}
40861 +
40862 +/**
40863 + * Handles a host channel Transfer Complete interrupt. This handler may be
40864 + * called in either DMA mode or Slave mode.
40865 + */
40866 +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
40867 +                                      dwc_hc_t * hc,
40868 +                                      dwc_otg_hc_regs_t * hc_regs,
40869 +                                      dwc_otg_qtd_t * qtd)
40870 +{
40871 +       int urb_xfer_done;
40872 +       dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
40873 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40874 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40875 +
40876 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40877 +                   "Transfer Complete--\n", hc->hc_num);
40878 +
40879 +       if (hcd->core_if->dma_desc_enable) {
40880 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
40881 +               if (pipe_type == UE_ISOCHRONOUS) {
40882 +                       /* Do not disable the interrupt, just clear it */
40883 +                       clear_hc_int(hc_regs, xfercomp);
40884 +                       return 1;
40885 +               }
40886 +               goto handle_xfercomp_done;
40887 +       }
40888 +
40889 +       /*
40890 +        * Handle xfer complete on CSPLIT.
40891 +        */
40892 +
40893 +       if (hc->qh->do_split) {
40894 +               if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
40895 +                   && hcd->core_if->dma_enable) {
40896 +                       if (qtd->complete_split
40897 +                           && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
40898 +                                                            qtd))
40899 +                               goto handle_xfercomp_done;
40900 +               } else {
40901 +                       qtd->complete_split = 0;
40902 +               }
40903 +       }
40904 +
40905 +       /* Update the QTD and URB states. */
40906 +       switch (pipe_type) {
40907 +       case UE_CONTROL:
40908 +               switch (qtd->control_phase) {
40909 +               case DWC_OTG_CONTROL_SETUP:
40910 +                       if (urb->length > 0) {
40911 +                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
40912 +                       } else {
40913 +                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
40914 +                       }
40915 +                       DWC_DEBUGPL(DBG_HCDV,
40916 +                                   "  Control setup transaction done\n");
40917 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40918 +                       break;
40919 +               case DWC_OTG_CONTROL_DATA:{
40920 +                               urb_xfer_done =
40921 +                                   update_urb_state_xfer_comp(hc, hc_regs, urb,
40922 +                                                              qtd);
40923 +                               if (urb_xfer_done) {
40924 +                                       qtd->control_phase =
40925 +                                           DWC_OTG_CONTROL_STATUS;
40926 +                                       DWC_DEBUGPL(DBG_HCDV,
40927 +                                                   "  Control data transfer done\n");
40928 +                               } else {
40929 +                                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40930 +                               }
40931 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40932 +                               break;
40933 +                       }
40934 +               case DWC_OTG_CONTROL_STATUS:
40935 +                       DWC_DEBUGPL(DBG_HCDV, "  Control transfer complete\n");
40936 +                       if (urb->status == -DWC_E_IN_PROGRESS) {
40937 +                               urb->status = 0;
40938 +                       }
40939 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40940 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40941 +                       break;
40942 +               }
40943 +
40944 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40945 +               break;
40946 +       case UE_BULK:
40947 +               DWC_DEBUGPL(DBG_HCDV, "  Bulk transfer complete\n");
40948 +               urb_xfer_done =
40949 +                   update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40950 +               if (urb_xfer_done) {
40951 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40952 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40953 +               } else {
40954 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40955 +               }
40956 +
40957 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40958 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40959 +               break;
40960 +       case UE_INTERRUPT:
40961 +               DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");
40962 +               urb_xfer_done =
40963 +                       update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40964 +
40965 +               /*
40966 +                * Interrupt URB is done on the first transfer complete
40967 +                * interrupt.
40968 +                */
40969 +               if (urb_xfer_done) {
40970 +                               hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40971 +                               halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40972 +               } else {
40973 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40974 +               }
40975 +
40976 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40977 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40978 +               break;
40979 +       case UE_ISOCHRONOUS:
40980 +               DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");
40981 +               if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
40982 +                       halt_status =
40983 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
40984 +                                                 DWC_OTG_HC_XFER_COMPLETE);
40985 +               }
40986 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40987 +               break;
40988 +       }
40989 +
40990 +handle_xfercomp_done:
40991 +       disable_hc_int(hc_regs, xfercompl);
40992 +
40993 +       return 1;
40994 +}
40995 +
40996 +/**
40997 + * Handles a host channel STALL interrupt. This handler may be called in
40998 + * either DMA mode or Slave mode.
40999 + */
41000 +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
41001 +                                   dwc_hc_t * hc,
41002 +                                   dwc_otg_hc_regs_t * hc_regs,
41003 +                                   dwc_otg_qtd_t * qtd)
41004 +{
41005 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
41006 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
41007 +
41008 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
41009 +                   "STALL Received--\n", hc->hc_num);
41010 +
41011 +       if (hcd->core_if->dma_desc_enable) {
41012 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
41013 +               goto handle_stall_done;
41014 +       }
41015 +
41016 +       if (pipe_type == UE_CONTROL) {
41017 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
41018 +       }
41019 +
41020 +       if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
41021 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
41022 +               /*
41023 +                * USB protocol requires resetting the data toggle for bulk
41024 +                * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
41025 +                * setup command is issued to the endpoint. Anticipate the
41026 +                * CLEAR_FEATURE command since a STALL has occurred and reset
41027 +                * the data toggle now.
41028 +                */
41029 +               hc->qh->data_toggle = 0;
41030 +       }
41031 +
41032 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
41033 +
41034 +handle_stall_done:
41035 +       disable_hc_int(hc_regs, stall);
41036 +
41037 +       return 1;
41038 +}
41039 +
41040 +/*
41041 + * Updates the state of the URB when a transfer has been stopped due to an
41042 + * abnormal condition before the transfer completes. Modifies the
41043 + * actual_length field of the URB to reflect the number of bytes that have
41044 + * actually been transferred via the host channel.
41045 + */
41046 +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
41047 +                                      dwc_otg_hc_regs_t * hc_regs,
41048 +                                      dwc_otg_hcd_urb_t * urb,
41049 +                                      dwc_otg_qtd_t * qtd,
41050 +                                      dwc_otg_halt_status_e halt_status)
41051 +{
41052 +       uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
41053 +                                                           halt_status, NULL);
41054 +       /* non DWORD-aligned buffer case handling. */
41055 +       if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
41056 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
41057 +                          bytes_transferred);
41058 +       }
41059 +
41060 +       urb->actual_length += bytes_transferred;
41061 +
41062 +#ifdef DEBUG
41063 +       {
41064 +               hctsiz_data_t hctsiz;
41065 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41066 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
41067 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
41068 +                           hc->hc_num);
41069 +               DWC_DEBUGPL(DBG_HCDV, "  hc->start_pkt_count %d\n",
41070 +                           hc->start_pkt_count);
41071 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
41072 +               DWC_DEBUGPL(DBG_HCDV, "  hc->max_packet %d\n", hc->max_packet);
41073 +               DWC_DEBUGPL(DBG_HCDV, "  bytes_transferred %d\n",
41074 +                           bytes_transferred);
41075 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
41076 +                           urb->actual_length);
41077 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
41078 +                           urb->length);
41079 +       }
41080 +#endif
41081 +}
41082 +
41083 +/**
41084 + * Handles a host channel NAK interrupt. This handler may be called in either
41085 + * DMA mode or Slave mode.
41086 + */
41087 +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
41088 +                                 dwc_hc_t * hc,
41089 +                                 dwc_otg_hc_regs_t * hc_regs,
41090 +                                 dwc_otg_qtd_t * qtd)
41091 +{
41092 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41093 +                   "NAK Received--\n", hc->hc_num);
41094 +
41095 +       /*
41096 +        * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
41097 +        * interrupt.  Re-start the SSPLIT transfer.
41098 +        */
41099 +       if (hc->do_split) {
41100 +               if (hc->complete_split) {
41101 +                       qtd->error_count = 0;
41102 +               }
41103 +               qtd->complete_split = 0;
41104 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41105 +               goto handle_nak_done;
41106 +       }
41107 +
41108 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41109 +       case UE_CONTROL:
41110 +       case UE_BULK:
41111 +               if (hcd->core_if->dma_enable && hc->ep_is_in) {
41112 +                       /*
41113 +                        * NAK interrupts are enabled on bulk/control IN
41114 +                        * transfers in DMA mode for the sole purpose of
41115 +                        * resetting the error count after a transaction error
41116 +                        * occurs. The core will continue transferring data.
41117 +                        */
41118 +                       qtd->error_count = 0;
41119 +                       goto handle_nak_done;
41120 +               }
41121 +
41122 +               /*
41123 +                * NAK interrupts normally occur during OUT transfers in DMA
41124 +                * or Slave mode. For IN transfers, more requests will be
41125 +                * queued as request queue space is available.
41126 +                */
41127 +               qtd->error_count = 0;
41128 +
41129 +               if (!hc->qh->ping_state) {
41130 +                       update_urb_state_xfer_intr(hc, hc_regs,
41131 +                                                  qtd->urb, qtd,
41132 +                                                  DWC_OTG_HC_XFER_NAK);
41133 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41134 +
41135 +                       if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
41136 +                               hc->qh->ping_state = 1;
41137 +               }
41138 +
41139 +               /*
41140 +                * Halt the channel so the transfer can be re-started from
41141 +                * the appropriate point or the PING protocol will
41142 +                * start/continue.
41143 +                */
41144 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41145 +               break;
41146 +       case UE_INTERRUPT:
41147 +               qtd->error_count = 0;
41148 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41149 +               break;
41150 +       case UE_ISOCHRONOUS:
41151 +               /* Should never get called for isochronous transfers. */
41152 +               DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
41153 +               break;
41154 +       }
41155 +
41156 +handle_nak_done:
41157 +       disable_hc_int(hc_regs, nak);
41158 +
41159 +       return 1;
41160 +}
41161 +
41162 +/**
41163 + * Handles a host channel ACK interrupt. This interrupt is enabled when
41164 + * performing the PING protocol in Slave mode, when errors occur during
41165 + * either Slave mode or DMA mode, and during Start Split transactions.
41166 + */
41167 +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
41168 +                                 dwc_hc_t * hc,
41169 +                                 dwc_otg_hc_regs_t * hc_regs,
41170 +                                 dwc_otg_qtd_t * qtd)
41171 +{
41172 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41173 +                   "ACK Received--\n", hc->hc_num);
41174 +
41175 +       if (hc->do_split) {
41176 +               /*
41177 +                * Handle ACK on SSPLIT.
41178 +                * ACK should not occur in CSPLIT.
41179 +                */
41180 +               if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
41181 +                       qtd->ssplit_out_xfer_count = hc->xfer_len;
41182 +               }
41183 +               if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
41184 +                       /* Don't need complete for isochronous out transfers. */
41185 +                       qtd->complete_split = 1;
41186 +               }
41187 +
41188 +               /* ISOC OUT */
41189 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41190 +                       switch (hc->xact_pos) {
41191 +                       case DWC_HCSPLIT_XACTPOS_ALL:
41192 +                               break;
41193 +                       case DWC_HCSPLIT_XACTPOS_END:
41194 +                               qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
41195 +                               qtd->isoc_split_offset = 0;
41196 +                               break;
41197 +                       case DWC_HCSPLIT_XACTPOS_BEGIN:
41198 +                       case DWC_HCSPLIT_XACTPOS_MID:
41199 +                               /*
41200 +                                * For BEGIN or MID, calculate the length for
41201 +                                * the next microframe to determine the correct
41202 +                                * SSPLIT token, either MID or END.
41203 +                                */
41204 +                               {
41205 +                                       struct dwc_otg_hcd_iso_packet_desc
41206 +                                       *frame_desc;
41207 +
41208 +                                       frame_desc =
41209 +                                           &qtd->urb->
41210 +                                           iso_descs[qtd->isoc_frame_index];
41211 +                                       qtd->isoc_split_offset += 188;
41212 +
41213 +                                       if ((frame_desc->length -
41214 +                                            qtd->isoc_split_offset) <= 188) {
41215 +                                               qtd->isoc_split_pos =
41216 +                                                   DWC_HCSPLIT_XACTPOS_END;
41217 +                                       } else {
41218 +                                               qtd->isoc_split_pos =
41219 +                                                   DWC_HCSPLIT_XACTPOS_MID;
41220 +                                       }
41221 +
41222 +                               }
41223 +                               break;
41224 +                       }
41225 +               } else {
41226 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41227 +               }
41228 +       } else {
41229 +               qtd->error_count = 0;
41230 +
41231 +               if (hc->qh->ping_state) {
41232 +                       hc->qh->ping_state = 0;
41233 +                       /*
41234 +                        * Halt the channel so the transfer can be re-started
41235 +                        * from the appropriate point. This only happens in
41236 +                        * Slave mode. In DMA mode, the ping_state is cleared
41237 +                        * when the transfer is started because the core
41238 +                        * automatically executes the PING, then the transfer.
41239 +                        */
41240 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41241 +               }
41242 +       }
41243 +
41244 +       /*
41245 +        * If the ACK occurred when _not_ in the PING state, let the channel
41246 +        * continue transferring data after clearing the error count.
41247 +        */
41248 +
41249 +       disable_hc_int(hc_regs, ack);
41250 +
41251 +       return 1;
41252 +}
41253 +
41254 +/**
41255 + * Handles a host channel NYET interrupt. This interrupt should only occur on
41256 + * Bulk and Control OUT endpoints and for complete split transactions. If a
41257 + * NYET occurs at the same time as a Transfer Complete interrupt, it is
41258 + * handled in the xfercomp interrupt handler, not here. This handler may be
41259 + * called in either DMA mode or Slave mode.
41260 + */
41261 +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
41262 +                                  dwc_hc_t * hc,
41263 +                                  dwc_otg_hc_regs_t * hc_regs,
41264 +                                  dwc_otg_qtd_t * qtd)
41265 +{
41266 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41267 +                   "NYET Received--\n", hc->hc_num);
41268 +
41269 +       /*
41270 +        * NYET on CSPLIT
41271 +        * re-do the CSPLIT immediately on non-periodic
41272 +        */
41273 +       if (hc->do_split && hc->complete_split) {
41274 +               if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
41275 +                   && hcd->core_if->dma_enable) {
41276 +                       qtd->complete_split = 0;
41277 +                       qtd->isoc_split_offset = 0;
41278 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
41279 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
41280 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
41281 +                       }
41282 +                       else
41283 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
41284 +                       goto handle_nyet_done;
41285 +               }
41286 +
41287 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41288 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41289 +                       int frnum = dwc_otg_hcd_get_frame_number(hcd);
41290 +
41291 +                       if (dwc_full_frame_num(frnum) !=
41292 +                           dwc_full_frame_num(hc->qh->sched_frame)) {
41293 +                               /*
41294 +                                * No longer in the same full speed frame.
41295 +                                * Treat this as a transaction error.
41296 +                                */
41297 +#if 0
41298 +                               /** @todo Fix system performance so this can
41299 +                                * be treated as an error. Right now complete
41300 +                                * splits cannot be scheduled precisely enough
41301 +                                * due to other system activity, so this error
41302 +                                * occurs regularly in Slave mode.
41303 +                                */
41304 +                               qtd->error_count++;
41305 +#endif
41306 +                               qtd->complete_split = 0;
41307 +                               halt_channel(hcd, hc, qtd,
41308 +                                            DWC_OTG_HC_XFER_XACT_ERR);
41309 +                               /** @todo add support for isoc release */
41310 +                               goto handle_nyet_done;
41311 +                       }
41312 +               }
41313 +
41314 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41315 +               goto handle_nyet_done;
41316 +       }
41317 +
41318 +       hc->qh->ping_state = 1;
41319 +       qtd->error_count = 0;
41320 +
41321 +       update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
41322 +                                  DWC_OTG_HC_XFER_NYET);
41323 +       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41324 +
41325 +       /*
41326 +        * Halt the channel and re-start the transfer so the PING
41327 +        * protocol will start.
41328 +        */
41329 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41330 +
41331 +handle_nyet_done:
41332 +       disable_hc_int(hc_regs, nyet);
41333 +       return 1;
41334 +}
41335 +
41336 +/**
41337 + * Handles a host channel babble interrupt. This handler may be called in
41338 + * either DMA mode or Slave mode.
41339 + */
41340 +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
41341 +                                    dwc_hc_t * hc,
41342 +                                    dwc_otg_hc_regs_t * hc_regs,
41343 +                                    dwc_otg_qtd_t * qtd)
41344 +{
41345 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41346 +                   "Babble Error--\n", hc->hc_num);
41347 +
41348 +       if (hcd->core_if->dma_desc_enable) {
41349 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41350 +                                              DWC_OTG_HC_XFER_BABBLE_ERR);
41351 +               goto handle_babble_done;
41352 +       }
41353 +
41354 +       if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
41355 +               hcd->fops->complete(hcd, qtd->urb->priv,
41356 +                                   qtd->urb, -DWC_E_OVERFLOW);
41357 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
41358 +       } else {
41359 +               dwc_otg_halt_status_e halt_status;
41360 +               halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41361 +                                                   DWC_OTG_HC_XFER_BABBLE_ERR);
41362 +               halt_channel(hcd, hc, qtd, halt_status);
41363 +       }
41364 +
41365 +handle_babble_done:
41366 +       disable_hc_int(hc_regs, bblerr);
41367 +       return 1;
41368 +}
41369 +
41370 +/**
41371 + * Handles a host channel AHB error interrupt. This handler is only called in
41372 + * DMA mode.
41373 + */
41374 +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
41375 +                                    dwc_hc_t * hc,
41376 +                                    dwc_otg_hc_regs_t * hc_regs,
41377 +                                    dwc_otg_qtd_t * qtd)
41378 +{
41379 +       hcchar_data_t hcchar;
41380 +       hcsplt_data_t hcsplt;
41381 +       hctsiz_data_t hctsiz;
41382 +       uint32_t hcdma;
41383 +       char *pipetype, *speed;
41384 +
41385 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
41386 +
41387 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41388 +                   "AHB Error--\n", hc->hc_num);
41389 +
41390 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41391 +       hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41392 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41393 +       hcdma = DWC_READ_REG32(&hc_regs->hcdma);
41394 +
41395 +       DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
41396 +       DWC_ERROR("  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
41397 +       DWC_ERROR("  hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
41398 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
41399 +       DWC_ERROR("  Device address: %d\n",
41400 +                 dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
41401 +       DWC_ERROR("  Endpoint: %d, %s\n",
41402 +                 dwc_otg_hcd_get_ep_num(&urb->pipe_info),
41403 +                 (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
41404 +
41405 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
41406 +       case UE_CONTROL:
41407 +               pipetype = "CONTROL";
41408 +               break;
41409 +       case UE_BULK:
41410 +               pipetype = "BULK";
41411 +               break;
41412 +       case UE_INTERRUPT:
41413 +               pipetype = "INTERRUPT";
41414 +               break;
41415 +       case UE_ISOCHRONOUS:
41416 +               pipetype = "ISOCHRONOUS";
41417 +               break;
41418 +       default:
41419 +               pipetype = "UNKNOWN";
41420 +               break;
41421 +       }
41422 +
41423 +       DWC_ERROR("  Endpoint type: %s\n", pipetype);
41424 +
41425 +       switch (hc->speed) {
41426 +       case DWC_OTG_EP_SPEED_HIGH:
41427 +               speed = "HIGH";
41428 +               break;
41429 +       case DWC_OTG_EP_SPEED_FULL:
41430 +               speed = "FULL";
41431 +               break;
41432 +       case DWC_OTG_EP_SPEED_LOW:
41433 +               speed = "LOW";
41434 +               break;
41435 +       default:
41436 +               speed = "UNKNOWN";
41437 +               break;
41438 +       };
41439 +
41440 +       DWC_ERROR("  Speed: %s\n", speed);
41441 +
41442 +       DWC_ERROR("  Max packet size: %d\n",
41443 +                 dwc_otg_hcd_get_mps(&urb->pipe_info));
41444 +       DWC_ERROR("  Data buffer length: %d\n", urb->length);
41445 +       DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",
41446 +                 urb->buf, (void *)urb->dma);
41447 +       DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",
41448 +                 urb->setup_packet, (void *)urb->setup_dma);
41449 +       DWC_ERROR("  Interval: %d\n", urb->interval);
41450 +
41451 +       /* Core haltes the channel for Descriptor DMA mode */
41452 +       if (hcd->core_if->dma_desc_enable) {
41453 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41454 +                                              DWC_OTG_HC_XFER_AHB_ERR);
41455 +               goto handle_ahberr_done;
41456 +       }
41457 +
41458 +       hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
41459 +
41460 +       /*
41461 +        * Force a channel halt. Don't call halt_channel because that won't
41462 +        * write to the HCCHARn register in DMA mode to force the halt.
41463 +        */
41464 +       dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
41465 +handle_ahberr_done:
41466 +       disable_hc_int(hc_regs, ahberr);
41467 +       return 1;
41468 +}
41469 +
41470 +/**
41471 + * Handles a host channel transaction error interrupt. This handler may be
41472 + * called in either DMA mode or Slave mode.
41473 + */
41474 +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
41475 +                                     dwc_hc_t * hc,
41476 +                                     dwc_otg_hc_regs_t * hc_regs,
41477 +                                     dwc_otg_qtd_t * qtd)
41478 +{
41479 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41480 +                   "Transaction Error--\n", hc->hc_num);
41481 +
41482 +       if (hcd->core_if->dma_desc_enable) {
41483 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41484 +                                              DWC_OTG_HC_XFER_XACT_ERR);
41485 +               goto handle_xacterr_done;
41486 +       }
41487 +
41488 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41489 +       case UE_CONTROL:
41490 +       case UE_BULK:
41491 +               qtd->error_count++;
41492 +               if (!hc->qh->ping_state) {
41493 +
41494 +                       update_urb_state_xfer_intr(hc, hc_regs,
41495 +                                                  qtd->urb, qtd,
41496 +                                                  DWC_OTG_HC_XFER_XACT_ERR);
41497 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41498 +                       if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
41499 +                               hc->qh->ping_state = 1;
41500 +                       }
41501 +               }
41502 +
41503 +               /*
41504 +                * Halt the channel so the transfer can be re-started from
41505 +                * the appropriate point or the PING protocol will start.
41506 +                */
41507 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41508 +               break;
41509 +       case UE_INTERRUPT:
41510 +               qtd->error_count++;
41511 +               if (hc->do_split && hc->complete_split) {
41512 +                       qtd->complete_split = 0;
41513 +               }
41514 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41515 +               break;
41516 +       case UE_ISOCHRONOUS:
41517 +               {
41518 +                       dwc_otg_halt_status_e halt_status;
41519 +                       halt_status =
41520 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41521 +                                                 DWC_OTG_HC_XFER_XACT_ERR);
41522 +
41523 +                       halt_channel(hcd, hc, qtd, halt_status);
41524 +               }
41525 +               break;
41526 +       }
41527 +handle_xacterr_done:
41528 +       disable_hc_int(hc_regs, xacterr);
41529 +
41530 +       return 1;
41531 +}
41532 +
41533 +/**
41534 + * Handles a host channel frame overrun interrupt. This handler may be called
41535 + * in either DMA mode or Slave mode.
41536 + */
41537 +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
41538 +                                      dwc_hc_t * hc,
41539 +                                      dwc_otg_hc_regs_t * hc_regs,
41540 +                                      dwc_otg_qtd_t * qtd)
41541 +{
41542 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41543 +                   "Frame Overrun--\n", hc->hc_num);
41544 +
41545 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41546 +       case UE_CONTROL:
41547 +       case UE_BULK:
41548 +               break;
41549 +       case UE_INTERRUPT:
41550 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
41551 +               break;
41552 +       case UE_ISOCHRONOUS:
41553 +               {
41554 +                       dwc_otg_halt_status_e halt_status;
41555 +                       halt_status =
41556 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41557 +                                                 DWC_OTG_HC_XFER_FRAME_OVERRUN);
41558 +
41559 +                       halt_channel(hcd, hc, qtd, halt_status);
41560 +               }
41561 +               break;
41562 +       }
41563 +
41564 +       disable_hc_int(hc_regs, frmovrun);
41565 +
41566 +       return 1;
41567 +}
41568 +
41569 +/**
41570 + * Handles a host channel data toggle error interrupt. This handler may be
41571 + * called in either DMA mode or Slave mode.
41572 + */
41573 +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
41574 +                                        dwc_hc_t * hc,
41575 +                                        dwc_otg_hc_regs_t * hc_regs,
41576 +                                        dwc_otg_qtd_t * qtd)
41577 +{
41578 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41579 +                   "Data Toggle Error--\n", hc->hc_num);
41580 +
41581 +       if (hc->ep_is_in) {
41582 +               qtd->error_count = 0;
41583 +       } else {
41584 +               DWC_ERROR("Data Toggle Error on OUT transfer,"
41585 +                         "channel %d\n", hc->hc_num);
41586 +       }
41587 +
41588 +       disable_hc_int(hc_regs, datatglerr);
41589 +
41590 +       return 1;
41591 +}
41592 +
41593 +#ifdef DEBUG
41594 +/**
41595 + * This function is for debug only. It checks that a valid halt status is set
41596 + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
41597 + * taken and a warning is issued.
41598 + * @return 1 if halt status is ok, 0 otherwise.
41599 + */
41600 +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
41601 +                                dwc_hc_t * hc,
41602 +                                dwc_otg_hc_regs_t * hc_regs,
41603 +                                dwc_otg_qtd_t * qtd)
41604 +{
41605 +       hcchar_data_t hcchar;
41606 +       hctsiz_data_t hctsiz;
41607 +       hcint_data_t hcint;
41608 +       hcintmsk_data_t hcintmsk;
41609 +       hcsplt_data_t hcsplt;
41610 +
41611 +       if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
41612 +               /*
41613 +                * This code is here only as a check. This condition should
41614 +                * never happen. Ignore the halt if it does occur.
41615 +                */
41616 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41617 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41618 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41619 +               hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41620 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41621 +               DWC_WARN
41622 +                   ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
41623 +                    "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
41624 +                    "hcint 0x%08x, hcintmsk 0x%08x, "
41625 +                    "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
41626 +                    hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
41627 +                    hcintmsk.d32, hcsplt.d32, qtd->complete_split);
41628 +
41629 +               DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
41630 +                        __func__, hc->hc_num);
41631 +               DWC_WARN("\n");
41632 +               clear_hc_int(hc_regs, chhltd);
41633 +               return 0;
41634 +       }
41635 +
41636 +       /*
41637 +        * This code is here only as a check. hcchar.chdis should
41638 +        * never be set when the halt interrupt occurs. Halt the
41639 +        * channel again if it does occur.
41640 +        */
41641 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41642 +       if (hcchar.b.chdis) {
41643 +               DWC_WARN("%s: hcchar.chdis set unexpectedly, "
41644 +                        "hcchar 0x%08x, trying to halt again\n",
41645 +                        __func__, hcchar.d32);
41646 +               clear_hc_int(hc_regs, chhltd);
41647 +               hc->halt_pending = 0;
41648 +               halt_channel(hcd, hc, qtd, hc->halt_status);
41649 +               return 0;
41650 +       }
41651 +
41652 +       return 1;
41653 +}
41654 +#endif
41655 +
41656 +/**
41657 + * Handles a host Channel Halted interrupt in DMA mode. This handler
41658 + * determines the reason the channel halted and proceeds accordingly.
41659 + */
41660 +static void handle_hc_chhltd_intr_dma(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 +       hcint_data_t hcint;
41666 +       hcintmsk_data_t hcintmsk;
41667 +       int out_nak_enh = 0;
41668 +
41669 +       /* For core with OUT NAK enhancement, the flow for high-
41670 +        * speed CONTROL/BULK OUT is handled a little differently.
41671 +        */
41672 +       if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
41673 +               if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
41674 +                   (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
41675 +                    hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
41676 +                       out_nak_enh = 1;
41677 +               }
41678 +       }
41679 +
41680 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
41681 +           (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
41682 +            && !hcd->core_if->dma_desc_enable)) {
41683 +               /*
41684 +                * Just release the channel. A dequeue can happen on a
41685 +                * transfer timeout. In the case of an AHB Error, the channel
41686 +                * was forced to halt because there's no way to gracefully
41687 +                * recover.
41688 +                */
41689 +               if (hcd->core_if->dma_desc_enable)
41690 +                       dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41691 +                                                      hc->halt_status);
41692 +               else
41693 +                       release_channel(hcd, hc, qtd, hc->halt_status);
41694 +               return;
41695 +       }
41696 +
41697 +       /* Read the HCINTn register to determine the cause for the halt. */
41698 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41699 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41700 +
41701 +       if (hcint.b.xfercomp) {
41702 +               /** @todo This is here because of a possible hardware bug.  Spec
41703 +                * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
41704 +                * interrupt w/ACK bit set should occur, but I only see the
41705 +                * XFERCOMP bit, even with it masked out.  This is a workaround
41706 +                * for that behavior.  Should fix this when hardware is fixed.
41707 +                */
41708 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41709 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41710 +               }
41711 +               handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
41712 +       } else if (hcint.b.stall) {
41713 +               handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
41714 +       } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
41715 +               if (out_nak_enh) {
41716 +                       if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
41717 +                               DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
41718 +                               qtd->error_count = 0;
41719 +                       } else {
41720 +                               DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
41721 +                       }
41722 +               }
41723 +
41724 +               /*
41725 +                * Must handle xacterr before nak or ack. Could get a xacterr
41726 +                * at the same time as either of these on a BULK/CONTROL OUT
41727 +                * that started with a PING. The xacterr takes precedence.
41728 +                */
41729 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41730 +       } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
41731 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41732 +       } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
41733 +               handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
41734 +       } else if (hcint.b.bblerr) {
41735 +               handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
41736 +       } else if (hcint.b.frmovrun) {
41737 +               handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
41738 +       } else if (!out_nak_enh) {
41739 +               if (hcint.b.nyet) {
41740 +                       /*
41741 +                        * Must handle nyet before nak or ack. Could get a nyet at the
41742 +                        * same time as either of those on a BULK/CONTROL OUT that
41743 +                        * started with a PING. The nyet takes precedence.
41744 +                        */
41745 +                       handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
41746 +               } else if (hcint.b.nak && !hcintmsk.b.nak) {
41747 +                       /*
41748 +                        * If nak is not masked, it's because a non-split IN transfer
41749 +                        * is in an error state. In that case, the nak is handled by
41750 +                        * the nak interrupt handler, not here. Handle nak here for
41751 +                        * BULK/CONTROL OUT transfers, which halt on a NAK to allow
41752 +                        * rewinding the buffer pointer.
41753 +                        */
41754 +                       handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
41755 +               } else if (hcint.b.ack && !hcintmsk.b.ack) {
41756 +                       /*
41757 +                        * If ack is not masked, it's because a non-split IN transfer
41758 +                        * is in an error state. In that case, the ack is handled by
41759 +                        * the ack interrupt handler, not here. Handle ack here for
41760 +                        * split transfers. Start splits halt on ACK.
41761 +                        */
41762 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41763 +               } else {
41764 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41765 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41766 +                               /*
41767 +                                * A periodic transfer halted with no other channel
41768 +                                * interrupts set. Assume it was halted by the core
41769 +                                * because it could not be completed in its scheduled
41770 +                                * (micro)frame.
41771 +                                */
41772 +#ifdef DEBUG
41773 +                               DWC_PRINTF
41774 +                                   ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
41775 +                                    __func__, hc->hc_num);
41776 +#endif
41777 +                               halt_channel(hcd, hc, qtd,
41778 +                                            DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
41779 +                       } else {
41780 +                               DWC_ERROR
41781 +                                   ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
41782 +                                    "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
41783 +                                    __func__, hc->hc_num, hcint.d32,
41784 +                                    DWC_READ_REG32(&hcd->
41785 +                                                   core_if->core_global_regs->
41786 +                                                   gintsts));
41787 +                       }
41788 +
41789 +               }
41790 +       } else {
41791 +               DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
41792 +                          hcint.d32);
41793 +       }
41794 +}
41795 +
41796 +/**
41797 + * Handles a host channel Channel Halted interrupt.
41798 + *
41799 + * In slave mode, this handler is called only when the driver specifically
41800 + * requests a halt. This occurs during handling other host channel interrupts
41801 + * (e.g. nak, xacterr, stall, nyet, etc.).
41802 + *
41803 + * In DMA mode, this is the interrupt that occurs when the core has finished
41804 + * processing a transfer on a channel. Other host channel interrupts (except
41805 + * ahberr) are disabled in DMA mode.
41806 + */
41807 +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
41808 +                                    dwc_hc_t * hc,
41809 +                                    dwc_otg_hc_regs_t * hc_regs,
41810 +                                    dwc_otg_qtd_t * qtd)
41811 +{
41812 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41813 +                   "Channel Halted--\n", hc->hc_num);
41814 +
41815 +       if (hcd->core_if->dma_enable) {
41816 +               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
41817 +       } else {
41818 +#ifdef DEBUG
41819 +               if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
41820 +                       return 1;
41821 +               }
41822 +#endif
41823 +               release_channel(hcd, hc, qtd, hc->halt_status);
41824 +       }
41825 +
41826 +       return 1;
41827 +}
41828 +
41829 +/** Handles interrupt for a specific Host Channel */
41830 +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
41831 +{
41832 +       int retval = 0;
41833 +       hcint_data_t hcint;
41834 +       hcintmsk_data_t hcintmsk;
41835 +       dwc_hc_t *hc;
41836 +       dwc_otg_hc_regs_t *hc_regs;
41837 +       dwc_otg_qtd_t *qtd;
41838 +
41839 +       DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
41840 +
41841 +       hc = dwc_otg_hcd->hc_ptr_array[num];
41842 +       hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
41843 +       qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
41844 +
41845 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41846 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41847 +       DWC_DEBUGPL(DBG_HCDV,
41848 +                   "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
41849 +                   hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
41850 +       hcint.d32 = hcint.d32 & hcintmsk.d32;
41851 +
41852 +       if (!dwc_otg_hcd->core_if->dma_enable) {
41853 +               if (hcint.b.chhltd && hcint.d32 != 0x2) {
41854 +                       hcint.b.chhltd = 0;
41855 +               }
41856 +       }
41857 +
41858 +       if (hcint.b.xfercomp) {
41859 +               retval |=
41860 +                   handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41861 +               /*
41862 +                * If NYET occurred at same time as Xfer Complete, the NYET is
41863 +                * handled by the Xfer Complete interrupt handler. Don't want
41864 +                * to call the NYET interrupt handler in this case.
41865 +                */
41866 +               hcint.b.nyet = 0;
41867 +       }
41868 +       if (hcint.b.chhltd) {
41869 +               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41870 +       }
41871 +       if (hcint.b.ahberr) {
41872 +               retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41873 +       }
41874 +       if (hcint.b.stall) {
41875 +               retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41876 +       }
41877 +       if (hcint.b.nak) {
41878 +               retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41879 +       }
41880 +       if (hcint.b.ack) {
41881 +               retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41882 +       }
41883 +       if (hcint.b.nyet) {
41884 +               retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41885 +       }
41886 +       if (hcint.b.xacterr) {
41887 +               retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41888 +       }
41889 +       if (hcint.b.bblerr) {
41890 +               retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41891 +       }
41892 +       if (hcint.b.frmovrun) {
41893 +               retval |=
41894 +                   handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41895 +       }
41896 +       if (hcint.b.datatglerr) {
41897 +               retval |=
41898 +                   handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41899 +       }
41900 +
41901 +       return retval;
41902 +}
41903 +
41904 +#endif /* DWC_DEVICE_ONLY */
41905 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41906 new file mode 100644
41907 index 0000000..e4787f5
41908 --- /dev/null
41909 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41910 @@ -0,0 +1,893 @@
41911 +/* ==========================================================================
41912 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
41913 + * $Revision: #20 $
41914 + * $Date: 2011/10/26 $
41915 + * $Change: 1872981 $
41916 + *
41917 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
41918 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
41919 + * otherwise expressly agreed to in writing between Synopsys and you.
41920 + *
41921 + * The Software IS NOT an item of Licensed Software or Licensed Product under
41922 + * any End User Software License Agreement or Agreement for Licensed Product
41923 + * with Synopsys or any supplement thereto. You are permitted to use and
41924 + * redistribute this Software in source and binary forms, with or without
41925 + * modification, provided that redistributions of source code must retain this
41926 + * notice. You may not view, use, disclose, copy or distribute this file or
41927 + * any information contained herein except pursuant to this license grant from
41928 + * Synopsys. If you do not agree with this notice, including the disclaimer
41929 + * below, then you are not authorized to use the Software.
41930 + *
41931 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
41932 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41933 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41934 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
41935 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41936 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41937 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41938 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41939 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41940 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41941 + * DAMAGE.
41942 + * ========================================================================== */
41943 +#ifndef DWC_DEVICE_ONLY
41944 +
41945 +/**
41946 + * @file
41947 + *
41948 + * This file contains the implementation of the HCD. In Linux, the HCD
41949 + * implements the hc_driver API.
41950 + */
41951 +#include <linux/kernel.h>
41952 +#include <linux/module.h>
41953 +#include <linux/moduleparam.h>
41954 +#include <linux/init.h>
41955 +#include <linux/device.h>
41956 +#include <linux/errno.h>
41957 +#include <linux/list.h>
41958 +#include <linux/interrupt.h>
41959 +#include <linux/string.h>
41960 +#include <linux/dma-mapping.h>
41961 +#include <linux/version.h>
41962 +#include <asm/io.h>
41963 +#include <linux/usb.h>
41964 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
41965 +#include <../drivers/usb/core/hcd.h>
41966 +#else
41967 +#include <linux/usb/hcd.h>
41968 +#endif
41969 +
41970 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
41971 +#define USB_URB_EP_LINKING 1
41972 +#else
41973 +#define USB_URB_EP_LINKING 0
41974 +#endif
41975 +
41976 +#include "dwc_otg_hcd_if.h"
41977 +#include "dwc_otg_dbg.h"
41978 +#include "dwc_otg_driver.h"
41979 +#include "dwc_otg_hcd.h"
41980 +/**
41981 + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
41982 + * qualified with its direction (possible 32 endpoints per device).
41983 + */
41984 +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
41985 +                                                    ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
41986 +
41987 +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
41988 +
41989 +/** @name Linux HC Driver API Functions */
41990 +/** @{ */
41991 +/* manage i/o requests, device state */
41992 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
41993 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41994 +                      struct usb_host_endpoint *ep,
41995 +#endif
41996 +                      struct urb *urb, gfp_t mem_flags);
41997 +
41998 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
41999 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42000 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
42001 +#endif
42002 +#else /* kernels at or post 2.6.30 */
42003 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,
42004 +                               struct urb *urb, int status);
42005 +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
42006 +
42007 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
42008 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42009 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
42010 +#endif
42011 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
42012 +extern int hcd_start(struct usb_hcd *hcd);
42013 +extern void hcd_stop(struct usb_hcd *hcd);
42014 +static int get_frame_number(struct usb_hcd *hcd);
42015 +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
42016 +extern int hub_control(struct usb_hcd *hcd,
42017 +                      u16 typeReq,
42018 +                      u16 wValue, u16 wIndex, char *buf, u16 wLength);
42019 +
42020 +struct wrapper_priv_data {
42021 +       dwc_otg_hcd_t *dwc_otg_hcd;
42022 +};
42023 +
42024 +/** @} */
42025 +
42026 +static struct hc_driver dwc_otg_hc_driver = {
42027 +
42028 +       .description = dwc_otg_hcd_name,
42029 +       .product_desc = "DWC OTG Controller",
42030 +       .hcd_priv_size = sizeof(struct wrapper_priv_data),
42031 +
42032 +       .irq = dwc_otg_hcd_irq,
42033 +
42034 +       .flags = HCD_MEMORY | HCD_USB2,
42035 +
42036 +       //.reset =
42037 +       .start = hcd_start,
42038 +       //.suspend =
42039 +       //.resume =
42040 +       .stop = hcd_stop,
42041 +
42042 +       .urb_enqueue = dwc_otg_urb_enqueue,
42043 +       .urb_dequeue = dwc_otg_urb_dequeue,
42044 +       .endpoint_disable = endpoint_disable,
42045 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42046 +       .endpoint_reset = endpoint_reset,
42047 +#endif
42048 +       .get_frame_number = get_frame_number,
42049 +
42050 +       .hub_status_data = hub_status_data,
42051 +       .hub_control = hub_control,
42052 +       //.bus_suspend =
42053 +       //.bus_resume =
42054 +};
42055 +
42056 +/** Gets the dwc_otg_hcd from a struct usb_hcd */
42057 +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
42058 +{
42059 +       struct wrapper_priv_data *p;
42060 +       p = (struct wrapper_priv_data *)(hcd->hcd_priv);
42061 +       return p->dwc_otg_hcd;
42062 +}
42063 +
42064 +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
42065 +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
42066 +{
42067 +       return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
42068 +}
42069 +
42070 +/** Gets the usb_host_endpoint associated with an URB. */
42071 +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
42072 +{
42073 +       struct usb_device *dev = urb->dev;
42074 +       int ep_num = usb_pipeendpoint(urb->pipe);
42075 +
42076 +       if (usb_pipein(urb->pipe))
42077 +               return dev->ep_in[ep_num];
42078 +       else
42079 +               return dev->ep_out[ep_num];
42080 +}
42081 +
42082 +static int _disconnect(dwc_otg_hcd_t * hcd)
42083 +{
42084 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42085 +
42086 +       usb_hcd->self.is_b_host = 0;
42087 +       return 0;
42088 +}
42089 +
42090 +static int _start(dwc_otg_hcd_t * hcd)
42091 +{
42092 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42093 +
42094 +       usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
42095 +       hcd_start(usb_hcd);
42096 +
42097 +       return 0;
42098 +}
42099 +
42100 +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
42101 +                    uint32_t * port_addr)
42102 +{
42103 +   struct urb *urb = (struct urb *)urb_handle;
42104 +   struct usb_bus *bus;
42105 +#if 1 //GRAYG - temporary
42106 +   if (NULL == urb_handle)
42107 +      DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
42108 +   if (NULL == urb->dev)
42109 +      DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
42110 +   if (NULL == port_addr)
42111 +      DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
42112 +#endif
42113 +   if (urb->dev->tt) {
42114 +        if (NULL == urb->dev->tt->hub) {
42115 +                DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
42116 +                           __func__); //GRAYG
42117 +                //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
42118 +                *hub_addr = 0; //GRAYG
42119 +                // we probably shouldn't have a transaction translator if
42120 +                // there's no associated hub?
42121 +        } else {
42122 +               bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
42123 +               if (urb->dev->tt->hub == bus->root_hub)
42124 +                       *hub_addr = 0;
42125 +               else
42126 +                       *hub_addr = urb->dev->tt->hub->devnum;
42127 +       }
42128 +       *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
42129 +   } else {
42130 +        *hub_addr = 0;
42131 +       *port_addr = urb->dev->ttport;
42132 +   }
42133 +   return 0;
42134 +}
42135 +
42136 +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
42137 +{
42138 +       struct urb *urb = (struct urb *)urb_handle;
42139 +       return urb->dev->speed;
42140 +}
42141 +
42142 +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
42143 +{
42144 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42145 +       return usb_hcd->self.b_hnp_enable;
42146 +}
42147 +
42148 +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42149 +                                  struct urb *urb)
42150 +{
42151 +       hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
42152 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42153 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
42154 +       } else {
42155 +               hcd_to_bus(hcd)->bandwidth_int_reqs++;
42156 +       }
42157 +}
42158 +
42159 +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42160 +                              struct urb *urb)
42161 +{
42162 +       hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
42163 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42164 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
42165 +       } else {
42166 +               hcd_to_bus(hcd)->bandwidth_int_reqs--;
42167 +       }
42168 +}
42169 +
42170 +/**
42171 + * Sets the final status of an URB and returns it to the device driver. Any
42172 + * required cleanup of the URB is performed.
42173 + */
42174 +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
42175 +                    dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
42176 +{
42177 +       struct urb *urb = (struct urb *)urb_handle;
42178 +
42179 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42180 +               DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
42181 +                          __func__, urb, usb_pipedevice(urb->pipe),
42182 +                          usb_pipeendpoint(urb->pipe),
42183 +                          usb_pipein(urb->pipe) ? "IN" : "OUT", status);
42184 +               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42185 +                       int i;
42186 +                       for (i = 0; i < urb->number_of_packets; i++) {
42187 +                               DWC_PRINTF("  ISO Desc %d status: %d\n",
42188 +                                          i, urb->iso_frame_desc[i].status);
42189 +                       }
42190 +               }
42191 +       }
42192 +
42193 +       urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
42194 +       /* Convert status value. */
42195 +       switch (status) {
42196 +       case -DWC_E_PROTOCOL:
42197 +               status = -EPROTO;
42198 +               break;
42199 +       case -DWC_E_IN_PROGRESS:
42200 +               status = -EINPROGRESS;
42201 +               break;
42202 +       case -DWC_E_PIPE:
42203 +               status = -EPIPE;
42204 +               break;
42205 +       case -DWC_E_IO:
42206 +               status = -EIO;
42207 +               break;
42208 +       case -DWC_E_TIMEOUT:
42209 +               status = -ETIMEDOUT;
42210 +               break;
42211 +       case -DWC_E_OVERFLOW:
42212 +               status = -EOVERFLOW;
42213 +               break;
42214 +       default:
42215 +               if (status) {
42216 +                       DWC_PRINTF("Uknown urb status %d\n", status);
42217 +
42218 +               }
42219 +       }
42220 +
42221 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42222 +               int i;
42223 +
42224 +               urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
42225 +               for (i = 0; i < urb->number_of_packets; ++i) {
42226 +                       urb->iso_frame_desc[i].actual_length =
42227 +                           dwc_otg_hcd_urb_get_iso_desc_actual_length
42228 +                           (dwc_otg_urb, i);
42229 +                       urb->iso_frame_desc[i].status =
42230 +                           dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
42231 +               }
42232 +       }
42233 +
42234 +       urb->status = status;
42235 +       urb->hcpriv = NULL;
42236 +       if (!status) {
42237 +               if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
42238 +                   (urb->actual_length < urb->transfer_buffer_length)) {
42239 +                       urb->status = -EREMOTEIO;
42240 +               }
42241 +       }
42242 +
42243 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
42244 +           (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42245 +               struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
42246 +               if (ep) {
42247 +                       free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
42248 +                                          dwc_otg_hcd_get_ep_bandwidth(hcd,
42249 +                                                                       ep->hcpriv),
42250 +                                          urb);
42251 +               }
42252 +       }
42253 +
42254 +       DWC_FREE(dwc_otg_urb);
42255 +
42256 +#if USB_URB_EP_LINKING
42257 +        usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
42258 +#endif
42259 +       DWC_SPINUNLOCK(hcd->lock);
42260 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42261 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
42262 +#else
42263 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
42264 +#endif
42265 +       DWC_SPINLOCK(hcd->lock);
42266 +
42267 +       return 0;
42268 +}
42269 +
42270 +static struct dwc_otg_hcd_function_ops hcd_fops = {
42271 +       .start = _start,
42272 +       .disconnect = _disconnect,
42273 +       .hub_info = _hub_info,
42274 +       .speed = _speed,
42275 +       .complete = _complete,
42276 +       .get_b_hnp_enable = _get_b_hnp_enable,
42277 +};
42278 +
42279 +/**
42280 + * Initializes the HCD. This function allocates memory for and initializes the
42281 + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
42282 + * USB bus with the core and calls the hc_driver->start() function. It returns
42283 + * a negative error on failure.
42284 + */
42285 +int hcd_init(dwc_bus_dev_t *_dev)
42286 +{
42287 +       struct usb_hcd *hcd = NULL;
42288 +       dwc_otg_hcd_t *dwc_otg_hcd = NULL;
42289 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42290 +       int retval = 0;
42291 +        u64 dmamask;
42292 +
42293 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
42294 +
42295 +       /* Set device flags indicating whether the HCD supports DMA. */
42296 +       if (dwc_otg_is_dma_enable(otg_dev->core_if))
42297 +                dmamask = DMA_BIT_MASK(32);
42298 +        else
42299 +                dmamask = 0;
42300 +
42301 +#if    defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
42302 +        dma_set_mask(&_dev->dev, dmamask);
42303 +        dma_set_coherent_mask(&_dev->dev, dmamask);
42304 +#elif  defined(PCI_INTERFACE)
42305 +        pci_set_dma_mask(_dev, dmamask);
42306 +        pci_set_consistent_dma_mask(_dev, dmamask);
42307 +#endif
42308 +
42309 +       /*
42310 +        * Allocate memory for the base HCD plus the DWC OTG HCD.
42311 +        * Initialize the base HCD.
42312 +        */
42313 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
42314 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
42315 +#else
42316 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
42317 +       hcd->has_tt = 1;
42318 +//      hcd->uses_new_polling = 1;
42319 +//      hcd->poll_rh = 0;
42320 +#endif
42321 +       if (!hcd) {
42322 +               retval = -ENOMEM;
42323 +               goto error1;
42324 +       }
42325 +
42326 +       hcd->regs = otg_dev->os_dep.base;
42327 +
42328 +       /* Initialize the DWC OTG HCD. */
42329 +       dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
42330 +       if (!dwc_otg_hcd) {
42331 +               goto error2;
42332 +       }
42333 +       ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
42334 +           dwc_otg_hcd;
42335 +       otg_dev->hcd = dwc_otg_hcd;
42336 +
42337 +       if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
42338 +               goto error2;
42339 +       }
42340 +
42341 +       otg_dev->hcd->otg_dev = otg_dev;
42342 +       hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
42343 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
42344 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later
42345 +       hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
42346 +#endif
42347 +       /* Don't support SG list at this point */
42348 +       hcd->self.sg_tablesize = 0;
42349 +#endif
42350 +       /*
42351 +        * Finish generic HCD initialization and start the HCD. This function
42352 +        * allocates the DMA buffer pool, registers the USB bus, requests the
42353 +        * IRQ line, and calls hcd_start method.
42354 +        */
42355 +#ifdef PLATFORM_INTERFACE
42356 +        retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
42357 +#else
42358 +        retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
42359 +#endif
42360 +       if (retval < 0) {
42361 +               goto error2;
42362 +       }
42363 +
42364 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
42365 +       return 0;
42366 +
42367 +error2:
42368 +       usb_put_hcd(hcd);
42369 +error1:
42370 +       return retval;
42371 +}
42372 +
42373 +/**
42374 + * Removes the HCD.
42375 + * Frees memory and resources associated with the HCD and deregisters the bus.
42376 + */
42377 +void hcd_remove(dwc_bus_dev_t *_dev)
42378 +{
42379 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42380 +       dwc_otg_hcd_t *dwc_otg_hcd;
42381 +       struct usb_hcd *hcd;
42382 +
42383 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
42384 +
42385 +       if (!otg_dev) {
42386 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
42387 +               return;
42388 +       }
42389 +
42390 +       dwc_otg_hcd = otg_dev->hcd;
42391 +
42392 +       if (!dwc_otg_hcd) {
42393 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
42394 +               return;
42395 +       }
42396 +
42397 +       hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
42398 +
42399 +       if (!hcd) {
42400 +               DWC_DEBUGPL(DBG_ANY,
42401 +                           "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
42402 +                           __func__);
42403 +               return;
42404 +       }
42405 +       usb_remove_hcd(hcd);
42406 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
42407 +       dwc_otg_hcd_remove(dwc_otg_hcd);
42408 +       usb_put_hcd(hcd);
42409 +}
42410 +
42411 +/* =========================================================================
42412 + *  Linux HC Driver Functions
42413 + * ========================================================================= */
42414 +
42415 +/** Initializes the DWC_otg controller and its root hub and prepares it for host
42416 + * mode operation. Activates the root port. Returns 0 on success and a negative
42417 + * error code on failure. */
42418 +int hcd_start(struct usb_hcd *hcd)
42419 +{
42420 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42421 +       struct usb_bus *bus;
42422 +
42423 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
42424 +       bus = hcd_to_bus(hcd);
42425 +
42426 +       hcd->state = HC_STATE_RUNNING;
42427 +       if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
42428 +               return 0;
42429 +       }
42430 +
42431 +       /* Initialize and connect root hub if one is not already attached */
42432 +       if (bus->root_hub) {
42433 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
42434 +               /* Inform the HUB driver to resume. */
42435 +               usb_hcd_resume_root_hub(hcd);
42436 +       }
42437 +
42438 +       return 0;
42439 +}
42440 +
42441 +/**
42442 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
42443 + * stopped.
42444 + */
42445 +void hcd_stop(struct usb_hcd *hcd)
42446 +{
42447 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42448 +
42449 +       dwc_otg_hcd_stop(dwc_otg_hcd);
42450 +}
42451 +
42452 +/** Returns the current frame number. */
42453 +static int get_frame_number(struct usb_hcd *hcd)
42454 +{
42455 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42456 +
42457 +       return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
42458 +}
42459 +
42460 +#ifdef DEBUG
42461 +static void dump_urb_info(struct urb *urb, char *fn_name)
42462 +{
42463 +       DWC_PRINTF("%s, urb %p\n", fn_name, urb);
42464 +       DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));
42465 +       DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
42466 +                  (usb_pipein(urb->pipe) ? "IN" : "OUT"));
42467 +       DWC_PRINTF("  Endpoint type: %s\n", ( {
42468 +                                            char *pipetype;
42469 +                                            switch (usb_pipetype(urb->pipe)) {
42470 +case PIPE_CONTROL:
42471 +pipetype = "CONTROL"; break; case PIPE_BULK:
42472 +pipetype = "BULK"; break; case PIPE_INTERRUPT:
42473 +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
42474 +pipetype = "ISOCHRONOUS"; break; default:
42475 +                                            pipetype = "UNKNOWN"; break;};
42476 +                                            pipetype;}
42477 +                  )) ;
42478 +       DWC_PRINTF("  Speed: %s\n", ( {
42479 +                                    char *speed; switch (urb->dev->speed) {
42480 +case USB_SPEED_HIGH:
42481 +speed = "HIGH"; break; case USB_SPEED_FULL:
42482 +speed = "FULL"; break; case USB_SPEED_LOW:
42483 +speed = "LOW"; break; default:
42484 +                                    speed = "UNKNOWN"; break;};
42485 +                                    speed;}
42486 +                  )) ;
42487 +       DWC_PRINTF("  Max packet size: %d\n",
42488 +                  usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
42489 +       DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);
42490 +       DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",
42491 +                  urb->transfer_buffer, (void *)urb->transfer_dma);
42492 +       DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",
42493 +                  urb->setup_packet, (void *)urb->setup_dma);
42494 +       DWC_PRINTF("  Interval: %d\n", urb->interval);
42495 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42496 +               int i;
42497 +               for (i = 0; i < urb->number_of_packets; i++) {
42498 +                       DWC_PRINTF("  ISO Desc %d:\n", i);
42499 +                       DWC_PRINTF("    offset: %d, length %d\n",
42500 +                                  urb->iso_frame_desc[i].offset,
42501 +                                  urb->iso_frame_desc[i].length);
42502 +               }
42503 +       }
42504 +}
42505 +#endif
42506 +
42507 +/** Starts processing a USB transfer request specified by a USB Request Block
42508 + * (URB). mem_flags indicates the type of memory allocation to use while
42509 + * processing this URB. */
42510 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
42511 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42512 +                      struct usb_host_endpoint *ep,
42513 +#endif
42514 +                      struct urb *urb, gfp_t mem_flags)
42515 +{
42516 +       int retval = 0;
42517 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
42518 +       struct usb_host_endpoint *ep = urb->ep;
42519 +#endif
42520 +#if USB_URB_EP_LINKING
42521 +       dwc_irqflags_t irqflags;
42522 +#endif
42523 +        void **ref_ep_hcpriv = &ep->hcpriv;
42524 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42525 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
42526 +       int i;
42527 +       int alloc_bandwidth = 0;
42528 +       uint8_t ep_type = 0;
42529 +       uint32_t flags = 0;
42530 +       void *buf;
42531 +
42532 +#ifdef DEBUG
42533 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42534 +               dump_urb_info(urb, "dwc_otg_urb_enqueue");
42535 +       }
42536 +#endif
42537 +
42538 +       if (!urb->transfer_buffer && urb->transfer_buffer_length)
42539 +               return -EINVAL;
42540 +
42541 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
42542 +           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42543 +               if (!dwc_otg_hcd_is_bandwidth_allocated
42544 +                   (dwc_otg_hcd, ref_ep_hcpriv)) {
42545 +                       alloc_bandwidth = 1;
42546 +               }
42547 +       }
42548 +
42549 +       switch (usb_pipetype(urb->pipe)) {
42550 +       case PIPE_CONTROL:
42551 +               ep_type = USB_ENDPOINT_XFER_CONTROL;
42552 +               break;
42553 +       case PIPE_ISOCHRONOUS:
42554 +               ep_type = USB_ENDPOINT_XFER_ISOC;
42555 +               break;
42556 +       case PIPE_BULK:
42557 +               ep_type = USB_ENDPOINT_XFER_BULK;
42558 +               break;
42559 +       case PIPE_INTERRUPT:
42560 +               ep_type = USB_ENDPOINT_XFER_INT;
42561 +               break;
42562 +       default:
42563 +                DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));
42564 +       }
42565 +
42566 +        /* # of packets is often 0 - do we really need to call this then? */
42567 +       dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
42568 +                                           urb->number_of_packets,
42569 +                                           mem_flags == GFP_ATOMIC ? 1 : 0);
42570 +
42571 +       if(dwc_otg_urb == NULL)
42572 +               return -ENOMEM;
42573 +
42574 +        urb->hcpriv = dwc_otg_urb;
42575 +        if (!dwc_otg_urb && urb->number_of_packets)
42576 +                return -ENOMEM;
42577 +
42578 +       dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
42579 +                                    usb_pipeendpoint(urb->pipe), ep_type,
42580 +                                    usb_pipein(urb->pipe),
42581 +                                    usb_maxpacket(urb->dev, urb->pipe,
42582 +                                                  !(usb_pipein(urb->pipe))));
42583 +
42584 +       buf = urb->transfer_buffer;
42585 +       if (hcd->self.uses_dma) {
42586 +               /*
42587 +                * Calculate virtual address from physical address,
42588 +                * because some class driver may not fill transfer_buffer.
42589 +                * In Buffer DMA mode virual address is used,
42590 +                * when handling non DWORD aligned buffers.
42591 +                */
42592 +               //buf = phys_to_virt(urb->transfer_dma);
42593 +                // DMA addresses are bus addresses not physical addresses!
42594 +                buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
42595 +       }
42596 +
42597 +       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
42598 +               flags |= URB_GIVEBACK_ASAP;
42599 +       if (urb->transfer_flags & URB_ZERO_PACKET)
42600 +               flags |= URB_SEND_ZERO_PACKET;
42601 +
42602 +       dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
42603 +                                  urb->transfer_dma,
42604 +                                  urb->transfer_buffer_length,
42605 +                                  urb->setup_packet,
42606 +                                  urb->setup_dma, flags, urb->interval);
42607 +
42608 +       for (i = 0; i < urb->number_of_packets; ++i) {
42609 +               dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
42610 +                                                   urb->
42611 +                                                   iso_frame_desc[i].offset,
42612 +                                                   urb->
42613 +                                                   iso_frame_desc[i].length);
42614 +       }
42615 +
42616 +#if USB_URB_EP_LINKING
42617 +        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42618 +       retval = usb_hcd_link_urb_to_ep(hcd, urb);
42619 +        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42620 +       if (0 == retval)
42621 +#endif
42622 +        {
42623 +                retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
42624 +                                                 /*(dwc_otg_qh_t **)*/
42625 +                                                 ref_ep_hcpriv,
42626 +                                                 mem_flags == GFP_ATOMIC ? 1 : 0);
42627 +                if (0 == retval) {
42628 +                        if (alloc_bandwidth) {
42629 +                                allocate_bus_bandwidth(hcd,
42630 +                                        dwc_otg_hcd_get_ep_bandwidth(
42631 +                                                dwc_otg_hcd, *ref_ep_hcpriv),
42632 +                                                       urb);
42633 +                        }
42634 +                } else {
42635 +#if USB_URB_EP_LINKING
42636 +                       dwc_irqflags_t irqflags;
42637 +                        DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
42638 +                        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42639 +                        usb_hcd_unlink_urb_from_ep(hcd, urb);
42640 +                        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42641 +#endif
42642 +                        if (retval == -DWC_E_NO_DEVICE) {
42643 +                                retval = -ENODEV;
42644 +                        }
42645 +                }
42646 +        }
42647 +       return retval;
42648 +}
42649 +
42650 +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
42651 + * success.  */
42652 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42653 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
42654 +#else
42655 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
42656 +#endif
42657 +{
42658 +       dwc_irqflags_t flags;
42659 +       dwc_otg_hcd_t *dwc_otg_hcd;
42660 +        int rc;
42661 +
42662 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
42663 +
42664 +       dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42665 +
42666 +#ifdef DEBUG
42667 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42668 +               dump_urb_info(urb, "dwc_otg_urb_dequeue");
42669 +       }
42670 +#endif
42671 +
42672 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42673 +       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
42674 +       if (0 == rc) {
42675 +               if(urb->hcpriv != NULL) {
42676 +                       dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,
42677 +                                           (dwc_otg_hcd_urb_t *)urb->hcpriv);
42678 +
42679 +                       DWC_FREE(urb->hcpriv);
42680 +                       urb->hcpriv = NULL;
42681 +               }
42682 +        }
42683 +
42684 +        if (0 == rc) {
42685 +               /* Higher layer software sets URB status. */
42686 +#if USB_URB_EP_LINKING
42687 +                usb_hcd_unlink_urb_from_ep(hcd, urb);
42688 +#endif
42689 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42690 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42691 +                usb_hcd_giveback_urb(hcd, urb);
42692 +#else
42693 +                usb_hcd_giveback_urb(hcd, urb, status);
42694 +#endif
42695 +                if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42696 +                        DWC_PRINTF("Called usb_hcd_giveback_urb() \n");
42697 +                        DWC_PRINTF("  1urb->status = %d\n", urb->status);
42698 +                }
42699 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");
42700 +        } else {
42701 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42702 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",
42703 +                            rc);
42704 +        }
42705 +
42706 +       return rc;
42707 +}
42708 +
42709 +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
42710 + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
42711 + * must already be dequeued. */
42712 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42713 +{
42714 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42715 +
42716 +       DWC_DEBUGPL(DBG_HCD,
42717 +                   "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
42718 +                   "endpoint=%d\n", ep->desc.bEndpointAddress,
42719 +                   dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
42720 +       dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
42721 +       ep->hcpriv = NULL;
42722 +}
42723 +
42724 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42725 +/* Resets endpoint specific parameter values, in current version used to reset
42726 + * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
42727 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42728 +{
42729 +       dwc_irqflags_t flags;
42730 +       struct usb_device *udev = NULL;
42731 +       int epnum = usb_endpoint_num(&ep->desc);
42732 +       int is_out = usb_endpoint_dir_out(&ep->desc);
42733 +       int is_control = usb_endpoint_xfer_control(&ep->desc);
42734 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42735 +        struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);
42736 +
42737 +       if (dev)
42738 +               udev = to_usb_device(dev);
42739 +       else
42740 +               return;
42741 +
42742 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
42743 +
42744 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42745 +       usb_settoggle(udev, epnum, is_out, 0);
42746 +       if (is_control)
42747 +               usb_settoggle(udev, epnum, !is_out, 0);
42748 +
42749 +       if (ep->hcpriv) {
42750 +               dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
42751 +       }
42752 +       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42753 +}
42754 +#endif
42755 +
42756 +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
42757 + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
42758 + * interrupt.
42759 + *
42760 + * This function is called by the USB core when an interrupt occurs */
42761 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
42762 +{
42763 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42764 +       int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
42765 +       if (retval != 0) {
42766 +               S3C2410X_CLEAR_EINTPEND();
42767 +       }
42768 +       return IRQ_RETVAL(retval);
42769 +}
42770 +
42771 +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
42772 + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
42773 + * is the status change indicator for the single root port. Returns 1 if either
42774 + * change indicator is 1, otherwise returns 0. */
42775 +int hub_status_data(struct usb_hcd *hcd, char *buf)
42776 +{
42777 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42778 +
42779 +       buf[0] = 0;
42780 +       buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
42781 +
42782 +       return (buf[0] != 0);
42783 +}
42784 +
42785 +/** Handles hub class-specific requests. */
42786 +int hub_control(struct usb_hcd *hcd,
42787 +               u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
42788 +{
42789 +       int retval;
42790 +
42791 +       retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
42792 +                                        typeReq, wValue, wIndex, buf, wLength);
42793 +
42794 +       switch (retval) {
42795 +       case -DWC_E_INVALID:
42796 +               retval = -EINVAL;
42797 +               break;
42798 +       }
42799 +
42800 +       return retval;
42801 +}
42802 +
42803 +#endif /* DWC_DEVICE_ONLY */
42804 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42805 new file mode 100644
42806 index 0000000..0a1cbb7
42807 --- /dev/null
42808 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42809 @@ -0,0 +1,923 @@
42810 +/* ==========================================================================
42811 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
42812 + * $Revision: #44 $
42813 + * $Date: 2011/10/26 $
42814 + * $Change: 1873028 $
42815 + *
42816 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42817 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
42818 + * otherwise expressly agreed to in writing between Synopsys and you.
42819 + *
42820 + * The Software IS NOT an item of Licensed Software or Licensed Product under
42821 + * any End User Software License Agreement or Agreement for Licensed Product
42822 + * with Synopsys or any supplement thereto. You are permitted to use and
42823 + * redistribute this Software in source and binary forms, with or without
42824 + * modification, provided that redistributions of source code must retain this
42825 + * notice. You may not view, use, disclose, copy or distribute this file or
42826 + * any information contained herein except pursuant to this license grant from
42827 + * Synopsys. If you do not agree with this notice, including the disclaimer
42828 + * below, then you are not authorized to use the Software.
42829 + *
42830 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
42831 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42832 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42833 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
42834 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42835 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42836 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42837 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42838 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42839 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
42840 + * DAMAGE.
42841 + * ========================================================================== */
42842 +#ifndef DWC_DEVICE_ONLY
42843 +
42844 +/**
42845 + * @file
42846 + *
42847 + * This file contains the functions to manage Queue Heads and Queue
42848 + * Transfer Descriptors.
42849 + */
42850 +
42851 +#include "dwc_otg_hcd.h"
42852 +#include "dwc_otg_regs.h"
42853 +
42854 +extern bool microframe_schedule;
42855 +
42856 +/**
42857 + * Free each QTD in the QH's QTD-list then free the QH.  QH should already be
42858 + * removed from a list.  QTD list should already be empty if called from URB
42859 + * Dequeue.
42860 + *
42861 + * @param hcd HCD instance.
42862 + * @param qh The QH to free.
42863 + */
42864 +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
42865 +{
42866 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
42867 +       dwc_irqflags_t flags;
42868 +
42869 +       /* Free each QTD in the QTD list */
42870 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
42871 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
42872 +               DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
42873 +               dwc_otg_hcd_qtd_free(qtd);
42874 +       }
42875 +
42876 +       if (hcd->core_if->dma_desc_enable) {
42877 +               dwc_otg_hcd_qh_free_ddma(hcd, qh);
42878 +       } else if (qh->dw_align_buf) {
42879 +               uint32_t buf_size;
42880 +               if (qh->ep_type == UE_ISOCHRONOUS) {
42881 +                       buf_size = 4096;
42882 +               } else {
42883 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
42884 +               }
42885 +               DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
42886 +       }
42887 +
42888 +       DWC_FREE(qh);
42889 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
42890 +       return;
42891 +}
42892 +
42893 +#define BitStuffTime(bytecount)  ((8 * 7* bytecount) / 6)
42894 +#define HS_HOST_DELAY          5       /* nanoseconds */
42895 +#define FS_LS_HOST_DELAY       1000    /* nanoseconds */
42896 +#define HUB_LS_SETUP           333     /* nanoseconds */
42897 +#define NS_TO_US(ns)           ((ns + 500) / 1000)
42898 +                               /* convert & round nanoseconds to microseconds */
42899 +
42900 +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)
42901 +{
42902 +       unsigned long retval;
42903 +
42904 +       switch (speed) {
42905 +       case USB_SPEED_HIGH:
42906 +               if (is_isoc) {
42907 +                       retval =
42908 +                           ((38 * 8 * 2083) +
42909 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42910 +                           HS_HOST_DELAY;
42911 +               } else {
42912 +                       retval =
42913 +                           ((55 * 8 * 2083) +
42914 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42915 +                           HS_HOST_DELAY;
42916 +               }
42917 +               break;
42918 +       case USB_SPEED_FULL:
42919 +               if (is_isoc) {
42920 +                       retval =
42921 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42922 +                       if (is_in) {
42923 +                               retval = 7268 + FS_LS_HOST_DELAY + retval;
42924 +                       } else {
42925 +                               retval = 6265 + FS_LS_HOST_DELAY + retval;
42926 +                       }
42927 +               } else {
42928 +                       retval =
42929 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42930 +                       retval = 9107 + FS_LS_HOST_DELAY + retval;
42931 +               }
42932 +               break;
42933 +       case USB_SPEED_LOW:
42934 +               if (is_in) {
42935 +                       retval =
42936 +                           (67667 * (31 + 10 * BitStuffTime(bytecount))) /
42937 +                           1000;
42938 +                       retval =
42939 +                           64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42940 +                           retval;
42941 +               } else {
42942 +                       retval =
42943 +                           (66700 * (31 + 10 * BitStuffTime(bytecount))) /
42944 +                           1000;
42945 +                       retval =
42946 +                           64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42947 +                           retval;
42948 +               }
42949 +               break;
42950 +       default:
42951 +               DWC_WARN("Unknown device speed\n");
42952 +               retval = -1;
42953 +       }
42954 +
42955 +       return NS_TO_US(retval);
42956 +}
42957 +
42958 +/**
42959 + * Initializes a QH structure.
42960 + *
42961 + * @param hcd The HCD state structure for the DWC OTG controller.
42962 + * @param qh  The QH to init.
42963 + * @param urb Holds the information about the device/endpoint that we need
42964 + *           to initialize the QH.
42965 + */
42966 +#define SCHEDULE_SLOP 10
42967 +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
42968 +{
42969 +       char *speed, *type;
42970 +       int dev_speed;
42971 +       uint32_t hub_addr, hub_port;
42972 +
42973 +       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
42974 +
42975 +       /* Initialize QH */
42976 +       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
42977 +       qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
42978 +
42979 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
42980 +       qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
42981 +       DWC_CIRCLEQ_INIT(&qh->qtd_list);
42982 +       DWC_LIST_INIT(&qh->qh_list_entry);
42983 +       qh->channel = NULL;
42984 +
42985 +       /* FS/LS Enpoint on HS Hub
42986 +        * NOT virtual root hub */
42987 +       dev_speed = hcd->fops->speed(hcd, urb->priv);
42988 +
42989 +       hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
42990 +       qh->do_split = 0;
42991 +       if (microframe_schedule)
42992 +               qh->speed = dev_speed;
42993 +
42994 +
42995 +       if (((dev_speed == USB_SPEED_LOW) ||
42996 +            (dev_speed == USB_SPEED_FULL)) &&
42997 +           (hub_addr != 0 && hub_addr != 1)) {
42998 +               DWC_DEBUGPL(DBG_HCD,
42999 +                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
43000 +                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
43001 +                           hub_port);
43002 +               qh->do_split = 1;
43003 +       }
43004 +
43005 +       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
43006 +               /* Compute scheduling parameters once and save them. */
43007 +               hprt0_data_t hprt;
43008 +
43009 +               /** @todo Account for split transfers in the bus time. */
43010 +               int bytecount =
43011 +                   dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
43012 +
43013 +               qh->usecs =
43014 +                   calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
43015 +                                 qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),
43016 +                                 bytecount);
43017 +               /* Start in a slightly future (micro)frame. */
43018 +               qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
43019 +                                                   SCHEDULE_SLOP);
43020 +               qh->interval = urb->interval;
43021 +
43022 +#if 0
43023 +               /* Increase interrupt polling rate for debugging. */
43024 +               if (qh->ep_type == UE_INTERRUPT) {
43025 +                       qh->interval = 8;
43026 +               }
43027 +#endif
43028 +               hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
43029 +               if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
43030 +                   ((dev_speed == USB_SPEED_LOW) ||
43031 +                    (dev_speed == USB_SPEED_FULL))) {
43032 +                       qh->interval *= 8;
43033 +                       qh->sched_frame |= 0x7;
43034 +                       qh->start_split_frame = qh->sched_frame;
43035 +               }
43036 +
43037 +       }
43038 +
43039 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
43040 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);
43041 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
43042 +                   dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
43043 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
43044 +                   dwc_otg_hcd_get_ep_num(&urb->pipe_info),
43045 +                   dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
43046 +       switch (dev_speed) {
43047 +       case USB_SPEED_LOW:
43048 +               qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
43049 +               speed = "low";
43050 +               break;
43051 +       case USB_SPEED_FULL:
43052 +               qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
43053 +               speed = "full";
43054 +               break;
43055 +       case USB_SPEED_HIGH:
43056 +               qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
43057 +               speed = "high";
43058 +               break;
43059 +       default:
43060 +               speed = "?";
43061 +               break;
43062 +       }
43063 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);
43064 +
43065 +       switch (qh->ep_type) {
43066 +       case UE_ISOCHRONOUS:
43067 +               type = "isochronous";
43068 +               break;
43069 +       case UE_INTERRUPT:
43070 +               type = "interrupt";
43071 +               break;
43072 +       case UE_CONTROL:
43073 +               type = "control";
43074 +               break;
43075 +       case UE_BULK:
43076 +               type = "bulk";
43077 +               break;
43078 +       default:
43079 +               type = "?";
43080 +               break;
43081 +       }
43082 +
43083 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n", type);
43084 +
43085 +#ifdef DEBUG
43086 +       if (qh->ep_type == UE_INTERRUPT) {
43087 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
43088 +                           qh->usecs);
43089 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
43090 +                           qh->interval);
43091 +       }
43092 +#endif
43093 +
43094 +}
43095 +
43096 +/**
43097 + * This function allocates and initializes a QH.
43098 + *
43099 + * @param hcd The HCD state structure for the DWC OTG controller.
43100 + * @param urb Holds the information about the device/endpoint that we need
43101 + *           to initialize the QH.
43102 + * @param atomic_alloc Flag to do atomic allocation if needed
43103 + *
43104 + * @return Returns pointer to the newly allocated QH, or NULL on error. */
43105 +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
43106 +                                   dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43107 +{
43108 +       dwc_otg_qh_t *qh;
43109 +
43110 +       /* Allocate memory */
43111 +       /** @todo add memflags argument */
43112 +       qh = dwc_otg_hcd_qh_alloc(atomic_alloc);
43113 +       if (qh == NULL) {
43114 +               DWC_ERROR("qh allocation failed");
43115 +               return NULL;
43116 +       }
43117 +
43118 +       qh_init(hcd, qh, urb);
43119 +
43120 +       if (hcd->core_if->dma_desc_enable
43121 +           && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
43122 +               dwc_otg_hcd_qh_free(hcd, qh);
43123 +               return NULL;
43124 +       }
43125 +
43126 +       return qh;
43127 +}
43128 +
43129 +/* microframe_schedule=0 start */
43130 +
43131 +/**
43132 + * Checks that a channel is available for a periodic transfer.
43133 + *
43134 + * @return 0 if successful, negative error code otherise.
43135 + */
43136 +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
43137 +{
43138 +       /*
43139 +        * Currently assuming that there is a dedicated host channnel for each
43140 +        * periodic transaction plus at least one host channel for
43141 +        * non-periodic transactions.
43142 +        */
43143 +       int status;
43144 +       int num_channels;
43145 +
43146 +       num_channels = hcd->core_if->core_params->host_channels;
43147 +       if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)
43148 +           && (hcd->periodic_channels < num_channels - 1)) {
43149 +               status = 0;
43150 +       } else {
43151 +               DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
43152 +                       __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels);    //NOTICE
43153 +               status = -DWC_E_NO_SPACE;
43154 +       }
43155 +
43156 +       return status;
43157 +}
43158 +
43159 +/**
43160 + * Checks that there is sufficient bandwidth for the specified QH in the
43161 + * periodic schedule. For simplicity, this calculation assumes that all the
43162 + * transfers in the periodic schedule may occur in the same (micro)frame.
43163 + *
43164 + * @param hcd The HCD state structure for the DWC OTG controller.
43165 + * @param qh QH containing periodic bandwidth required.
43166 + *
43167 + * @return 0 if successful, negative error code otherwise.
43168 + */
43169 +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43170 +{
43171 +       int status;
43172 +       int16_t max_claimed_usecs;
43173 +
43174 +       status = 0;
43175 +
43176 +       if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
43177 +               /*
43178 +                * High speed mode.
43179 +                * Max periodic usecs is 80% x 125 usec = 100 usec.
43180 +                */
43181 +
43182 +               max_claimed_usecs = 100 - qh->usecs;
43183 +       } else {
43184 +               /*
43185 +                * Full speed mode.
43186 +                * Max periodic usecs is 90% x 1000 usec = 900 usec.
43187 +                */
43188 +               max_claimed_usecs = 900 - qh->usecs;
43189 +       }
43190 +
43191 +       if (hcd->periodic_usecs > max_claimed_usecs) {
43192 +               DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs);        //NOTICE
43193 +               status = -DWC_E_NO_SPACE;
43194 +       }
43195 +
43196 +       return status;
43197 +}
43198 +
43199 +/* microframe_schedule=0 end */
43200 +
43201 +/**
43202 + * Microframe scheduler
43203 + * track the total use in hcd->frame_usecs
43204 + * keep each qh use in qh->frame_usecs
43205 + * when surrendering the qh then donate the time back
43206 + */
43207 +const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
43208 +
43209 +/*
43210 + * called from dwc_otg_hcd.c:dwc_otg_hcd_init
43211 + */
43212 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
43213 +{
43214 +       int i;
43215 +       for (i=0; i<8; i++) {
43216 +               _hcd->frame_usecs[i] = max_uframe_usecs[i];
43217 +       }
43218 +       return 0;
43219 +}
43220 +
43221 +static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43222 +{
43223 +       int i;
43224 +       unsigned short utime;
43225 +       int t_left;
43226 +       int ret;
43227 +       int done;
43228 +
43229 +       ret = -1;
43230 +       utime = _qh->usecs;
43231 +       t_left = utime;
43232 +       i = 0;
43233 +       done = 0;
43234 +       while (done == 0) {
43235 +               /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
43236 +               if (utime <= _hcd->frame_usecs[i]) {
43237 +                       _hcd->frame_usecs[i] -= utime;
43238 +                       _qh->frame_usecs[i] += utime;
43239 +                       t_left -= utime;
43240 +                       ret = i;
43241 +                       done = 1;
43242 +                       return ret;
43243 +               } else {
43244 +                       i++;
43245 +                       if (i == 8) {
43246 +                               done = 1;
43247 +                               ret = -1;
43248 +                       }
43249 +               }
43250 +       }
43251 +       return ret;
43252 + }
43253 +
43254 +/*
43255 + * use this for FS apps that can span multiple uframes
43256 +  */
43257 +static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43258 +{
43259 +       int i;
43260 +       int j;
43261 +       unsigned short utime;
43262 +       int t_left;
43263 +       int ret;
43264 +       int done;
43265 +       unsigned short xtime;
43266 +
43267 +       ret = -1;
43268 +       utime = _qh->usecs;
43269 +       t_left = utime;
43270 +       i = 0;
43271 +       done = 0;
43272 +loop:
43273 +       while (done == 0) {
43274 +               if(_hcd->frame_usecs[i] <= 0) {
43275 +                       i++;
43276 +                       if (i == 8) {
43277 +                               done = 1;
43278 +                               ret = -1;
43279 +                       }
43280 +                       goto loop;
43281 +               }
43282 +
43283 +               /*
43284 +                * we need n consecutive slots
43285 +                * so use j as a start slot j plus j+1 must be enough time (for now)
43286 +                */
43287 +               xtime= _hcd->frame_usecs[i];
43288 +               for (j = i+1 ; j < 8 ; j++ ) {
43289 +                       /*
43290 +                        * if we add this frame remaining time to xtime we may
43291 +                        * be OK, if not we need to test j for a complete frame
43292 +                        */
43293 +                       if ((xtime+_hcd->frame_usecs[j]) < utime) {
43294 +                               if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
43295 +                                       j = 8;
43296 +                                       ret = -1;
43297 +                                       continue;
43298 +                               }
43299 +                       }
43300 +                       if (xtime >= utime) {
43301 +                               ret = i;
43302 +                               j = 8;  /* stop loop with a good value ret */
43303 +                               continue;
43304 +                       }
43305 +                       /* add the frame time to x time */
43306 +                       xtime += _hcd->frame_usecs[j];
43307 +                      /* we must have a fully available next frame or break */
43308 +                      if ((xtime < utime)
43309 +                                      && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
43310 +                              ret = -1;
43311 +                              j = 8;  /* stop loop with a bad value ret */
43312 +                              continue;
43313 +                      }
43314 +               }
43315 +               if (ret >= 0) {
43316 +                       t_left = utime;
43317 +                       for (j = i; (t_left>0) && (j < 8); j++ ) {
43318 +                               t_left -= _hcd->frame_usecs[j];
43319 +                               if ( t_left <= 0 ) {
43320 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
43321 +                                       _hcd->frame_usecs[j]= -t_left;
43322 +                                       ret = i;
43323 +                                       done = 1;
43324 +                               } else {
43325 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j];
43326 +                                       _hcd->frame_usecs[j] = 0;
43327 +                               }
43328 +                       }
43329 +               } else {
43330 +                       i++;
43331 +                       if (i == 8) {
43332 +                               done = 1;
43333 +                               ret = -1;
43334 +                       }
43335 +               }
43336 +       }
43337 +       return ret;
43338 +}
43339 +
43340 +static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43341 +{
43342 +       int ret;
43343 +       ret = -1;
43344 +
43345 +       if (_qh->speed == USB_SPEED_HIGH) {
43346 +               /* if this is a hs transaction we need a full frame */
43347 +               ret = find_single_uframe(_hcd, _qh);
43348 +       } else {
43349 +               /* if this is a fs transaction we may need a sequence of frames */
43350 +               ret = find_multi_uframe(_hcd, _qh);
43351 +       }
43352 +       return ret;
43353 +}
43354 +
43355 +/**
43356 + * Checks that the max transfer size allowed in a host channel is large enough
43357 + * to handle the maximum data transfer in a single (micro)frame for a periodic
43358 + * transfer.
43359 + *
43360 + * @param hcd The HCD state structure for the DWC OTG controller.
43361 + * @param qh QH for a periodic endpoint.
43362 + *
43363 + * @return 0 if successful, negative error code otherwise.
43364 + */
43365 +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43366 +{
43367 +       int status;
43368 +       uint32_t max_xfer_size;
43369 +       uint32_t max_channel_xfer_size;
43370 +
43371 +       status = 0;
43372 +
43373 +       max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
43374 +       max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
43375 +
43376 +       if (max_xfer_size > max_channel_xfer_size) {
43377 +               DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
43378 +                               __func__, max_xfer_size, max_channel_xfer_size);        //NOTICE
43379 +               status = -DWC_E_NO_SPACE;
43380 +       }
43381 +
43382 +       return status;
43383 +}
43384 +
43385 +/**
43386 + * Schedules an interrupt or isochronous transfer in the periodic schedule.
43387 + *
43388 + * @param hcd The HCD state structure for the DWC OTG controller.
43389 + * @param qh QH for the periodic transfer. The QH should already contain the
43390 + * scheduling information.
43391 + *
43392 + * @return 0 if successful, negative error code otherwise.
43393 + */
43394 +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43395 +{
43396 +       int status = 0;
43397 +
43398 +       if (microframe_schedule) {
43399 +               int frame;
43400 +               status = find_uframe(hcd, qh);
43401 +               frame = -1;
43402 +               if (status == 0) {
43403 +                       frame = 7;
43404 +               } else {
43405 +                       if (status > 0 )
43406 +                               frame = status-1;
43407 +               }
43408 +
43409 +               /* Set the new frame up */
43410 +               if (frame > -1) {
43411 +                       qh->sched_frame &= ~0x7;
43412 +                       qh->sched_frame |= (frame & 7);
43413 +               }
43414 +
43415 +               if (status != -1)
43416 +                       status = 0;
43417 +       } else {
43418 +               status = periodic_channel_available(hcd);
43419 +               if (status) {
43420 +                       DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__);        //NOTICE
43421 +                       return status;
43422 +               }
43423 +
43424 +               status = check_periodic_bandwidth(hcd, qh);
43425 +       }
43426 +       if (status) {
43427 +               DWC_INFO("%s: Insufficient periodic bandwidth for "
43428 +                           "periodic transfer.\n", __func__);
43429 +               return status;
43430 +       }
43431 +       status = check_max_xfer_size(hcd, qh);
43432 +       if (status) {
43433 +               DWC_INFO("%s: Channel max transfer size too small "
43434 +                           "for periodic transfer.\n", __func__);
43435 +               return status;
43436 +       }
43437 +
43438 +       if (hcd->core_if->dma_desc_enable) {
43439 +               /* Don't rely on SOF and start in ready schedule */
43440 +               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
43441 +       }
43442 +       else {
43443 +       /* Always start in the inactive schedule. */
43444 +       DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
43445 +       }
43446 +
43447 +       if (!microframe_schedule) {
43448 +               /* Reserve the periodic channel. */
43449 +               hcd->periodic_channels++;
43450 +       }
43451 +
43452 +       /* Update claimed usecs per (micro)frame. */
43453 +       hcd->periodic_usecs += qh->usecs;
43454 +
43455 +       return status;
43456 +}
43457 +
43458 +/**
43459 + * This function adds a QH to either the non periodic or periodic schedule if
43460 + * it is not already in the schedule. If the QH is already in the schedule, no
43461 + * action is taken.
43462 + *
43463 + * @return 0 if successful, negative error code otherwise.
43464 + */
43465 +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43466 +{
43467 +       int status = 0;
43468 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43469 +
43470 +       if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43471 +               /* QH already in a schedule. */
43472 +               return status;
43473 +       }
43474 +
43475 +       /* Add the new QH to the appropriate schedule */
43476 +       if (dwc_qh_is_non_per(qh)) {
43477 +               /* Always start in the inactive schedule. */
43478 +               DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
43479 +                                    &qh->qh_list_entry);
43480 +       } else {
43481 +               status = schedule_periodic(hcd, qh);
43482 +               if ( !hcd->periodic_qh_count ) {
43483 +                       intr_mask.b.sofintr = 1;
43484 +                       DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43485 +                                                               intr_mask.d32, intr_mask.d32);
43486 +               }
43487 +               hcd->periodic_qh_count++;
43488 +       }
43489 +
43490 +       return status;
43491 +}
43492 +
43493 +/**
43494 + * Removes an interrupt or isochronous transfer from the periodic schedule.
43495 + *
43496 + * @param hcd The HCD state structure for the DWC OTG controller.
43497 + * @param qh QH for the periodic transfer.
43498 + */
43499 +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43500 +{
43501 +       int i;
43502 +       DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43503 +
43504 +       /* Update claimed usecs per (micro)frame. */
43505 +       hcd->periodic_usecs -= qh->usecs;
43506 +
43507 +       if (!microframe_schedule) {
43508 +               /* Release the periodic channel reservation. */
43509 +               hcd->periodic_channels--;
43510 +       } else {
43511 +               for (i = 0; i < 8; i++) {
43512 +                       hcd->frame_usecs[i] += qh->frame_usecs[i];
43513 +                       qh->frame_usecs[i] = 0;
43514 +               }
43515 +       }
43516 +}
43517 +
43518 +/**
43519 + * Removes a QH from either the non-periodic or periodic schedule.  Memory is
43520 + * not freed.
43521 + *
43522 + * @param hcd The HCD state structure.
43523 + * @param qh QH to remove from schedule. */
43524 +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43525 +{
43526 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43527 +
43528 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43529 +               /* QH is not in a schedule. */
43530 +               return;
43531 +       }
43532 +
43533 +       if (dwc_qh_is_non_per(qh)) {
43534 +               if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
43535 +                       hcd->non_periodic_qh_ptr =
43536 +                           hcd->non_periodic_qh_ptr->next;
43537 +               }
43538 +               DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43539 +       } else {
43540 +               deschedule_periodic(hcd, qh);
43541 +               hcd->periodic_qh_count--;
43542 +               if( !hcd->periodic_qh_count ) {
43543 +                       intr_mask.b.sofintr = 1;
43544 +                               DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43545 +                                                                       intr_mask.d32, 0);
43546 +               }
43547 +       }
43548 +}
43549 +
43550 +/**
43551 + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
43552 + * non-periodic schedule. The QH is added to the inactive non-periodic
43553 + * schedule if any QTDs are still attached to the QH.
43554 + *
43555 + * For periodic QHs, the QH is removed from the periodic queued schedule. If
43556 + * there are any QTDs still attached to the QH, the QH is added to either the
43557 + * periodic inactive schedule or the periodic ready schedule and its next
43558 + * scheduled frame is calculated. The QH is placed in the ready schedule if
43559 + * the scheduled frame has been reached already. Otherwise it's placed in the
43560 + * inactive schedule. If there are no QTDs attached to the QH, the QH is
43561 + * completely removed from the periodic schedule.
43562 + */
43563 +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
43564 +                              int sched_next_periodic_split)
43565 +{
43566 +       if (dwc_qh_is_non_per(qh)) {
43567 +               dwc_otg_hcd_qh_remove(hcd, qh);
43568 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43569 +                       /* Add back to inactive non-periodic schedule. */
43570 +                       dwc_otg_hcd_qh_add(hcd, qh);
43571 +               }
43572 +       } else {
43573 +               uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
43574 +
43575 +               if (qh->do_split) {
43576 +                       /* Schedule the next continuing periodic split transfer */
43577 +                       if (sched_next_periodic_split) {
43578 +
43579 +                               qh->sched_frame = frame_number;
43580 +                               if (dwc_frame_num_le(frame_number,
43581 +                                                    dwc_frame_num_inc
43582 +                                                    (qh->start_split_frame,
43583 +                                                     1))) {
43584 +                                       /*
43585 +                                        * Allow one frame to elapse after start
43586 +                                        * split microframe before scheduling
43587 +                                        * complete split, but DONT if we are
43588 +                                        * doing the next start split in the
43589 +                                        * same frame for an ISOC out.
43590 +                                        */
43591 +                                       if ((qh->ep_type != UE_ISOCHRONOUS) ||
43592 +                                           (qh->ep_is_in != 0)) {
43593 +                                               qh->sched_frame =
43594 +                                                   dwc_frame_num_inc(qh->sched_frame, 1);
43595 +                                       }
43596 +                               }
43597 +                       } else {
43598 +                               qh->sched_frame =
43599 +                                   dwc_frame_num_inc(qh->start_split_frame,
43600 +                                                     qh->interval);
43601 +                               if (dwc_frame_num_le
43602 +                                   (qh->sched_frame, frame_number)) {
43603 +                                       qh->sched_frame = frame_number;
43604 +                               }
43605 +                               qh->sched_frame |= 0x7;
43606 +                               qh->start_split_frame = qh->sched_frame;
43607 +                       }
43608 +               } else {
43609 +                       qh->sched_frame =
43610 +                           dwc_frame_num_inc(qh->sched_frame, qh->interval);
43611 +                       if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
43612 +                               qh->sched_frame = frame_number;
43613 +                       }
43614 +               }
43615 +
43616 +               if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43617 +                       dwc_otg_hcd_qh_remove(hcd, qh);
43618 +               } else {
43619 +                       /*
43620 +                        * Remove from periodic_sched_queued and move to
43621 +                        * appropriate queue.
43622 +                        */
43623 +                       if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||
43624 +                       (!microframe_schedule && qh->sched_frame == frame_number)) {
43625 +                               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
43626 +                                                  &qh->qh_list_entry);
43627 +                       } else {
43628 +                               DWC_LIST_MOVE_HEAD
43629 +                                   (&hcd->periodic_sched_inactive,
43630 +                                    &qh->qh_list_entry);
43631 +                       }
43632 +               }
43633 +       }
43634 +}
43635 +
43636 +/**
43637 + * This function allocates and initializes a QTD.
43638 + *
43639 + * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up
43640 + *           pointing to each other so each pair should have a unique correlation.
43641 + * @param atomic_alloc Flag to do atomic alloc if needed
43642 + *
43643 + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
43644 +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43645 +{
43646 +       dwc_otg_qtd_t *qtd;
43647 +
43648 +       qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);
43649 +       if (qtd == NULL) {
43650 +               return NULL;
43651 +       }
43652 +
43653 +       dwc_otg_hcd_qtd_init(qtd, urb);
43654 +       return qtd;
43655 +}
43656 +
43657 +/**
43658 + * Initializes a QTD structure.
43659 + *
43660 + * @param qtd The QTD to initialize.
43661 + * @param urb The URB to use for initialization.  */
43662 +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
43663 +{
43664 +       dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
43665 +       qtd->urb = urb;
43666 +       if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
43667 +               /*
43668 +                * The only time the QTD data toggle is used is on the data
43669 +                * phase of control transfers. This phase always starts with
43670 +                * DATA1.
43671 +                */
43672 +               qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
43673 +               qtd->control_phase = DWC_OTG_CONTROL_SETUP;
43674 +       }
43675 +
43676 +       /* start split */
43677 +       qtd->complete_split = 0;
43678 +       qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
43679 +       qtd->isoc_split_offset = 0;
43680 +       qtd->in_process = 0;
43681 +
43682 +       /* Store the qtd ptr in the urb to reference what QTD. */
43683 +       urb->qtd = qtd;
43684 +       return;
43685 +}
43686 +
43687 +/**
43688 + * This function adds a QTD to the QTD-list of a QH.  It will find the correct
43689 + * QH to place the QTD into.  If it does not find a QH, then it will create a
43690 + * new QH. If the QH to which the QTD is added is not currently scheduled, it
43691 + * is placed into the proper schedule based on its EP type.
43692 + *
43693 + * @param[in] qtd The QTD to add
43694 + * @param[in] hcd The DWC HCD structure
43695 + * @param[out] qh out parameter to return queue head
43696 + * @param atomic_alloc Flag to do atomic alloc if needed
43697 + *
43698 + * @return 0 if successful, negative error code otherwise.
43699 + */
43700 +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
43701 +                       dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
43702 +{
43703 +       int retval = 0;
43704 +       dwc_irqflags_t flags;
43705 +
43706 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
43707 +
43708 +       /*
43709 +        * Get the QH which holds the QTD-list to insert to. Create QH if it
43710 +        * doesn't exist.
43711 +        */
43712 +       if (*qh == NULL) {
43713 +               *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
43714 +               if (*qh == NULL) {
43715 +                       retval = -1;
43716 +                       goto done;
43717 +               }
43718 +       }
43719 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
43720 +       retval = dwc_otg_hcd_qh_add(hcd, *qh);
43721 +       if (retval == 0) {
43722 +               DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
43723 +                                       qtd_list_entry);
43724 +       }
43725 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
43726 +
43727 +done:
43728 +
43729 +       return retval;
43730 +}
43731 +
43732 +#endif /* DWC_DEVICE_ONLY */
43733 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43734 new file mode 100644
43735 index 0000000..e46d9bb
43736 --- /dev/null
43737 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43738 @@ -0,0 +1,185 @@
43739 +#ifndef _DWC_OS_DEP_H_
43740 +#define _DWC_OS_DEP_H_
43741 +
43742 +/**
43743 + * @file
43744 + *
43745 + * This file contains OS dependent structures.
43746 + *
43747 + */
43748 +
43749 +#include <linux/kernel.h>
43750 +#include <linux/module.h>
43751 +#include <linux/moduleparam.h>
43752 +#include <linux/init.h>
43753 +#include <linux/device.h>
43754 +#include <linux/errno.h>
43755 +#include <linux/types.h>
43756 +#include <linux/slab.h>
43757 +#include <linux/list.h>
43758 +#include <linux/interrupt.h>
43759 +#include <linux/ctype.h>
43760 +#include <linux/string.h>
43761 +#include <linux/dma-mapping.h>
43762 +#include <linux/jiffies.h>
43763 +#include <linux/delay.h>
43764 +#include <linux/timer.h>
43765 +#include <linux/workqueue.h>
43766 +#include <linux/stat.h>
43767 +#include <linux/pci.h>
43768 +
43769 +#include <linux/version.h>
43770 +
43771 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
43772 +# include <linux/irq.h>
43773 +#endif
43774 +
43775 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
43776 +# include <linux/usb/ch9.h>
43777 +#else
43778 +# include <linux/usb_ch9.h>
43779 +#endif
43780 +
43781 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
43782 +# include <linux/usb/gadget.h>
43783 +#else
43784 +# include <linux/usb_gadget.h>
43785 +#endif
43786 +
43787 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
43788 +# include <asm/irq.h>
43789 +#endif
43790 +
43791 +#ifdef PCI_INTERFACE
43792 +# include <asm/io.h>
43793 +#endif
43794 +
43795 +#ifdef LM_INTERFACE
43796 +# include <asm/unaligned.h>
43797 +# include <asm/sizes.h>
43798 +# include <asm/param.h>
43799 +# include <asm/io.h>
43800 +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
43801 +#  include <asm/arch/hardware.h>
43802 +#  include <asm/arch/lm.h>
43803 +#  include <asm/arch/irqs.h>
43804 +#  include <asm/arch/regs-irq.h>
43805 +# else
43806 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
43807 +   here we assume that the machine architecture provides definitions
43808 +   in its own header
43809 +*/
43810 +#  include <mach/lm.h>
43811 +#  include <mach/hardware.h>
43812 +# endif
43813 +#endif
43814 +
43815 +#ifdef PLATFORM_INTERFACE
43816 +#include <linux/platform_device.h>
43817 +#include <asm/mach/map.h>
43818 +#endif
43819 +
43820 +/** The OS page size */
43821 +#define DWC_OS_PAGE_SIZE       PAGE_SIZE
43822 +
43823 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
43824 +typedef int gfp_t;
43825 +#endif
43826 +
43827 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
43828 +# define IRQF_SHARED SA_SHIRQ
43829 +#endif
43830 +
43831 +typedef struct os_dependent {
43832 +       /** Base address returned from ioremap() */
43833 +       void *base;
43834 +
43835 +       /** Register offset for Diagnostic API */
43836 +       uint32_t reg_offset;
43837 +
43838 +#ifdef LM_INTERFACE
43839 +       struct lm_device *lmdev;
43840 +#elif  defined(PCI_INTERFACE)
43841 +       struct pci_dev *pcidev;
43842 +
43843 +       /** Start address of a PCI region */
43844 +       resource_size_t rsrc_start;
43845 +
43846 +       /** Length address of a PCI region */
43847 +       resource_size_t rsrc_len;
43848 +#elif  defined(PLATFORM_INTERFACE)
43849 +       struct platform_device *platformdev;
43850 +#endif
43851 +
43852 +} os_dependent_t;
43853 +
43854 +#ifdef __cplusplus
43855 +}
43856 +#endif
43857 +
43858 +
43859 +
43860 +/* Type for the our device on the chosen bus */
43861 +#if   defined(LM_INTERFACE)
43862 +typedef struct lm_device       dwc_bus_dev_t;
43863 +#elif defined(PCI_INTERFACE)
43864 +typedef struct pci_dev         dwc_bus_dev_t;
43865 +#elif defined(PLATFORM_INTERFACE)
43866 +typedef struct platform_device dwc_bus_dev_t;
43867 +#endif
43868 +
43869 +/* Helper macro to retrieve drvdata from the device on the chosen bus */
43870 +#if    defined(LM_INTERFACE)
43871 +#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)
43872 +#elif  defined(PCI_INTERFACE)
43873 +#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)
43874 +#elif  defined(PLATFORM_INTERFACE)
43875 +#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)
43876 +#endif
43877 +
43878 +/**
43879 + * Helper macro returning the otg_device structure of a given struct device
43880 + *
43881 + * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
43882 + */
43883 +#ifdef LM_INTERFACE
43884 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43885 +                struct lm_device *lm_dev = \
43886 +                        container_of(_dev, struct lm_device, dev); \
43887 +                _var = lm_get_drvdata(lm_dev); \
43888 +        } while (0)
43889 +
43890 +#elif defined(PCI_INTERFACE)
43891 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43892 +                _var = dev_get_drvdata(_dev); \
43893 +        } while (0)
43894 +
43895 +#elif defined(PLATFORM_INTERFACE)
43896 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43897 +                struct platform_device *platform_dev = \
43898 +                        container_of(_dev, struct platform_device, dev); \
43899 +                _var = platform_get_drvdata(platform_dev); \
43900 +        } while (0)
43901 +#endif
43902 +
43903 +
43904 +/**
43905 + * Helper macro returning the struct dev of the given struct os_dependent
43906 + *
43907 + * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)
43908 + */
43909 +#ifdef LM_INTERFACE
43910 +#define DWC_OTG_OS_GETDEV(_osdep) \
43911 +        ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)
43912 +#elif defined(PCI_INTERFACE)
43913 +#define DWC_OTG_OS_GETDEV(_osdep) \
43914 +        ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)
43915 +#elif defined(PLATFORM_INTERFACE)
43916 +#define DWC_OTG_OS_GETDEV(_osdep) \
43917 +        ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)
43918 +#endif
43919 +
43920 +
43921 +
43922 +
43923 +#endif /* _DWC_OS_DEP_H_ */
43924 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
43925 new file mode 100644
43926 index 0000000..ae0c72d
43927 --- /dev/null
43928 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
43929 @@ -0,0 +1,2712 @@
43930 +/* ==========================================================================
43931 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
43932 + * $Revision: #101 $
43933 + * $Date: 2012/08/10 $
43934 + * $Change: 2047372 $
43935 + *
43936 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
43937 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
43938 + * otherwise expressly agreed to in writing between Synopsys and you.
43939 + *
43940 + * The Software IS NOT an item of Licensed Software or Licensed Product under
43941 + * any End User Software License Agreement or Agreement for Licensed Product
43942 + * with Synopsys or any supplement thereto. You are permitted to use and
43943 + * redistribute this Software in source and binary forms, with or without
43944 + * modification, provided that redistributions of source code must retain this
43945 + * notice. You may not view, use, disclose, copy or distribute this file or
43946 + * any information contained herein except pursuant to this license grant from
43947 + * Synopsys. If you do not agree with this notice, including the disclaimer
43948 + * below, then you are not authorized to use the Software.
43949 + *
43950 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
43951 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43952 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43953 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
43954 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43955 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43956 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
43957 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43958 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43959 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
43960 + * DAMAGE.
43961 + * ========================================================================== */
43962 +#ifndef DWC_HOST_ONLY
43963 +
43964 +/** @file
43965 + * This file implements PCD Core. All code in this file is portable and doesn't
43966 + * use any OS specific functions.
43967 + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
43968 + * header file, which can be used to implement OS specific PCD interface.
43969 + *
43970 + * An important function of the PCD is managing interrupts generated
43971 + * by the DWC_otg controller. The implementation of the DWC_otg device
43972 + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
43973 + *
43974 + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
43975 + * @todo Does it work when the request size is greater than DEPTSIZ
43976 + * transfer size
43977 + *
43978 + */
43979 +
43980 +#include "dwc_otg_pcd.h"
43981 +
43982 +#ifdef DWC_UTE_CFI
43983 +#include "dwc_otg_cfi.h"
43984 +
43985 +extern int init_cfi(cfiobject_t * cfiobj);
43986 +#endif
43987 +
43988 +/**
43989 + * Choose endpoint from ep arrays using usb_ep structure.
43990 + */
43991 +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
43992 +{
43993 +       int i;
43994 +       if (pcd->ep0.priv == handle) {
43995 +               return &pcd->ep0;
43996 +       }
43997 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
43998 +               if (pcd->in_ep[i].priv == handle)
43999 +                       return &pcd->in_ep[i];
44000 +               if (pcd->out_ep[i].priv == handle)
44001 +                       return &pcd->out_ep[i];
44002 +       }
44003 +
44004 +       return NULL;
44005 +}
44006 +
44007 +/**
44008 + * This function completes a request.  It call's the request call back.
44009 + */
44010 +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
44011 +                         int32_t status)
44012 +{
44013 +       unsigned stopped = ep->stopped;
44014 +
44015 +       DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
44016 +       DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
44017 +
44018 +       /* don't modify queue heads during completion callback */
44019 +       ep->stopped = 1;
44020 +       /* spin_unlock/spin_lock now done in fops->complete() */
44021 +       ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
44022 +                               req->actual);
44023 +
44024 +       if (ep->pcd->request_pending > 0) {
44025 +               --ep->pcd->request_pending;
44026 +       }
44027 +
44028 +       ep->stopped = stopped;
44029 +       DWC_FREE(req);
44030 +}
44031 +
44032 +/**
44033 + * This function terminates all the requsts in the EP request queue.
44034 + */
44035 +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
44036 +{
44037 +       dwc_otg_pcd_request_t *req;
44038 +
44039 +       ep->stopped = 1;
44040 +
44041 +       /* called with irqs blocked?? */
44042 +       while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
44043 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
44044 +               dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
44045 +       }
44046 +}
44047 +
44048 +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
44049 +                      const struct dwc_otg_pcd_function_ops *fops)
44050 +{
44051 +       pcd->fops = fops;
44052 +}
44053 +
44054 +/**
44055 + * PCD Callback function for initializing the PCD when switching to
44056 + * device mode.
44057 + *
44058 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44059 + */
44060 +static int32_t dwc_otg_pcd_start_cb(void *p)
44061 +{
44062 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44063 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
44064 +
44065 +       /*
44066 +        * Initialized the Core for Device mode.
44067 +        */
44068 +       if (dwc_otg_is_device_mode(core_if)) {
44069 +               dwc_otg_core_dev_init(core_if);
44070 +               /* Set core_if's lock pointer to the pcd->lock */
44071 +               core_if->lock = pcd->lock;
44072 +       }
44073 +       return 1;
44074 +}
44075 +
44076 +/** CFI-specific buffer allocation function for EP */
44077 +#ifdef DWC_UTE_CFI
44078 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
44079 +                             size_t buflen, int flags)
44080 +{
44081 +       dwc_otg_pcd_ep_t *ep;
44082 +       ep = get_ep_from_handle(pcd, pep);
44083 +       if (!ep) {
44084 +               DWC_WARN("bad ep\n");
44085 +               return -DWC_E_INVALID;
44086 +       }
44087 +
44088 +       return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
44089 +                                         flags);
44090 +}
44091 +#else
44092 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
44093 +                             size_t buflen, int flags);
44094 +#endif
44095 +
44096 +/**
44097 + * PCD Callback function for notifying the PCD when resuming from
44098 + * suspend.
44099 + *
44100 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44101 + */
44102 +static int32_t dwc_otg_pcd_resume_cb(void *p)
44103 +{
44104 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44105 +
44106 +       if (pcd->fops->resume) {
44107 +               pcd->fops->resume(pcd);
44108 +       }
44109 +
44110 +       /* Stop the SRP timeout timer. */
44111 +       if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
44112 +           || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
44113 +               if (GET_CORE_IF(pcd)->srp_timer_started) {
44114 +                       GET_CORE_IF(pcd)->srp_timer_started = 0;
44115 +                       DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
44116 +               }
44117 +       }
44118 +       return 1;
44119 +}
44120 +
44121 +/**
44122 + * PCD Callback function for notifying the PCD device is suspended.
44123 + *
44124 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44125 + */
44126 +static int32_t dwc_otg_pcd_suspend_cb(void *p)
44127 +{
44128 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44129 +
44130 +       if (pcd->fops->suspend) {
44131 +               DWC_SPINUNLOCK(pcd->lock);
44132 +               pcd->fops->suspend(pcd);
44133 +               DWC_SPINLOCK(pcd->lock);
44134 +       }
44135 +
44136 +       return 1;
44137 +}
44138 +
44139 +/**
44140 + * PCD Callback function for stopping the PCD when switching to Host
44141 + * mode.
44142 + *
44143 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44144 + */
44145 +static int32_t dwc_otg_pcd_stop_cb(void *p)
44146 +{
44147 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44148 +       extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
44149 +
44150 +       dwc_otg_pcd_stop(pcd);
44151 +       return 1;
44152 +}
44153 +
44154 +/**
44155 + * PCD Callback structure for handling mode switching.
44156 + */
44157 +static dwc_otg_cil_callbacks_t pcd_callbacks = {
44158 +       .start = dwc_otg_pcd_start_cb,
44159 +       .stop = dwc_otg_pcd_stop_cb,
44160 +       .suspend = dwc_otg_pcd_suspend_cb,
44161 +       .resume_wakeup = dwc_otg_pcd_resume_cb,
44162 +       .p = 0,                 /* Set at registration */
44163 +};
44164 +
44165 +/**
44166 + * This function allocates a DMA Descriptor chain for the Endpoint
44167 + * buffer to be used for a transfer to/from the specified endpoint.
44168 + */
44169 +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
44170 +                                                   uint32_t count)
44171 +{
44172 +       return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t),
44173 +                                                       dma_desc_addr);
44174 +}
44175 +
44176 +/**
44177 + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
44178 + */
44179 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
44180 +                               uint32_t dma_desc_addr, uint32_t count)
44181 +{
44182 +       DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
44183 +                    dma_desc_addr);
44184 +}
44185 +
44186 +#ifdef DWC_EN_ISOC
44187 +
44188 +/**
44189 + * This function initializes a descriptor chain for Isochronous transfer
44190 + *
44191 + * @param core_if Programming view of DWC_otg controller.
44192 + * @param dwc_ep The EP to start the transfer on.
44193 + *
44194 + */
44195 +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
44196 +                                       dwc_ep_t * dwc_ep)
44197 +{
44198 +
44199 +       dsts_data_t dsts = {.d32 = 0 };
44200 +       depctl_data_t depctl = {.d32 = 0 };
44201 +       volatile uint32_t *addr;
44202 +       int i, j;
44203 +       uint32_t len;
44204 +
44205 +       if (dwc_ep->is_in)
44206 +               dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
44207 +       else
44208 +               dwc_ep->desc_cnt =
44209 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44210 +                   dwc_ep->bInterval;
44211 +
44212 +       /** Allocate descriptors for double buffering */
44213 +       dwc_ep->iso_desc_addr =
44214 +           dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
44215 +                                       dwc_ep->desc_cnt * 2);
44216 +       if (dwc_ep->desc_addr) {
44217 +               DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
44218 +               return;
44219 +       }
44220 +
44221 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44222 +
44223 +       /** ISO OUT EP */
44224 +       if (dwc_ep->is_in == 0) {
44225 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44226 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44227 +               dma_addr_t dma_ad;
44228 +               uint32_t data_per_desc;
44229 +               dwc_otg_dev_out_ep_regs_t *out_regs =
44230 +                   core_if->dev_if->out_ep_regs[dwc_ep->num];
44231 +               int offset;
44232 +
44233 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
44234 +               dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
44235 +
44236 +               /** Buffer 0 descriptors setup */
44237 +               dma_ad = dwc_ep->dma_addr0;
44238 +
44239 +               sts.b_iso_out.bs = BS_HOST_READY;
44240 +               sts.b_iso_out.rxsts = 0;
44241 +               sts.b_iso_out.l = 0;
44242 +               sts.b_iso_out.sp = 0;
44243 +               sts.b_iso_out.ioc = 0;
44244 +               sts.b_iso_out.pid = 0;
44245 +               sts.b_iso_out.framenum = 0;
44246 +
44247 +               offset = 0;
44248 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44249 +                    i += dwc_ep->pkt_per_frm) {
44250 +
44251 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44252 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44253 +                               if (len > dwc_ep->data_per_frame)
44254 +                                       data_per_desc =
44255 +                                           dwc_ep->data_per_frame -
44256 +                                           j * dwc_ep->maxpacket;
44257 +                               else
44258 +                                       data_per_desc = dwc_ep->maxpacket;
44259 +                               len = data_per_desc % 4;
44260 +                               if (len)
44261 +                                       data_per_desc += 4 - len;
44262 +
44263 +                               sts.b_iso_out.rxbytes = data_per_desc;
44264 +                               dma_desc->buf = dma_ad;
44265 +                               dma_desc->status.d32 = sts.d32;
44266 +
44267 +                               offset += data_per_desc;
44268 +                               dma_desc++;
44269 +                               dma_ad += data_per_desc;
44270 +                       }
44271 +               }
44272 +
44273 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44274 +                       uint32_t len = (j + 1) * dwc_ep->maxpacket;
44275 +                       if (len > dwc_ep->data_per_frame)
44276 +                               data_per_desc =
44277 +                                   dwc_ep->data_per_frame -
44278 +                                   j * dwc_ep->maxpacket;
44279 +                       else
44280 +                               data_per_desc = dwc_ep->maxpacket;
44281 +                       len = data_per_desc % 4;
44282 +                       if (len)
44283 +                               data_per_desc += 4 - len;
44284 +                       sts.b_iso_out.rxbytes = data_per_desc;
44285 +                       dma_desc->buf = dma_ad;
44286 +                       dma_desc->status.d32 = sts.d32;
44287 +
44288 +                       offset += data_per_desc;
44289 +                       dma_desc++;
44290 +                       dma_ad += data_per_desc;
44291 +               }
44292 +
44293 +               sts.b_iso_out.ioc = 1;
44294 +               len = (j + 1) * dwc_ep->maxpacket;
44295 +               if (len > dwc_ep->data_per_frame)
44296 +                       data_per_desc =
44297 +                           dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
44298 +               else
44299 +                       data_per_desc = dwc_ep->maxpacket;
44300 +               len = data_per_desc % 4;
44301 +               if (len)
44302 +                       data_per_desc += 4 - len;
44303 +               sts.b_iso_out.rxbytes = data_per_desc;
44304 +
44305 +               dma_desc->buf = dma_ad;
44306 +               dma_desc->status.d32 = sts.d32;
44307 +               dma_desc++;
44308 +
44309 +               /** Buffer 1 descriptors setup */
44310 +               sts.b_iso_out.ioc = 0;
44311 +               dma_ad = dwc_ep->dma_addr1;
44312 +
44313 +               offset = 0;
44314 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44315 +                    i += dwc_ep->pkt_per_frm) {
44316 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44317 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44318 +                               if (len > dwc_ep->data_per_frame)
44319 +                                       data_per_desc =
44320 +                                           dwc_ep->data_per_frame -
44321 +                                           j * dwc_ep->maxpacket;
44322 +                               else
44323 +                                       data_per_desc = dwc_ep->maxpacket;
44324 +                               len = data_per_desc % 4;
44325 +                               if (len)
44326 +                                       data_per_desc += 4 - len;
44327 +
44328 +                               data_per_desc =
44329 +                                   sts.b_iso_out.rxbytes = data_per_desc;
44330 +                               dma_desc->buf = dma_ad;
44331 +                               dma_desc->status.d32 = sts.d32;
44332 +
44333 +                               offset += data_per_desc;
44334 +                               dma_desc++;
44335 +                               dma_ad += data_per_desc;
44336 +                       }
44337 +               }
44338 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44339 +                       data_per_desc =
44340 +                           ((j + 1) * dwc_ep->maxpacket >
44341 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44342 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44343 +                       data_per_desc +=
44344 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44345 +                       sts.b_iso_out.rxbytes = data_per_desc;
44346 +                       dma_desc->buf = dma_ad;
44347 +                       dma_desc->status.d32 = sts.d32;
44348 +
44349 +                       offset += data_per_desc;
44350 +                       dma_desc++;
44351 +                       dma_ad += data_per_desc;
44352 +               }
44353 +
44354 +               sts.b_iso_out.ioc = 1;
44355 +               sts.b_iso_out.l = 1;
44356 +               data_per_desc =
44357 +                   ((j + 1) * dwc_ep->maxpacket >
44358 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44359 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44360 +               data_per_desc +=
44361 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44362 +               sts.b_iso_out.rxbytes = data_per_desc;
44363 +
44364 +               dma_desc->buf = dma_ad;
44365 +               dma_desc->status.d32 = sts.d32;
44366 +
44367 +               dwc_ep->next_frame = 0;
44368 +
44369 +               /** Write dma_ad into DOEPDMA register */
44370 +               DWC_WRITE_REG32(&(out_regs->doepdma),
44371 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44372 +
44373 +       }
44374 +       /** ISO IN EP */
44375 +       else {
44376 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44377 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44378 +               dma_addr_t dma_ad;
44379 +               dwc_otg_dev_in_ep_regs_t *in_regs =
44380 +                   core_if->dev_if->in_ep_regs[dwc_ep->num];
44381 +               unsigned int frmnumber;
44382 +               fifosize_data_t txfifosize, rxfifosize;
44383 +
44384 +               txfifosize.d32 =
44385 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
44386 +                                  dtxfsts);
44387 +               rxfifosize.d32 =
44388 +                   DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
44389 +
44390 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
44391 +
44392 +               dma_ad = dwc_ep->dma_addr0;
44393 +
44394 +               dsts.d32 =
44395 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44396 +
44397 +               sts.b_iso_in.bs = BS_HOST_READY;
44398 +               sts.b_iso_in.txsts = 0;
44399 +               sts.b_iso_in.sp =
44400 +                   (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
44401 +               sts.b_iso_in.ioc = 0;
44402 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
44403 +
44404 +               frmnumber = dwc_ep->next_frame;
44405 +
44406 +               sts.b_iso_in.framenum = frmnumber;
44407 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
44408 +               sts.b_iso_in.l = 0;
44409 +
44410 +               /** Buffer 0 descriptors setup */
44411 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
44412 +                       dma_desc->buf = dma_ad;
44413 +                       dma_desc->status.d32 = sts.d32;
44414 +                       dma_desc++;
44415 +
44416 +                       dma_ad += dwc_ep->data_per_frame;
44417 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44418 +               }
44419 +
44420 +               sts.b_iso_in.ioc = 1;
44421 +               dma_desc->buf = dma_ad;
44422 +               dma_desc->status.d32 = sts.d32;
44423 +               ++dma_desc;
44424 +
44425 +               /** Buffer 1 descriptors setup */
44426 +               sts.b_iso_in.ioc = 0;
44427 +               dma_ad = dwc_ep->dma_addr1;
44428 +
44429 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44430 +                    i += dwc_ep->pkt_per_frm) {
44431 +                       dma_desc->buf = dma_ad;
44432 +                       dma_desc->status.d32 = sts.d32;
44433 +                       dma_desc++;
44434 +
44435 +                       dma_ad += dwc_ep->data_per_frame;
44436 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44437 +
44438 +                       sts.b_iso_in.ioc = 0;
44439 +               }
44440 +               sts.b_iso_in.ioc = 1;
44441 +               sts.b_iso_in.l = 1;
44442 +
44443 +               dma_desc->buf = dma_ad;
44444 +               dma_desc->status.d32 = sts.d32;
44445 +
44446 +               dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
44447 +
44448 +               /** Write dma_ad into diepdma register */
44449 +               DWC_WRITE_REG32(&(in_regs->diepdma),
44450 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44451 +       }
44452 +       /** Enable endpoint, clear nak  */
44453 +       depctl.d32 = 0;
44454 +       depctl.b.epena = 1;
44455 +       depctl.b.usbactep = 1;
44456 +       depctl.b.cnak = 1;
44457 +
44458 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44459 +       depctl.d32 = DWC_READ_REG32(addr);
44460 +}
44461 +
44462 +/**
44463 + * This function initializes a descriptor chain for Isochronous transfer
44464 + *
44465 + * @param core_if Programming view of DWC_otg controller.
44466 + * @param ep The EP to start the transfer on.
44467 + *
44468 + */
44469 +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
44470 +                                      dwc_ep_t * ep)
44471 +{
44472 +       depctl_data_t depctl = {.d32 = 0 };
44473 +       volatile uint32_t *addr;
44474 +
44475 +       if (ep->is_in) {
44476 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44477 +       } else {
44478 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44479 +       }
44480 +
44481 +       if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
44482 +               return;
44483 +       } else {
44484 +               deptsiz_data_t deptsiz = {.d32 = 0 };
44485 +
44486 +               ep->xfer_len =
44487 +                   ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
44488 +               ep->pkt_cnt =
44489 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44490 +               ep->xfer_count = 0;
44491 +               ep->xfer_buff =
44492 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44493 +               ep->dma_addr =
44494 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44495 +
44496 +               if (ep->is_in) {
44497 +                       /* Program the transfer size and packet count
44498 +                        *      as follows: xfersize = N * maxpacket +
44499 +                        *      short_packet pktcnt = N + (short_packet
44500 +                        *      exist ? 1 : 0)
44501 +                        */
44502 +                       deptsiz.b.mc = ep->pkt_per_frm;
44503 +                       deptsiz.b.xfersize = ep->xfer_len;
44504 +                       deptsiz.b.pktcnt =
44505 +                           (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44506 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
44507 +                                       dieptsiz, deptsiz.d32);
44508 +
44509 +                       /* Write the DMA register */
44510 +                       DWC_WRITE_REG32(&
44511 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
44512 +                                        diepdma), (uint32_t) ep->dma_addr);
44513 +
44514 +               } else {
44515 +                       deptsiz.b.pktcnt =
44516 +                           (ep->xfer_len + (ep->maxpacket - 1)) /
44517 +                           ep->maxpacket;
44518 +                       deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
44519 +
44520 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
44521 +                                       doeptsiz, deptsiz.d32);
44522 +
44523 +                       /* Write the DMA register */
44524 +                       DWC_WRITE_REG32(&
44525 +                                       (core_if->dev_if->out_ep_regs[ep->num]->
44526 +                                        doepdma), (uint32_t) ep->dma_addr);
44527 +
44528 +               }
44529 +               /** Enable endpoint, clear nak  */
44530 +               depctl.d32 = 0;
44531 +               depctl.b.epena = 1;
44532 +               depctl.b.cnak = 1;
44533 +
44534 +               DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44535 +       }
44536 +}
44537 +
44538 +/**
44539 + * This function does the setup for a data transfer for an EP and
44540 + * starts the transfer. For an IN transfer, the packets will be
44541 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
44542 + * the packets are unloaded from the Rx FIFO in the ISR.
44543 + *
44544 + * @param core_if Programming view of DWC_otg controller.
44545 + * @param ep The EP to start the transfer on.
44546 + */
44547 +
44548 +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
44549 +                                         dwc_ep_t * ep)
44550 +{
44551 +       if (core_if->dma_enable) {
44552 +               if (core_if->dma_desc_enable) {
44553 +                       if (ep->is_in) {
44554 +                               ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
44555 +                       } else {
44556 +                               ep->desc_cnt = ep->pkt_cnt;
44557 +                       }
44558 +                       dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
44559 +               } else {
44560 +                       if (core_if->pti_enh_enable) {
44561 +                               dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
44562 +                       } else {
44563 +                               ep->cur_pkt_addr =
44564 +                                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
44565 +                                   xfer_buff0;
44566 +                               ep->cur_pkt_dma_addr =
44567 +                                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->
44568 +                                   dma_addr0;
44569 +                               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44570 +                       }
44571 +               }
44572 +       } else {
44573 +               ep->cur_pkt_addr =
44574 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44575 +               ep->cur_pkt_dma_addr =
44576 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44577 +               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44578 +       }
44579 +}
44580 +
44581 +/**
44582 + * This function stops transfer for an EP and
44583 + * resets the ep's variables.
44584 + *
44585 + * @param core_if Programming view of DWC_otg controller.
44586 + * @param ep The EP to start the transfer on.
44587 + */
44588 +
44589 +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
44590 +{
44591 +       depctl_data_t depctl = {.d32 = 0 };
44592 +       volatile uint32_t *addr;
44593 +
44594 +       if (ep->is_in == 1) {
44595 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44596 +       } else {
44597 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44598 +       }
44599 +
44600 +       /* disable the ep */
44601 +       depctl.d32 = DWC_READ_REG32(addr);
44602 +
44603 +       depctl.b.epdis = 1;
44604 +       depctl.b.snak = 1;
44605 +
44606 +       DWC_WRITE_REG32(addr, depctl.d32);
44607 +
44608 +       if (core_if->dma_desc_enable &&
44609 +           ep->iso_desc_addr && ep->iso_dma_desc_addr) {
44610 +               dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
44611 +                                          ep->iso_dma_desc_addr,
44612 +                                          ep->desc_cnt * 2);
44613 +       }
44614 +
44615 +       /* reset varibales */
44616 +       ep->dma_addr0 = 0;
44617 +       ep->dma_addr1 = 0;
44618 +       ep->xfer_buff0 = 0;
44619 +       ep->xfer_buff1 = 0;
44620 +       ep->data_per_frame = 0;
44621 +       ep->data_pattern_frame = 0;
44622 +       ep->sync_frame = 0;
44623 +       ep->buf_proc_intrvl = 0;
44624 +       ep->bInterval = 0;
44625 +       ep->proc_buf_num = 0;
44626 +       ep->pkt_per_frm = 0;
44627 +       ep->pkt_per_frm = 0;
44628 +       ep->desc_cnt = 0;
44629 +       ep->iso_desc_addr = 0;
44630 +       ep->iso_dma_desc_addr = 0;
44631 +}
44632 +
44633 +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
44634 +                            uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
44635 +                            dwc_dma_t dma1, int sync_frame, int dp_frame,
44636 +                            int data_per_frame, int start_frame,
44637 +                            int buf_proc_intrvl, void *req_handle,
44638 +                            int atomic_alloc)
44639 +{
44640 +       dwc_otg_pcd_ep_t *ep;
44641 +       dwc_irqflags_t flags = 0;
44642 +       dwc_ep_t *dwc_ep;
44643 +       int32_t frm_data;
44644 +       dsts_data_t dsts;
44645 +       dwc_otg_core_if_t *core_if;
44646 +
44647 +       ep = get_ep_from_handle(pcd, ep_handle);
44648 +
44649 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44650 +               DWC_WARN("bad ep\n");
44651 +               return -DWC_E_INVALID;
44652 +       }
44653 +
44654 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44655 +       core_if = GET_CORE_IF(pcd);
44656 +       dwc_ep = &ep->dwc_ep;
44657 +
44658 +       if (ep->iso_req_handle) {
44659 +               DWC_WARN("ISO request in progress\n");
44660 +       }
44661 +
44662 +       dwc_ep->dma_addr0 = dma0;
44663 +       dwc_ep->dma_addr1 = dma1;
44664 +
44665 +       dwc_ep->xfer_buff0 = buf0;
44666 +       dwc_ep->xfer_buff1 = buf1;
44667 +
44668 +       dwc_ep->data_per_frame = data_per_frame;
44669 +
44670 +       /** @todo - pattern data support is to be implemented in the future */
44671 +       dwc_ep->data_pattern_frame = dp_frame;
44672 +       dwc_ep->sync_frame = sync_frame;
44673 +
44674 +       dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
44675 +
44676 +       dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
44677 +
44678 +       dwc_ep->proc_buf_num = 0;
44679 +
44680 +       dwc_ep->pkt_per_frm = 0;
44681 +       frm_data = ep->dwc_ep.data_per_frame;
44682 +       while (frm_data > 0) {
44683 +               dwc_ep->pkt_per_frm++;
44684 +               frm_data -= ep->dwc_ep.maxpacket;
44685 +       }
44686 +
44687 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44688 +
44689 +       if (start_frame == -1) {
44690 +               dwc_ep->next_frame = dsts.b.soffn + 1;
44691 +               if (dwc_ep->bInterval != 1) {
44692 +                       dwc_ep->next_frame =
44693 +                           dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
44694 +                                                 dwc_ep->next_frame %
44695 +                                                 dwc_ep->bInterval);
44696 +               }
44697 +       } else {
44698 +               dwc_ep->next_frame = start_frame;
44699 +       }
44700 +
44701 +       if (!core_if->pti_enh_enable) {
44702 +               dwc_ep->pkt_cnt =
44703 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44704 +                   dwc_ep->bInterval;
44705 +       } else {
44706 +               dwc_ep->pkt_cnt =
44707 +                   (dwc_ep->data_per_frame *
44708 +                    (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
44709 +                    - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
44710 +       }
44711 +
44712 +       if (core_if->dma_desc_enable) {
44713 +               dwc_ep->desc_cnt =
44714 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44715 +                   dwc_ep->bInterval;
44716 +       }
44717 +
44718 +       if (atomic_alloc) {
44719 +               dwc_ep->pkt_info =
44720 +                   DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44721 +       } else {
44722 +               dwc_ep->pkt_info =
44723 +                   DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44724 +       }
44725 +       if (!dwc_ep->pkt_info) {
44726 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44727 +               return -DWC_E_NO_MEMORY;
44728 +       }
44729 +       if (core_if->pti_enh_enable) {
44730 +               dwc_memset(dwc_ep->pkt_info, 0,
44731 +                          sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44732 +       }
44733 +
44734 +       dwc_ep->cur_pkt = 0;
44735 +       ep->iso_req_handle = req_handle;
44736 +
44737 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44738 +       dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
44739 +       return 0;
44740 +}
44741 +
44742 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
44743 +                           void *req_handle)
44744 +{
44745 +       dwc_irqflags_t flags = 0;
44746 +       dwc_otg_pcd_ep_t *ep;
44747 +       dwc_ep_t *dwc_ep;
44748 +
44749 +       ep = get_ep_from_handle(pcd, ep_handle);
44750 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44751 +               DWC_WARN("bad ep\n");
44752 +               return -DWC_E_INVALID;
44753 +       }
44754 +       dwc_ep = &ep->dwc_ep;
44755 +
44756 +       dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
44757 +
44758 +       DWC_FREE(dwc_ep->pkt_info);
44759 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44760 +       if (ep->iso_req_handle != req_handle) {
44761 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44762 +               return -DWC_E_INVALID;
44763 +       }
44764 +
44765 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44766 +
44767 +       ep->iso_req_handle = 0;
44768 +       return 0;
44769 +}
44770 +
44771 +/**
44772 + * This function is used for perodical data exchnage between PCD and gadget drivers.
44773 + * for Isochronous EPs
44774 + *
44775 + *     - Every time a sync period completes this function is called to
44776 + *       perform data exchange between PCD and gadget
44777 + */
44778 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
44779 +                            void *req_handle)
44780 +{
44781 +       int i;
44782 +       dwc_ep_t *dwc_ep;
44783 +
44784 +       dwc_ep = &ep->dwc_ep;
44785 +
44786 +       DWC_SPINUNLOCK(ep->pcd->lock);
44787 +       pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
44788 +                                dwc_ep->proc_buf_num ^ 0x1);
44789 +       DWC_SPINLOCK(ep->pcd->lock);
44790 +
44791 +       for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
44792 +               dwc_ep->pkt_info[i].status = 0;
44793 +               dwc_ep->pkt_info[i].offset = 0;
44794 +               dwc_ep->pkt_info[i].length = 0;
44795 +       }
44796 +}
44797 +
44798 +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
44799 +                                    void *iso_req_handle)
44800 +{
44801 +       dwc_otg_pcd_ep_t *ep;
44802 +       dwc_ep_t *dwc_ep;
44803 +
44804 +       ep = get_ep_from_handle(pcd, ep_handle);
44805 +       if (!ep->desc || ep->dwc_ep.num == 0) {
44806 +               DWC_WARN("bad ep\n");
44807 +               return -DWC_E_INVALID;
44808 +       }
44809 +       dwc_ep = &ep->dwc_ep;
44810 +
44811 +       return dwc_ep->pkt_cnt;
44812 +}
44813 +
44814 +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
44815 +                                      void *iso_req_handle, int packet,
44816 +                                      int *status, int *actual, int *offset)
44817 +{
44818 +       dwc_otg_pcd_ep_t *ep;
44819 +       dwc_ep_t *dwc_ep;
44820 +
44821 +       ep = get_ep_from_handle(pcd, ep_handle);
44822 +       if (!ep)
44823 +               DWC_WARN("bad ep\n");
44824 +
44825 +       dwc_ep = &ep->dwc_ep;
44826 +
44827 +       *status = dwc_ep->pkt_info[packet].status;
44828 +       *actual = dwc_ep->pkt_info[packet].length;
44829 +       *offset = dwc_ep->pkt_info[packet].offset;
44830 +}
44831 +
44832 +#endif /* DWC_EN_ISOC */
44833 +
44834 +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
44835 +                               uint32_t is_in, uint32_t ep_num)
44836 +{
44837 +       /* Init EP structure */
44838 +       pcd_ep->desc = 0;
44839 +       pcd_ep->pcd = pcd;
44840 +       pcd_ep->stopped = 1;
44841 +       pcd_ep->queue_sof = 0;
44842 +
44843 +       /* Init DWC ep structure */
44844 +       pcd_ep->dwc_ep.is_in = is_in;
44845 +       pcd_ep->dwc_ep.num = ep_num;
44846 +       pcd_ep->dwc_ep.active = 0;
44847 +       pcd_ep->dwc_ep.tx_fifo_num = 0;
44848 +       /* Control until ep is actvated */
44849 +       pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44850 +       pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
44851 +       pcd_ep->dwc_ep.dma_addr = 0;
44852 +       pcd_ep->dwc_ep.start_xfer_buff = 0;
44853 +       pcd_ep->dwc_ep.xfer_buff = 0;
44854 +       pcd_ep->dwc_ep.xfer_len = 0;
44855 +       pcd_ep->dwc_ep.xfer_count = 0;
44856 +       pcd_ep->dwc_ep.sent_zlp = 0;
44857 +       pcd_ep->dwc_ep.total_len = 0;
44858 +       pcd_ep->dwc_ep.desc_addr = 0;
44859 +       pcd_ep->dwc_ep.dma_desc_addr = 0;
44860 +       DWC_CIRCLEQ_INIT(&pcd_ep->queue);
44861 +}
44862 +
44863 +/**
44864 + * Initialize ep's
44865 + */
44866 +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
44867 +{
44868 +       int i;
44869 +       uint32_t hwcfg1;
44870 +       dwc_otg_pcd_ep_t *ep;
44871 +       int in_ep_cntr, out_ep_cntr;
44872 +       uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
44873 +       uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
44874 +
44875 +       /**
44876 +        * Initialize the EP0 structure.
44877 +        */
44878 +       ep = &pcd->ep0;
44879 +       dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
44880 +
44881 +       in_ep_cntr = 0;
44882 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
44883 +       for (i = 1; in_ep_cntr < num_in_eps; i++) {
44884 +               if ((hwcfg1 & 0x1) == 0) {
44885 +                       dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
44886 +                       in_ep_cntr++;
44887 +                       /**
44888 +                        * @todo NGS: Add direction to EP, based on contents
44889 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44890 +                        * sprintf(";r
44891 +                        */
44892 +                       dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
44893 +
44894 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44895 +               }
44896 +               hwcfg1 >>= 2;
44897 +       }
44898 +
44899 +       out_ep_cntr = 0;
44900 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
44901 +       for (i = 1; out_ep_cntr < num_out_eps; i++) {
44902 +               if ((hwcfg1 & 0x1) == 0) {
44903 +                       dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
44904 +                       out_ep_cntr++;
44905 +                       /**
44906 +                        * @todo NGS: Add direction to EP, based on contents
44907 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44908 +                        * sprintf(";r
44909 +                        */
44910 +                       dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
44911 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44912 +               }
44913 +               hwcfg1 >>= 2;
44914 +       }
44915 +
44916 +       pcd->ep0state = EP0_DISCONNECT;
44917 +       pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
44918 +       pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44919 +}
44920 +
44921 +/**
44922 + * This function is called when the SRP timer expires. The SRP should
44923 + * complete within 6 seconds.
44924 + */
44925 +static void srp_timeout(void *ptr)
44926 +{
44927 +       gotgctl_data_t gotgctl;
44928 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
44929 +       volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
44930 +
44931 +       gotgctl.d32 = DWC_READ_REG32(addr);
44932 +
44933 +       core_if->srp_timer_started = 0;
44934 +
44935 +       if (core_if->adp_enable) {
44936 +               if (gotgctl.b.bsesvld == 0) {
44937 +                       gpwrdn_data_t gpwrdn = {.d32 = 0 };
44938 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
44939 +                       /* Power off the core */
44940 +                       if (core_if->power_down == 2) {
44941 +                               gpwrdn.b.pwrdnswtch = 1;
44942 +                               DWC_MODIFY_REG32(&core_if->
44943 +                                                core_global_regs->gpwrdn,
44944 +                                                gpwrdn.d32, 0);
44945 +                       }
44946 +
44947 +                       gpwrdn.d32 = 0;
44948 +                       gpwrdn.b.pmuintsel = 1;
44949 +                       gpwrdn.b.pmuactv = 1;
44950 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
44951 +                                        gpwrdn.d32);
44952 +                       dwc_otg_adp_probe_start(core_if);
44953 +               } else {
44954 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
44955 +                       core_if->op_state = B_PERIPHERAL;
44956 +                       dwc_otg_core_init(core_if);
44957 +                       dwc_otg_enable_global_interrupts(core_if);
44958 +                       cil_pcd_start(core_if);
44959 +               }
44960 +       }
44961 +
44962 +       if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
44963 +           (core_if->core_params->i2c_enable)) {
44964 +               DWC_PRINTF("SRP Timeout\n");
44965 +
44966 +               if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
44967 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
44968 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
44969 +                       }
44970 +
44971 +                       /* Clear Session Request */
44972 +                       gotgctl.d32 = 0;
44973 +                       gotgctl.b.sesreq = 1;
44974 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
44975 +                                        gotgctl.d32, 0);
44976 +
44977 +                       core_if->srp_success = 0;
44978 +               } else {
44979 +                       __DWC_ERROR("Device not connected/responding\n");
44980 +                       gotgctl.b.sesreq = 0;
44981 +                       DWC_WRITE_REG32(addr, gotgctl.d32);
44982 +               }
44983 +       } else if (gotgctl.b.sesreq) {
44984 +               DWC_PRINTF("SRP Timeout\n");
44985 +
44986 +               __DWC_ERROR("Device not connected/responding\n");
44987 +               gotgctl.b.sesreq = 0;
44988 +               DWC_WRITE_REG32(addr, gotgctl.d32);
44989 +       } else {
44990 +               DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
44991 +       }
44992 +}
44993 +
44994 +/**
44995 + * Tasklet
44996 + *
44997 + */
44998 +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
44999 +
45000 +static void start_xfer_tasklet_func(void *data)
45001 +{
45002 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
45003 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45004 +
45005 +       int i;
45006 +       depctl_data_t diepctl;
45007 +
45008 +       DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
45009 +
45010 +       diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
45011 +
45012 +       if (pcd->ep0.queue_sof) {
45013 +               pcd->ep0.queue_sof = 0;
45014 +               start_next_request(&pcd->ep0);
45015 +               // break;
45016 +       }
45017 +
45018 +       for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
45019 +               depctl_data_t diepctl;
45020 +               diepctl.d32 =
45021 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
45022 +
45023 +               if (pcd->in_ep[i].queue_sof) {
45024 +                       pcd->in_ep[i].queue_sof = 0;
45025 +                       start_next_request(&pcd->in_ep[i]);
45026 +                       // break;
45027 +               }
45028 +       }
45029 +
45030 +       return;
45031 +}
45032 +
45033 +/**
45034 + * This function initialized the PCD portion of the driver.
45035 + *
45036 + */
45037 +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
45038 +{
45039 +       dwc_otg_pcd_t *pcd = NULL;
45040 +       dwc_otg_dev_if_t *dev_if;
45041 +       int i;
45042 +
45043 +       /*
45044 +        * Allocate PCD structure
45045 +        */
45046 +       pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
45047 +
45048 +       if (pcd == NULL) {
45049 +               return NULL;
45050 +       }
45051 +
45052 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
45053 +       DWC_SPINLOCK_ALLOC_LINUX_DEBUG(pcd->lock);
45054 +#else
45055 +       pcd->lock = DWC_SPINLOCK_ALLOC();
45056 +#endif
45057 +        DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
45058 +                    pcd, core_if);//GRAYG
45059 +       if (!pcd->lock) {
45060 +               DWC_ERROR("Could not allocate lock for pcd");
45061 +               DWC_FREE(pcd);
45062 +               return NULL;
45063 +       }
45064 +       /* Set core_if's lock pointer to hcd->lock */
45065 +       core_if->lock = pcd->lock;
45066 +       pcd->core_if = core_if;
45067 +
45068 +       dev_if = core_if->dev_if;
45069 +       dev_if->isoc_ep = NULL;
45070 +
45071 +       if (core_if->hwcfg4.b.ded_fifo_en) {
45072 +               DWC_PRINTF("Dedicated Tx FIFOs mode\n");
45073 +       } else {
45074 +               DWC_PRINTF("Shared Tx FIFO mode\n");
45075 +       }
45076 +
45077 +       /*
45078 +        * Initialized the Core for Device mode here if there is nod ADP support.
45079 +        * Otherwise it will be done later in dwc_otg_adp_start routine.
45080 +        */
45081 +       if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
45082 +               dwc_otg_core_dev_init(core_if);
45083 +       }
45084 +
45085 +       /*
45086 +        * Register the PCD Callbacks.
45087 +        */
45088 +       dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
45089 +
45090 +       /*
45091 +        * Initialize the DMA buffer for SETUP packets
45092 +        */
45093 +       if (GET_CORE_IF(pcd)->dma_enable) {
45094 +               pcd->setup_pkt =
45095 +                   DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
45096 +                                 &pcd->setup_pkt_dma_handle);
45097 +               if (pcd->setup_pkt == NULL) {
45098 +                       DWC_FREE(pcd);
45099 +                       return NULL;
45100 +               }
45101 +
45102 +               pcd->status_buf =
45103 +                   DWC_DMA_ALLOC(sizeof(uint16_t),
45104 +                                 &pcd->status_buf_dma_handle);
45105 +               if (pcd->status_buf == NULL) {
45106 +                       DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45107 +                                    pcd->setup_pkt, pcd->setup_pkt_dma_handle);
45108 +                       DWC_FREE(pcd);
45109 +                       return NULL;
45110 +               }
45111 +
45112 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
45113 +                       dev_if->setup_desc_addr[0] =
45114 +                           dwc_otg_ep_alloc_desc_chain
45115 +                           (&dev_if->dma_setup_desc_addr[0], 1);
45116 +                       dev_if->setup_desc_addr[1] =
45117 +                           dwc_otg_ep_alloc_desc_chain
45118 +                           (&dev_if->dma_setup_desc_addr[1], 1);
45119 +                       dev_if->in_desc_addr =
45120 +                           dwc_otg_ep_alloc_desc_chain
45121 +                           (&dev_if->dma_in_desc_addr, 1);
45122 +                       dev_if->out_desc_addr =
45123 +                           dwc_otg_ep_alloc_desc_chain
45124 +                           (&dev_if->dma_out_desc_addr, 1);
45125 +                       pcd->data_terminated = 0;
45126 +
45127 +                       if (dev_if->setup_desc_addr[0] == 0
45128 +                           || dev_if->setup_desc_addr[1] == 0
45129 +                           || dev_if->in_desc_addr == 0
45130 +                           || dev_if->out_desc_addr == 0) {
45131 +
45132 +                               if (dev_if->out_desc_addr)
45133 +                                       dwc_otg_ep_free_desc_chain
45134 +                                           (dev_if->out_desc_addr,
45135 +                                            dev_if->dma_out_desc_addr, 1);
45136 +                               if (dev_if->in_desc_addr)
45137 +                                       dwc_otg_ep_free_desc_chain
45138 +                                           (dev_if->in_desc_addr,
45139 +                                            dev_if->dma_in_desc_addr, 1);
45140 +                               if (dev_if->setup_desc_addr[1])
45141 +                                       dwc_otg_ep_free_desc_chain
45142 +                                           (dev_if->setup_desc_addr[1],
45143 +                                            dev_if->dma_setup_desc_addr[1], 1);
45144 +                               if (dev_if->setup_desc_addr[0])
45145 +                                       dwc_otg_ep_free_desc_chain
45146 +                                           (dev_if->setup_desc_addr[0],
45147 +                                            dev_if->dma_setup_desc_addr[0], 1);
45148 +
45149 +                               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45150 +                                            pcd->setup_pkt,
45151 +                                            pcd->setup_pkt_dma_handle);
45152 +                               DWC_DMA_FREE(sizeof(*pcd->status_buf),
45153 +                                            pcd->status_buf,
45154 +                                            pcd->status_buf_dma_handle);
45155 +
45156 +                               DWC_FREE(pcd);
45157 +
45158 +                               return NULL;
45159 +                       }
45160 +               }
45161 +       } else {
45162 +               pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
45163 +               if (pcd->setup_pkt == NULL) {
45164 +                       DWC_FREE(pcd);
45165 +                       return NULL;
45166 +               }
45167 +
45168 +               pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
45169 +               if (pcd->status_buf == NULL) {
45170 +                       DWC_FREE(pcd->setup_pkt);
45171 +                       DWC_FREE(pcd);
45172 +                       return NULL;
45173 +               }
45174 +       }
45175 +
45176 +       dwc_otg_pcd_reinit(pcd);
45177 +
45178 +       /* Allocate the cfi object for the PCD */
45179 +#ifdef DWC_UTE_CFI
45180 +       pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
45181 +       if (NULL == pcd->cfi)
45182 +               goto fail;
45183 +       if (init_cfi(pcd->cfi)) {
45184 +               CFI_INFO("%s: Failed to init the CFI object\n", __func__);
45185 +               goto fail;
45186 +       }
45187 +#endif
45188 +
45189 +       /* Initialize tasklets */
45190 +       pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
45191 +                                                start_xfer_tasklet_func, pcd);
45192 +       pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
45193 +                                               do_test_mode, pcd);
45194 +
45195 +       /* Initialize SRP timer */
45196 +       core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
45197 +
45198 +       if (core_if->core_params->dev_out_nak) {
45199 +               /**
45200 +               * Initialize xfer timeout timer. Implemented for
45201 +               * 2.93a feature "Device DDMA OUT NAK Enhancement"
45202 +               */
45203 +               for(i = 0; i < MAX_EPS_CHANNELS; i++) {
45204 +                       pcd->core_if->ep_xfer_timer[i] =
45205 +                               DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
45206 +                               &pcd->core_if->ep_xfer_info[i]);
45207 +               }
45208 +       }
45209 +
45210 +       return pcd;
45211 +#ifdef DWC_UTE_CFI
45212 +fail:
45213 +#endif
45214 +       if (pcd->setup_pkt)
45215 +               DWC_FREE(pcd->setup_pkt);
45216 +       if (pcd->status_buf)
45217 +               DWC_FREE(pcd->status_buf);
45218 +#ifdef DWC_UTE_CFI
45219 +       if (pcd->cfi)
45220 +               DWC_FREE(pcd->cfi);
45221 +#endif
45222 +       if (pcd)
45223 +               DWC_FREE(pcd);
45224 +       return NULL;
45225 +
45226 +}
45227 +
45228 +/**
45229 + * Remove PCD specific data
45230 + */
45231 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
45232 +{
45233 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
45234 +       int i;
45235 +       if (pcd->core_if->core_params->dev_out_nak) {
45236 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45237 +                       DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
45238 +                       pcd->core_if->ep_xfer_info[i].state = 0;
45239 +               }
45240 +       }
45241 +
45242 +       if (GET_CORE_IF(pcd)->dma_enable) {
45243 +               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
45244 +                            pcd->setup_pkt_dma_handle);
45245 +               DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
45246 +                            pcd->status_buf_dma_handle);
45247 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
45248 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
45249 +                                                  dev_if->dma_setup_desc_addr
45250 +                                                  [0], 1);
45251 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
45252 +                                                  dev_if->dma_setup_desc_addr
45253 +                                                  [1], 1);
45254 +                       dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
45255 +                                                  dev_if->dma_in_desc_addr, 1);
45256 +                       dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
45257 +                                                  dev_if->dma_out_desc_addr,
45258 +                                                  1);
45259 +               }
45260 +       } else {
45261 +               DWC_FREE(pcd->setup_pkt);
45262 +               DWC_FREE(pcd->status_buf);
45263 +       }
45264 +       DWC_SPINLOCK_FREE(pcd->lock);
45265 +       /* Set core_if's lock pointer to NULL */
45266 +       pcd->core_if->lock = NULL;
45267 +
45268 +       DWC_TASK_FREE(pcd->start_xfer_tasklet);
45269 +       DWC_TASK_FREE(pcd->test_mode_tasklet);
45270 +       if (pcd->core_if->core_params->dev_out_nak) {
45271 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45272 +                       if (pcd->core_if->ep_xfer_timer[i]) {
45273 +                                       DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
45274 +                       }
45275 +               }
45276 +       }
45277 +
45278 +/* Release the CFI object's dynamic memory */
45279 +#ifdef DWC_UTE_CFI
45280 +       if (pcd->cfi->ops.release) {
45281 +               pcd->cfi->ops.release(pcd->cfi);
45282 +       }
45283 +#endif
45284 +
45285 +       DWC_FREE(pcd);
45286 +}
45287 +
45288 +/**
45289 + * Returns whether registered pcd is dual speed or not
45290 + */
45291 +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
45292 +{
45293 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45294 +
45295 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
45296 +           ((core_if->hwcfg2.b.hs_phy_type == 2) &&
45297 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
45298 +            (core_if->core_params->ulpi_fs_ls))) {
45299 +               return 0;
45300 +       }
45301 +
45302 +       return 1;
45303 +}
45304 +
45305 +/**
45306 + * Returns whether registered pcd is OTG capable or not
45307 + */
45308 +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
45309 +{
45310 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45311 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
45312 +
45313 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
45314 +       if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
45315 +               return 0;
45316 +       }
45317 +
45318 +       return 1;
45319 +}
45320 +
45321 +/**
45322 + * This function assigns periodic Tx FIFO to an periodic EP
45323 + * in shared Tx FIFO mode
45324 + */
45325 +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
45326 +{
45327 +       uint32_t TxMsk = 1;
45328 +       int i;
45329 +
45330 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
45331 +               if ((TxMsk & core_if->tx_msk) == 0) {
45332 +                       core_if->tx_msk |= TxMsk;
45333 +                       return i + 1;
45334 +               }
45335 +               TxMsk <<= 1;
45336 +       }
45337 +       return 0;
45338 +}
45339 +
45340 +/**
45341 + * This function assigns periodic Tx FIFO to an periodic EP
45342 + * in shared Tx FIFO mode
45343 + */
45344 +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
45345 +{
45346 +       uint32_t PerTxMsk = 1;
45347 +       int i;
45348 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
45349 +               if ((PerTxMsk & core_if->p_tx_msk) == 0) {
45350 +                       core_if->p_tx_msk |= PerTxMsk;
45351 +                       return i + 1;
45352 +               }
45353 +               PerTxMsk <<= 1;
45354 +       }
45355 +       return 0;
45356 +}
45357 +
45358 +/**
45359 + * This function releases periodic Tx FIFO
45360 + * in shared Tx FIFO mode
45361 + */
45362 +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
45363 +                                 uint32_t fifo_num)
45364 +{
45365 +       core_if->p_tx_msk =
45366 +           (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
45367 +}
45368 +
45369 +/**
45370 + * This function releases periodic Tx FIFO
45371 + * in shared Tx FIFO mode
45372 + */
45373 +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
45374 +{
45375 +       core_if->tx_msk =
45376 +           (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
45377 +}
45378 +
45379 +/**
45380 + * This function is being called from gadget
45381 + * to enable PCD endpoint.
45382 + */
45383 +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
45384 +                         const uint8_t * ep_desc, void *usb_ep)
45385 +{
45386 +       int num, dir;
45387 +       dwc_otg_pcd_ep_t *ep = NULL;
45388 +       const usb_endpoint_descriptor_t *desc;
45389 +       dwc_irqflags_t flags;
45390 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45391 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45392 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45393 +       int retval = 0;
45394 +       int i, epcount;
45395 +
45396 +       desc = (const usb_endpoint_descriptor_t *)ep_desc;
45397 +
45398 +       if (!desc) {
45399 +               pcd->ep0.priv = usb_ep;
45400 +               ep = &pcd->ep0;
45401 +               retval = -DWC_E_INVALID;
45402 +               goto out;
45403 +       }
45404 +
45405 +       num = UE_GET_ADDR(desc->bEndpointAddress);
45406 +       dir = UE_GET_DIR(desc->bEndpointAddress);
45407 +
45408 +       if (!desc->wMaxPacketSize) {
45409 +               DWC_WARN("bad maxpacketsize\n");
45410 +               retval = -DWC_E_INVALID;
45411 +               goto out;
45412 +       }
45413 +
45414 +       if (dir == UE_DIR_IN) {
45415 +               epcount = pcd->core_if->dev_if->num_in_eps;
45416 +               for (i = 0; i < epcount; i++) {
45417 +                       if (num == pcd->in_ep[i].dwc_ep.num) {
45418 +                               ep = &pcd->in_ep[i];
45419 +                               break;
45420 +                       }
45421 +               }
45422 +       } else {
45423 +               epcount = pcd->core_if->dev_if->num_out_eps;
45424 +               for (i = 0; i < epcount; i++) {
45425 +                       if (num == pcd->out_ep[i].dwc_ep.num) {
45426 +                               ep = &pcd->out_ep[i];
45427 +                               break;
45428 +                       }
45429 +               }
45430 +       }
45431 +
45432 +       if (!ep) {
45433 +               DWC_WARN("bad address\n");
45434 +               retval = -DWC_E_INVALID;
45435 +               goto out;
45436 +       }
45437 +
45438 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45439 +
45440 +       ep->desc = desc;
45441 +       ep->priv = usb_ep;
45442 +
45443 +       /*
45444 +        * Activate the EP
45445 +        */
45446 +       ep->stopped = 0;
45447 +
45448 +       ep->dwc_ep.is_in = (dir == UE_DIR_IN);
45449 +       ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
45450 +
45451 +       ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
45452 +
45453 +       if (ep->dwc_ep.is_in) {
45454 +               if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45455 +                       ep->dwc_ep.tx_fifo_num = 0;
45456 +
45457 +                       if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
45458 +                               /*
45459 +                                * if ISOC EP then assign a Periodic Tx FIFO.
45460 +                                */
45461 +                               ep->dwc_ep.tx_fifo_num =
45462 +                                   assign_perio_tx_fifo(GET_CORE_IF(pcd));
45463 +                       }
45464 +               } else {
45465 +                       /*
45466 +                        * if Dedicated FIFOs mode is on then assign a Tx FIFO.
45467 +                        */
45468 +                       ep->dwc_ep.tx_fifo_num =
45469 +                           assign_tx_fifo(GET_CORE_IF(pcd));
45470 +               }
45471 +
45472 +               /* Calculating EP info controller base address */
45473 +               if (ep->dwc_ep.tx_fifo_num
45474 +                   && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45475 +                       gdfifocfg.d32 =
45476 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
45477 +                                          core_global_regs->gdfifocfg);
45478 +                       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45479 +                       dptxfsiz.d32 =
45480 +                           (DWC_READ_REG32
45481 +                            (&GET_CORE_IF(pcd)->core_global_regs->
45482 +                             dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);
45483 +                       gdfifocfg.b.epinfobase =
45484 +                           gdfifocfgbase.d32 + dptxfsiz.d32;
45485 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45486 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45487 +                                               core_global_regs->gdfifocfg,
45488 +                                               gdfifocfg.d32);
45489 +                       }
45490 +               }
45491 +       }
45492 +       /* Set initial data PID. */
45493 +       if (ep->dwc_ep.type == UE_BULK) {
45494 +               ep->dwc_ep.data_pid_start = 0;
45495 +       }
45496 +
45497 +       /* Alloc DMA Descriptors */
45498 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45499 +#ifndef DWC_UTE_PER_IO
45500 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45501 +#endif
45502 +                       ep->dwc_ep.desc_addr =
45503 +                           dwc_otg_ep_alloc_desc_chain(&ep->
45504 +                                                       dwc_ep.dma_desc_addr,
45505 +                                                       MAX_DMA_DESC_CNT);
45506 +                       if (!ep->dwc_ep.desc_addr) {
45507 +                               DWC_WARN("%s, can't allocate DMA descriptor\n",
45508 +                                        __func__);
45509 +                               retval = -DWC_E_SHUTDOWN;
45510 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45511 +                               goto out;
45512 +                       }
45513 +#ifndef DWC_UTE_PER_IO
45514 +               }
45515 +#endif
45516 +       }
45517 +
45518 +       DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
45519 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"),
45520 +                   ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
45521 +#ifdef DWC_UTE_PER_IO
45522 +       ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
45523 +#endif
45524 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45525 +               ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
45526 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
45527 +       }
45528 +
45529 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
45530 +
45531 +#ifdef DWC_UTE_CFI
45532 +       if (pcd->cfi->ops.ep_enable) {
45533 +               pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
45534 +       }
45535 +#endif
45536 +
45537 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45538 +
45539 +out:
45540 +       return retval;
45541 +}
45542 +
45543 +/**
45544 + * This function is being called from gadget
45545 + * to disable PCD endpoint.
45546 + */
45547 +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
45548 +{
45549 +       dwc_otg_pcd_ep_t *ep;
45550 +       dwc_irqflags_t flags;
45551 +       dwc_otg_dev_dma_desc_t *desc_addr;
45552 +       dwc_dma_t dma_desc_addr;
45553 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45554 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45555 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45556 +
45557 +       ep = get_ep_from_handle(pcd, ep_handle);
45558 +
45559 +       if (!ep || !ep->desc) {
45560 +               DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
45561 +               return -DWC_E_INVALID;
45562 +       }
45563 +
45564 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45565 +
45566 +       dwc_otg_request_nuke(ep);
45567 +
45568 +       dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
45569 +       if (pcd->core_if->core_params->dev_out_nak) {
45570 +               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
45571 +               pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
45572 +       }
45573 +       ep->desc = NULL;
45574 +       ep->stopped = 1;
45575 +
45576 +       gdfifocfg.d32 =
45577 +           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
45578 +       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45579 +
45580 +       if (ep->dwc_ep.is_in) {
45581 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45582 +                       /* Flush the Tx FIFO */
45583 +                       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),
45584 +                                             ep->dwc_ep.tx_fifo_num);
45585 +               }
45586 +               release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45587 +               release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45588 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45589 +                       /* Decreasing EPinfo Base Addr */
45590 +                       dptxfsiz.d32 =
45591 +                           (DWC_READ_REG32
45592 +                            (&GET_CORE_IF(pcd)->
45593 +                               core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
45594 +                       gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
45595 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45596 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
45597 +                                       gdfifocfg.d32);
45598 +                       }
45599 +               }
45600 +       }
45601 +
45602 +       /* Free DMA Descriptors */
45603 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45604 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45605 +                       desc_addr = ep->dwc_ep.desc_addr;
45606 +                       dma_desc_addr = ep->dwc_ep.dma_desc_addr;
45607 +
45608 +                       /* Cannot call dma_free_coherent() with IRQs disabled */
45609 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45610 +                       dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
45611 +                                                  MAX_DMA_DESC_CNT);
45612 +
45613 +                       goto out_unlocked;
45614 +               }
45615 +       }
45616 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45617 +
45618 +out_unlocked:
45619 +       DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
45620 +                   ep->dwc_ep.is_in ? "IN" : "OUT");
45621 +       return 0;
45622 +
45623 +}
45624 +
45625 +/******************************************************************************/
45626 +#ifdef DWC_UTE_PER_IO
45627 +
45628 +/**
45629 + * Free the request and its extended parts
45630 + *
45631 + */
45632 +void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
45633 +{
45634 +       DWC_FREE(req->ext_req.per_io_frame_descs);
45635 +       DWC_FREE(req);
45636 +}
45637 +
45638 +/**
45639 + * Start the next request in the endpoint's queue.
45640 + *
45641 + */
45642 +int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
45643 +                                       dwc_otg_pcd_ep_t * ep)
45644 +{
45645 +       int i;
45646 +       dwc_otg_pcd_request_t *req = NULL;
45647 +       dwc_ep_t *dwcep = NULL;
45648 +       struct dwc_iso_xreq_port *ereq = NULL;
45649 +       struct dwc_iso_pkt_desc_port *ddesc_iso;
45650 +       uint16_t nat;
45651 +       depctl_data_t diepctl;
45652 +
45653 +       dwcep = &ep->dwc_ep;
45654 +
45655 +       if (dwcep->xiso_active_xfers > 0) {
45656 +#if 0  //Disable this to decrease s/w overhead that is crucial for Isoc transfers
45657 +               DWC_WARN("There are currently active transfers for EP%d \
45658 +                               (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers,
45659 +                               dwcep->xiso_queued_xfers);
45660 +#endif
45661 +               return 0;
45662 +       }
45663 +
45664 +       nat = UGETW(ep->desc->wMaxPacketSize);
45665 +       nat = (nat >> 11) & 0x03;
45666 +
45667 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45668 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45669 +               ereq = &req->ext_req;
45670 +               ep->stopped = 0;
45671 +
45672 +               /* Get the frame number */
45673 +               dwcep->xiso_frame_num =
45674 +                   dwc_otg_get_frame_number(GET_CORE_IF(pcd));
45675 +               DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
45676 +
45677 +               ddesc_iso = ereq->per_io_frame_descs;
45678 +
45679 +               if (dwcep->is_in) {
45680 +                       /* Setup DMA Descriptor chain for IN Isoc request */
45681 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45682 +                               //if ((i % (nat + 1)) == 0)
45683 +                               if ( i > 0 )
45684 +                                       dwcep->xiso_frame_num =
45685 +                                           (dwcep->xiso_bInterval +
45686 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45687 +                               dwcep->desc_addr[i].buf =
45688 +                                   req->dma + ddesc_iso[i].offset;
45689 +                               dwcep->desc_addr[i].status.b_iso_in.txbytes =
45690 +                                   ddesc_iso[i].length;
45691 +                               dwcep->desc_addr[i].status.b_iso_in.framenum =
45692 +                                   dwcep->xiso_frame_num;
45693 +                               dwcep->desc_addr[i].status.b_iso_in.bs =
45694 +                                   BS_HOST_READY;
45695 +                               dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
45696 +                               dwcep->desc_addr[i].status.b_iso_in.sp =
45697 +                                   (ddesc_iso[i].length %
45698 +                                    dwcep->maxpacket) ? 1 : 0;
45699 +                               dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
45700 +                               dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
45701 +                               dwcep->desc_addr[i].status.b_iso_in.l = 0;
45702 +
45703 +                               /* Process the last descriptor */
45704 +                               if (i == ereq->pio_pkt_count - 1) {
45705 +                                       dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
45706 +                                       dwcep->desc_addr[i].status.b_iso_in.l = 1;
45707 +                               }
45708 +                       }
45709 +
45710 +                       /* Setup and start the transfer for this endpoint */
45711 +                       dwcep->xiso_active_xfers++;
45712 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
45713 +                                       in_ep_regs[dwcep->num]->diepdma,
45714 +                                       dwcep->dma_desc_addr);
45715 +                       diepctl.d32 = 0;
45716 +                       diepctl.b.epena = 1;
45717 +                       diepctl.b.cnak = 1;
45718 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
45719 +                                        in_ep_regs[dwcep->num]->diepctl, 0,
45720 +                                        diepctl.d32);
45721 +               } else {
45722 +                       /* Setup DMA Descriptor chain for OUT Isoc request */
45723 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45724 +                               //if ((i % (nat + 1)) == 0)
45725 +                               dwcep->xiso_frame_num = (dwcep->xiso_bInterval +
45726 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45727 +                               dwcep->desc_addr[i].buf =
45728 +                                   req->dma + ddesc_iso[i].offset;
45729 +                               dwcep->desc_addr[i].status.b_iso_out.rxbytes =
45730 +                                   ddesc_iso[i].length;
45731 +                               dwcep->desc_addr[i].status.b_iso_out.framenum =
45732 +                                   dwcep->xiso_frame_num;
45733 +                               dwcep->desc_addr[i].status.b_iso_out.bs =
45734 +                                   BS_HOST_READY;
45735 +                               dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
45736 +                               dwcep->desc_addr[i].status.b_iso_out.sp =
45737 +                                   (ddesc_iso[i].length %
45738 +                                    dwcep->maxpacket) ? 1 : 0;
45739 +                               dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
45740 +                               dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
45741 +                               dwcep->desc_addr[i].status.b_iso_out.l = 0;
45742 +
45743 +                               /* Process the last descriptor */
45744 +                               if (i == ereq->pio_pkt_count - 1) {
45745 +                                       dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
45746 +                                       dwcep->desc_addr[i].status.b_iso_out.l = 1;
45747 +                               }
45748 +                       }
45749 +
45750 +                       /* Setup and start the transfer for this endpoint */
45751 +                       dwcep->xiso_active_xfers++;
45752 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45753 +                                       dev_if->out_ep_regs[dwcep->num]->
45754 +                                       doepdma, dwcep->dma_desc_addr);
45755 +                       diepctl.d32 = 0;
45756 +                       diepctl.b.epena = 1;
45757 +                       diepctl.b.cnak = 1;
45758 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
45759 +                                        dev_if->out_ep_regs[dwcep->num]->
45760 +                                        doepctl, 0, diepctl.d32);
45761 +               }
45762 +
45763 +       } else {
45764 +               ep->stopped = 1;
45765 +       }
45766 +
45767 +       return 0;
45768 +}
45769 +
45770 +/**
45771 + *     - Remove the request from the queue
45772 + */
45773 +void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
45774 +{
45775 +       dwc_otg_pcd_request_t *req = NULL;
45776 +       struct dwc_iso_xreq_port *ereq = NULL;
45777 +       struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
45778 +       dwc_ep_t *dwcep = NULL;
45779 +       int i;
45780 +
45781 +       //DWC_DEBUG();
45782 +       dwcep = &ep->dwc_ep;
45783 +
45784 +       /* Get the first pending request from the queue */
45785 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45786 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45787 +               if (!req) {
45788 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
45789 +                       return;
45790 +               }
45791 +               dwcep->xiso_active_xfers--;
45792 +               dwcep->xiso_queued_xfers--;
45793 +               /* Remove this request from the queue */
45794 +               DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
45795 +       } else {
45796 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
45797 +               return;
45798 +       }
45799 +
45800 +       ep->stopped = 1;
45801 +       ereq = &req->ext_req;
45802 +       ddesc_iso = ereq->per_io_frame_descs;
45803 +
45804 +       if (dwcep->xiso_active_xfers < 0) {
45805 +               DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
45806 +                        dwcep->xiso_active_xfers);
45807 +       }
45808 +
45809 +       /* Fill the Isoc descs of portable extended req from dma descriptors */
45810 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45811 +               if (dwcep->is_in) {     /* IN endpoints */
45812 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45813 +                           dwcep->desc_addr[i].status.b_iso_in.txbytes;
45814 +                       ddesc_iso[i].status =
45815 +                           dwcep->desc_addr[i].status.b_iso_in.txsts;
45816 +               } else {        /* OUT endpoints */
45817 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45818 +                           dwcep->desc_addr[i].status.b_iso_out.rxbytes;
45819 +                       ddesc_iso[i].status =
45820 +                           dwcep->desc_addr[i].status.b_iso_out.rxsts;
45821 +               }
45822 +       }
45823 +
45824 +       DWC_SPINUNLOCK(ep->pcd->lock);
45825 +
45826 +       /* Call the completion function in the non-portable logic */
45827 +       ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
45828 +                                     &req->ext_req);
45829 +
45830 +       DWC_SPINLOCK(ep->pcd->lock);
45831 +
45832 +       /* Free the request - specific freeing needed for extended request object */
45833 +       dwc_pcd_xiso_ereq_free(ep, req);
45834 +
45835 +       /* Start the next request */
45836 +       dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
45837 +
45838 +       return;
45839 +}
45840 +
45841 +/**
45842 + * Create and initialize the Isoc pkt descriptors of the extended request.
45843 + *
45844 + */
45845 +static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
45846 +                                            void *ereq_nonport,
45847 +                                            int atomic_alloc)
45848 +{
45849 +       struct dwc_iso_xreq_port *ereq = NULL;
45850 +       struct dwc_iso_xreq_port *req_mapped = NULL;
45851 +       struct dwc_iso_pkt_desc_port *ipds = NULL;      /* To be created in this function */
45852 +       uint32_t pkt_count;
45853 +       int i;
45854 +
45855 +       ereq = &req->ext_req;
45856 +       req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
45857 +       pkt_count = req_mapped->pio_pkt_count;
45858 +
45859 +       /* Create the isoc descs */
45860 +       if (atomic_alloc) {
45861 +               ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
45862 +       } else {
45863 +               ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
45864 +       }
45865 +
45866 +       if (!ipds) {
45867 +               DWC_ERROR("Failed to allocate isoc descriptors");
45868 +               return -DWC_E_NO_MEMORY;
45869 +       }
45870 +
45871 +       /* Initialize the extended request fields */
45872 +       ereq->per_io_frame_descs = ipds;
45873 +       ereq->error_count = 0;
45874 +       ereq->pio_alloc_pkt_count = pkt_count;
45875 +       ereq->pio_pkt_count = pkt_count;
45876 +       ereq->tr_sub_flags = req_mapped->tr_sub_flags;
45877 +
45878 +       /* Init the Isoc descriptors */
45879 +       for (i = 0; i < pkt_count; i++) {
45880 +               ipds[i].length = req_mapped->per_io_frame_descs[i].length;
45881 +               ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
45882 +               ipds[i].status = req_mapped->per_io_frame_descs[i].status;      /* 0 */
45883 +               ipds[i].actual_length =
45884 +                   req_mapped->per_io_frame_descs[i].actual_length;
45885 +       }
45886 +
45887 +       return 0;
45888 +}
45889 +
45890 +static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
45891 +{
45892 +       struct dwc_iso_pkt_desc_port *xfd = NULL;
45893 +       int i;
45894 +
45895 +       DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
45896 +       DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
45897 +       DWC_DEBUG("error_count=%d", ereq->error_count);
45898 +       DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
45899 +       DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
45900 +       DWC_DEBUG("res=%d", ereq->res);
45901 +
45902 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45903 +               xfd = &ereq->per_io_frame_descs[0];
45904 +               DWC_DEBUG("FD #%d", i);
45905 +
45906 +               DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
45907 +               DWC_DEBUG("xfd->length=%d", xfd->length);
45908 +               DWC_DEBUG("xfd->offset=%d", xfd->offset);
45909 +               DWC_DEBUG("xfd->status=%d", xfd->status);
45910 +       }
45911 +}
45912 +
45913 +/**
45914 + *
45915 + */
45916 +int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
45917 +                             uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
45918 +                             int zero, void *req_handle, int atomic_alloc,
45919 +                             void *ereq_nonport)
45920 +{
45921 +       dwc_otg_pcd_request_t *req = NULL;
45922 +       dwc_otg_pcd_ep_t *ep;
45923 +       dwc_irqflags_t flags;
45924 +       int res;
45925 +
45926 +       ep = get_ep_from_handle(pcd, ep_handle);
45927 +       if (!ep) {
45928 +               DWC_WARN("bad ep\n");
45929 +               return -DWC_E_INVALID;
45930 +       }
45931 +
45932 +       /* We support this extension only for DDMA mode */
45933 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
45934 +               if (!GET_CORE_IF(pcd)->dma_desc_enable)
45935 +                       return -DWC_E_INVALID;
45936 +
45937 +       /* Create a dwc_otg_pcd_request_t object */
45938 +       if (atomic_alloc) {
45939 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
45940 +       } else {
45941 +               req = DWC_ALLOC(sizeof(*req));
45942 +       }
45943 +
45944 +       if (!req) {
45945 +               return -DWC_E_NO_MEMORY;
45946 +       }
45947 +
45948 +       /* Create the Isoc descs for this request which shall be the exact match
45949 +        * of the structure sent to us from the non-portable logic */
45950 +       res =
45951 +           dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
45952 +       if (res) {
45953 +               DWC_WARN("Failed to init the Isoc descriptors");
45954 +               DWC_FREE(req);
45955 +               return res;
45956 +       }
45957 +
45958 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45959 +
45960 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
45961 +       req->buf = buf;
45962 +       req->dma = dma_buf;
45963 +       req->length = buflen;
45964 +       req->sent_zlp = zero;
45965 +       req->priv = req_handle;
45966 +
45967 +       //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45968 +       ep->dwc_ep.dma_addr = dma_buf;
45969 +       ep->dwc_ep.start_xfer_buff = buf;
45970 +       ep->dwc_ep.xfer_buff = buf;
45971 +       ep->dwc_ep.xfer_len = 0;
45972 +       ep->dwc_ep.xfer_count = 0;
45973 +       ep->dwc_ep.sent_zlp = 0;
45974 +       ep->dwc_ep.total_len = buflen;
45975 +
45976 +       /* Add this request to the tail */
45977 +       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
45978 +       ep->dwc_ep.xiso_queued_xfers++;
45979 +
45980 +//DWC_DEBUG("CP_0");
45981 +//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
45982 +//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
45983 +//prn_ext_request(&req->ext_req);
45984 +
45985 +       //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45986 +
45987 +       /* If the req->status == ASAP  then check if there is any active transfer
45988 +        * for this endpoint. If no active transfers, then get the first entry
45989 +        * from the queue and start that transfer
45990 +        */
45991 +       if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
45992 +               res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
45993 +               if (res) {
45994 +                       DWC_WARN("Failed to start the next Isoc transfer");
45995 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45996 +                       DWC_FREE(req);
45997 +                       return res;
45998 +               }
45999 +       }
46000 +
46001 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46002 +       return 0;
46003 +}
46004 +
46005 +#endif
46006 +/* END ifdef DWC_UTE_PER_IO ***************************************************/
46007 +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46008 +                        uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
46009 +                        int zero, void *req_handle, int atomic_alloc)
46010 +{
46011 +       dwc_irqflags_t flags;
46012 +       dwc_otg_pcd_request_t *req;
46013 +       dwc_otg_pcd_ep_t *ep;
46014 +       uint32_t max_transfer;
46015 +
46016 +       ep = get_ep_from_handle(pcd, ep_handle);
46017 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46018 +               DWC_WARN("bad ep\n");
46019 +               return -DWC_E_INVALID;
46020 +       }
46021 +
46022 +       if (atomic_alloc) {
46023 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
46024 +       } else {
46025 +               req = DWC_ALLOC(sizeof(*req));
46026 +       }
46027 +
46028 +       if (!req) {
46029 +               return -DWC_E_NO_MEMORY;
46030 +       }
46031 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
46032 +       if (!GET_CORE_IF(pcd)->core_params->opt) {
46033 +               if (ep->dwc_ep.num != 0) {
46034 +                       DWC_ERROR("queue req %p, len %d buf %p\n",
46035 +                                 req_handle, buflen, buf);
46036 +               }
46037 +       }
46038 +
46039 +       req->buf = buf;
46040 +       req->dma = dma_buf;
46041 +       req->length = buflen;
46042 +       req->sent_zlp = zero;
46043 +       req->priv = req_handle;
46044 +       req->dw_align_buf = NULL;
46045 +       if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
46046 +                       && !GET_CORE_IF(pcd)->dma_desc_enable)
46047 +               req->dw_align_buf = DWC_DMA_ALLOC(buflen,
46048 +                                &req->dw_align_buf_dma);
46049 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46050 +
46051 +       /*
46052 +        * After adding request to the queue for IN ISOC wait for In Token Received
46053 +        * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token
46054 +        * Received when EP is disabled interrupt to obtain starting microframe
46055 +        * (odd/even) start transfer
46056 +        */
46057 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
46058 +               if (req != 0) {
46059 +                       depctl_data_t depctl = {.d32 =
46060 +                                   DWC_READ_REG32(&pcd->core_if->dev_if->
46061 +                                                  in_ep_regs[ep->dwc_ep.num]->
46062 +                                                  diepctl) };
46063 +                       ++pcd->request_pending;
46064 +
46065 +                       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46066 +                       if (ep->dwc_ep.is_in) {
46067 +                               depctl.b.cnak = 1;
46068 +                               DWC_WRITE_REG32(&pcd->core_if->dev_if->
46069 +                                               in_ep_regs[ep->dwc_ep.num]->
46070 +                                               diepctl, depctl.d32);
46071 +                       }
46072 +
46073 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46074 +               }
46075 +               return 0;
46076 +       }
46077 +
46078 +       /*
46079 +        * For EP0 IN without premature status, zlp is required?
46080 +        */
46081 +       if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
46082 +               DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
46083 +               //_req->zero = 1;
46084 +       }
46085 +
46086 +       /* Start the transfer */
46087 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
46088 +               /* EP0 Transfer? */
46089 +               if (ep->dwc_ep.num == 0) {
46090 +                       switch (pcd->ep0state) {
46091 +                       case EP0_IN_DATA_PHASE:
46092 +                               DWC_DEBUGPL(DBG_PCD,
46093 +                                           "%s ep0: EP0_IN_DATA_PHASE\n",
46094 +                                           __func__);
46095 +                               break;
46096 +
46097 +                       case EP0_OUT_DATA_PHASE:
46098 +                               DWC_DEBUGPL(DBG_PCD,
46099 +                                           "%s ep0: EP0_OUT_DATA_PHASE\n",
46100 +                                           __func__);
46101 +                               if (pcd->request_config) {
46102 +                                       /* Complete STATUS PHASE */
46103 +                                       ep->dwc_ep.is_in = 1;
46104 +                                       pcd->ep0state = EP0_IN_STATUS_PHASE;
46105 +                               }
46106 +                               break;
46107 +
46108 +                       case EP0_IN_STATUS_PHASE:
46109 +                               DWC_DEBUGPL(DBG_PCD,
46110 +                                           "%s ep0: EP0_IN_STATUS_PHASE\n",
46111 +                                           __func__);
46112 +                               break;
46113 +
46114 +                       default:
46115 +                               DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
46116 +                                           pcd->ep0state);
46117 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46118 +                               return -DWC_E_SHUTDOWN;
46119 +                       }
46120 +
46121 +                       ep->dwc_ep.dma_addr = dma_buf;
46122 +                       ep->dwc_ep.start_xfer_buff = buf;
46123 +                       ep->dwc_ep.xfer_buff = buf;
46124 +                       ep->dwc_ep.xfer_len = buflen;
46125 +                       ep->dwc_ep.xfer_count = 0;
46126 +                       ep->dwc_ep.sent_zlp = 0;
46127 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
46128 +
46129 +                       if (zero) {
46130 +                               if ((ep->dwc_ep.xfer_len %
46131 +                                    ep->dwc_ep.maxpacket == 0)
46132 +                                   && (ep->dwc_ep.xfer_len != 0)) {
46133 +                                       ep->dwc_ep.sent_zlp = 1;
46134 +                               }
46135 +
46136 +                       }
46137 +
46138 +                       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
46139 +                                                  &ep->dwc_ep);
46140 +               }               // non-ep0 endpoints
46141 +               else {
46142 +#ifdef DWC_UTE_CFI
46143 +                       if (ep->dwc_ep.buff_mode != BM_STANDARD) {
46144 +                               /* store the request length */
46145 +                               ep->dwc_ep.cfi_req_len = buflen;
46146 +                               pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
46147 +                                                               ep, req);
46148 +                       } else {
46149 +#endif
46150 +                               max_transfer =
46151 +                                   GET_CORE_IF(ep->pcd)->core_params->
46152 +                                   max_transfer_size;
46153 +
46154 +                               /* Setup and start the Transfer */
46155 +                               if (req->dw_align_buf){
46156 +                                       if (ep->dwc_ep.is_in)
46157 +                                               dwc_memcpy(req->dw_align_buf,
46158 +                                                          buf, buflen);
46159 +                                       ep->dwc_ep.dma_addr =
46160 +                                           req->dw_align_buf_dma;
46161 +                                       ep->dwc_ep.start_xfer_buff =
46162 +                                           req->dw_align_buf;
46163 +                                       ep->dwc_ep.xfer_buff =
46164 +                                           req->dw_align_buf;
46165 +                               } else {
46166 +                                       ep->dwc_ep.dma_addr = dma_buf;
46167 +                                       ep->dwc_ep.start_xfer_buff = buf;
46168 +                                        ep->dwc_ep.xfer_buff = buf;
46169 +                               }
46170 +                               ep->dwc_ep.xfer_len = 0;
46171 +                               ep->dwc_ep.xfer_count = 0;
46172 +                               ep->dwc_ep.sent_zlp = 0;
46173 +                               ep->dwc_ep.total_len = buflen;
46174 +
46175 +                               ep->dwc_ep.maxxfer = max_transfer;
46176 +                               if (GET_CORE_IF(pcd)->dma_desc_enable) {
46177 +                                       uint32_t out_max_xfer =
46178 +                                           DDMA_MAX_TRANSFER_SIZE -
46179 +                                           (DDMA_MAX_TRANSFER_SIZE % 4);
46180 +                                       if (ep->dwc_ep.is_in) {
46181 +                                               if (ep->dwc_ep.maxxfer >
46182 +                                                   DDMA_MAX_TRANSFER_SIZE) {
46183 +                                                       ep->dwc_ep.maxxfer =
46184 +                                                           DDMA_MAX_TRANSFER_SIZE;
46185 +                                               }
46186 +                                       } else {
46187 +                                               if (ep->dwc_ep.maxxfer >
46188 +                                                   out_max_xfer) {
46189 +                                                       ep->dwc_ep.maxxfer =
46190 +                                                           out_max_xfer;
46191 +                                               }
46192 +                                       }
46193 +                               }
46194 +                               if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
46195 +                                       ep->dwc_ep.maxxfer -=
46196 +                                           (ep->dwc_ep.maxxfer %
46197 +                                            ep->dwc_ep.maxpacket);
46198 +                               }
46199 +
46200 +                               if (zero) {
46201 +                                       if ((ep->dwc_ep.total_len %
46202 +                                            ep->dwc_ep.maxpacket == 0)
46203 +                                           && (ep->dwc_ep.total_len != 0)) {
46204 +                                               ep->dwc_ep.sent_zlp = 1;
46205 +                                       }
46206 +                               }
46207 +#ifdef DWC_UTE_CFI
46208 +                       }
46209 +#endif
46210 +                       dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
46211 +                                                 &ep->dwc_ep);
46212 +               }
46213 +       }
46214 +
46215 +       if (req != 0) {
46216 +               ++pcd->request_pending;
46217 +               DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46218 +               if (ep->dwc_ep.is_in && ep->stopped
46219 +                   && !(GET_CORE_IF(pcd)->dma_enable)) {
46220 +                       /** @todo NGS Create a function for this. */
46221 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
46222 +                       diepmsk.b.intktxfemp = 1;
46223 +                       if (GET_CORE_IF(pcd)->multiproc_int_enable) {
46224 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46225 +                                                dev_if->dev_global_regs->diepeachintmsk
46226 +                                                [ep->dwc_ep.num], 0,
46227 +                                                diepmsk.d32);
46228 +                       } else {
46229 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46230 +                                                dev_if->dev_global_regs->
46231 +                                                diepmsk, 0, diepmsk.d32);
46232 +                       }
46233 +
46234 +               }
46235 +       }
46236 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46237 +
46238 +       return 0;
46239 +}
46240 +
46241 +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
46242 +                          void *req_handle)
46243 +{
46244 +       dwc_irqflags_t flags;
46245 +       dwc_otg_pcd_request_t *req;
46246 +       dwc_otg_pcd_ep_t *ep;
46247 +
46248 +       ep = get_ep_from_handle(pcd, ep_handle);
46249 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46250 +               DWC_WARN("bad argument\n");
46251 +               return -DWC_E_INVALID;
46252 +       }
46253 +
46254 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46255 +
46256 +       /* make sure it's actually queued on this endpoint */
46257 +       DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
46258 +               if (req->priv == (void *)req_handle) {
46259 +                       break;
46260 +               }
46261 +       }
46262 +
46263 +       if (req->priv != (void *)req_handle) {
46264 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46265 +               return -DWC_E_INVALID;
46266 +       }
46267 +
46268 +       if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
46269 +               dwc_otg_request_done(ep, req, -DWC_E_RESTART);
46270 +       } else {
46271 +               req = NULL;
46272 +       }
46273 +
46274 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46275 +
46276 +       return req ? 0 : -DWC_E_SHUTDOWN;
46277 +
46278 +}
46279 +
46280 +/**
46281 + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
46282 + *
46283 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
46284 + * requests. If the gadget driver clears the halt status, it will
46285 + * automatically unwedge the endpoint.
46286 + *
46287 + * Returns zero on success, else negative DWC error code.
46288 + */
46289 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
46290 +{
46291 +       dwc_otg_pcd_ep_t *ep;
46292 +       dwc_irqflags_t flags;
46293 +       int retval = 0;
46294 +
46295 +       ep = get_ep_from_handle(pcd, ep_handle);
46296 +
46297 +       if ((!ep->desc && ep != &pcd->ep0) ||
46298 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46299 +               DWC_WARN("%s, bad ep\n", __func__);
46300 +               return -DWC_E_INVALID;
46301 +       }
46302 +
46303 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46304 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46305 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46306 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46307 +               retval = -DWC_E_AGAIN;
46308 +       } else {
46309 +                /* This code needs to be reviewed */
46310 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46311 +                       dtxfsts_data_t txstatus;
46312 +                       fifosize_data_t txfifosize;
46313 +
46314 +                       txfifosize.d32 =
46315 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46316 +                                          core_global_regs->dtxfsiz[ep->dwc_ep.
46317 +                                                                    tx_fifo_num]);
46318 +                       txstatus.d32 =
46319 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46320 +                                          dev_if->in_ep_regs[ep->dwc_ep.num]->
46321 +                                          dtxfsts);
46322 +
46323 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46324 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46325 +                               retval = -DWC_E_AGAIN;
46326 +                       } else {
46327 +                               if (ep->dwc_ep.num == 0) {
46328 +                                       pcd->ep0state = EP0_STALL;
46329 +                               }
46330 +
46331 +                               ep->stopped = 1;
46332 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46333 +                                                    &ep->dwc_ep);
46334 +                       }
46335 +               } else {
46336 +                       if (ep->dwc_ep.num == 0) {
46337 +                               pcd->ep0state = EP0_STALL;
46338 +                       }
46339 +
46340 +                       ep->stopped = 1;
46341 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46342 +               }
46343 +       }
46344 +
46345 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46346 +
46347 +       return retval;
46348 +}
46349 +
46350 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
46351 +{
46352 +       dwc_otg_pcd_ep_t *ep;
46353 +       dwc_irqflags_t flags;
46354 +       int retval = 0;
46355 +
46356 +       ep = get_ep_from_handle(pcd, ep_handle);
46357 +
46358 +       if (!ep || (!ep->desc && ep != &pcd->ep0) ||
46359 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46360 +               DWC_WARN("%s, bad ep\n", __func__);
46361 +               return -DWC_E_INVALID;
46362 +       }
46363 +
46364 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46365 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46366 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46367 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46368 +               retval = -DWC_E_AGAIN;
46369 +       } else if (value == 0) {
46370 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46371 +       } else if (value == 1) {
46372 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46373 +                       dtxfsts_data_t txstatus;
46374 +                       fifosize_data_t txfifosize;
46375 +
46376 +                       txfifosize.d32 =
46377 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
46378 +                                          dtxfsiz[ep->dwc_ep.tx_fifo_num]);
46379 +                       txstatus.d32 =
46380 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
46381 +                                          in_ep_regs[ep->dwc_ep.num]->dtxfsts);
46382 +
46383 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46384 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46385 +                               retval = -DWC_E_AGAIN;
46386 +                       } else {
46387 +                               if (ep->dwc_ep.num == 0) {
46388 +                                       pcd->ep0state = EP0_STALL;
46389 +                               }
46390 +
46391 +                               ep->stopped = 1;
46392 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46393 +                                                    &ep->dwc_ep);
46394 +                       }
46395 +               } else {
46396 +                       if (ep->dwc_ep.num == 0) {
46397 +                               pcd->ep0state = EP0_STALL;
46398 +                       }
46399 +
46400 +                       ep->stopped = 1;
46401 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46402 +               }
46403 +       } else if (value == 2) {
46404 +               ep->dwc_ep.stall_clear_flag = 0;
46405 +       } else if (value == 3) {
46406 +               ep->dwc_ep.stall_clear_flag = 1;
46407 +       }
46408 +
46409 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46410 +
46411 +       return retval;
46412 +}
46413 +
46414 +/**
46415 + * This function initiates remote wakeup of the host from suspend state.
46416 + */
46417 +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
46418 +{
46419 +       dctl_data_t dctl = { 0 };
46420 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46421 +       dsts_data_t dsts;
46422 +
46423 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
46424 +       if (!dsts.b.suspsts) {
46425 +               DWC_WARN("Remote wakeup while is not in suspend state\n");
46426 +       }
46427 +       /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
46428 +       if (pcd->remote_wakeup_enable) {
46429 +               if (set) {
46430 +
46431 +                       if (core_if->adp_enable) {
46432 +                               gpwrdn_data_t gpwrdn;
46433 +
46434 +                               dwc_otg_adp_probe_stop(core_if);
46435 +
46436 +                               /* Mask SRP detected interrupt from Power Down Logic */
46437 +                               gpwrdn.d32 = 0;
46438 +                               gpwrdn.b.srp_det_msk = 1;
46439 +                               DWC_MODIFY_REG32(&core_if->
46440 +                                                core_global_regs->gpwrdn,
46441 +                                                gpwrdn.d32, 0);
46442 +
46443 +                               /* Disable Power Down Logic */
46444 +                               gpwrdn.d32 = 0;
46445 +                               gpwrdn.b.pmuactv = 1;
46446 +                               DWC_MODIFY_REG32(&core_if->
46447 +                                                core_global_regs->gpwrdn,
46448 +                                                gpwrdn.d32, 0);
46449 +
46450 +                               /*
46451 +                                * Initialize the Core for Device mode.
46452 +                                */
46453 +                               core_if->op_state = B_PERIPHERAL;
46454 +                               dwc_otg_core_init(core_if);
46455 +                               dwc_otg_enable_global_interrupts(core_if);
46456 +                               cil_pcd_start(core_if);
46457 +
46458 +                               dwc_otg_initiate_srp(core_if);
46459 +                       }
46460 +
46461 +                       dctl.b.rmtwkupsig = 1;
46462 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46463 +                                        dctl, 0, dctl.d32);
46464 +                       DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46465 +
46466 +                       dwc_mdelay(2);
46467 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46468 +                                        dctl, dctl.d32, 0);
46469 +                       DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
46470 +               }
46471 +       } else {
46472 +               DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
46473 +       }
46474 +}
46475 +
46476 +#ifdef CONFIG_USB_DWC_OTG_LPM
46477 +/**
46478 + * This function initiates remote wakeup of the host from L1 sleep state.
46479 + */
46480 +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
46481 +{
46482 +       glpmcfg_data_t lpmcfg;
46483 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46484 +
46485 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46486 +
46487 +       /* Check if we are in L1 state */
46488 +       if (!lpmcfg.b.prt_sleep_sts) {
46489 +               DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
46490 +               return;
46491 +       }
46492 +
46493 +       /* Check if host allows remote wakeup */
46494 +       if (!lpmcfg.b.rem_wkup_en) {
46495 +               DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
46496 +               return;
46497 +       }
46498 +
46499 +       /* Check if Resume OK */
46500 +       if (!lpmcfg.b.sleep_state_resumeok) {
46501 +               DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
46502 +               return;
46503 +       }
46504 +
46505 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46506 +       lpmcfg.b.en_utmi_sleep = 0;
46507 +       lpmcfg.b.hird_thres &= (~(1 << 4));
46508 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
46509 +
46510 +       if (set) {
46511 +               dctl_data_t dctl = {.d32 = 0 };
46512 +               dctl.b.rmtwkupsig = 1;
46513 +               /* Set RmtWkUpSig bit to start remote wakup signaling.
46514 +                * Hardware will automatically clear this bit.
46515 +                */
46516 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
46517 +                                0, dctl.d32);
46518 +               DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46519 +       }
46520 +
46521 +}
46522 +#endif
46523 +
46524 +/**
46525 + * Performs remote wakeup.
46526 + */
46527 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
46528 +{
46529 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46530 +       dwc_irqflags_t flags;
46531 +       if (dwc_otg_is_device_mode(core_if)) {
46532 +               DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46533 +#ifdef CONFIG_USB_DWC_OTG_LPM
46534 +               if (core_if->lx_state == DWC_OTG_L1) {
46535 +                       dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
46536 +               } else {
46537 +#endif
46538 +                       dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
46539 +#ifdef CONFIG_USB_DWC_OTG_LPM
46540 +               }
46541 +#endif
46542 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46543 +       }
46544 +       return;
46545 +}
46546 +
46547 +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
46548 +{
46549 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46550 +       dctl_data_t dctl = { 0 };
46551 +
46552 +       if (dwc_otg_is_device_mode(core_if)) {
46553 +               dctl.b.sftdiscon = 1;
46554 +               DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
46555 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
46556 +               dwc_udelay(no_of_usecs);
46557 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
46558 +
46559 +       } else{
46560 +               DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
46561 +       }
46562 +       return;
46563 +
46564 +}
46565 +
46566 +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
46567 +{
46568 +       dsts_data_t dsts;
46569 +       gotgctl_data_t gotgctl;
46570 +
46571 +       /*
46572 +        * This function starts the Protocol if no session is in progress. If
46573 +        * a session is already in progress, but the device is suspended,
46574 +        * remote wakeup signaling is started.
46575 +        */
46576 +
46577 +       /* Check if valid session */
46578 +       gotgctl.d32 =
46579 +           DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
46580 +       if (gotgctl.b.bsesvld) {
46581 +               /* Check if suspend state */
46582 +               dsts.d32 =
46583 +                   DWC_READ_REG32(&
46584 +                                  (GET_CORE_IF(pcd)->dev_if->
46585 +                                   dev_global_regs->dsts));
46586 +               if (dsts.b.suspsts) {
46587 +                       dwc_otg_pcd_remote_wakeup(pcd, 1);
46588 +               }
46589 +       } else {
46590 +               dwc_otg_pcd_initiate_srp(pcd);
46591 +       }
46592 +
46593 +       return 0;
46594 +
46595 +}
46596 +
46597 +/**
46598 + * Start the SRP timer to detect when the SRP does not complete within
46599 + * 6 seconds.
46600 + *
46601 + * @param pcd the pcd structure.
46602 + */
46603 +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
46604 +{
46605 +       dwc_irqflags_t flags;
46606 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46607 +       dwc_otg_initiate_srp(GET_CORE_IF(pcd));
46608 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46609 +}
46610 +
46611 +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
46612 +{
46613 +       return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
46614 +}
46615 +
46616 +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
46617 +{
46618 +       return GET_CORE_IF(pcd)->core_params->lpm_enable;
46619 +}
46620 +
46621 +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
46622 +{
46623 +       return pcd->b_hnp_enable;
46624 +}
46625 +
46626 +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
46627 +{
46628 +       return pcd->a_hnp_support;
46629 +}
46630 +
46631 +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
46632 +{
46633 +       return pcd->a_alt_hnp_support;
46634 +}
46635 +
46636 +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
46637 +{
46638 +       return pcd->remote_wakeup_enable;
46639 +}
46640 +
46641 +#endif /* DWC_HOST_ONLY */
46642 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46643 new file mode 100644
46644 index 0000000..8ef7ba6
46645 --- /dev/null
46646 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46647 @@ -0,0 +1,266 @@
46648 +/* ==========================================================================
46649 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
46650 + * $Revision: #48 $
46651 + * $Date: 2012/08/10 $
46652 + * $Change: 2047372 $
46653 + *
46654 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46655 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46656 + * otherwise expressly agreed to in writing between Synopsys and you.
46657 + *
46658 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46659 + * any End User Software License Agreement or Agreement for Licensed Product
46660 + * with Synopsys or any supplement thereto. You are permitted to use and
46661 + * redistribute this Software in source and binary forms, with or without
46662 + * modification, provided that redistributions of source code must retain this
46663 + * notice. You may not view, use, disclose, copy or distribute this file or
46664 + * any information contained herein except pursuant to this license grant from
46665 + * Synopsys. If you do not agree with this notice, including the disclaimer
46666 + * below, then you are not authorized to use the Software.
46667 + *
46668 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46669 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46670 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46671 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46672 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46673 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46674 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46675 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46676 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46677 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46678 + * DAMAGE.
46679 + * ========================================================================== */
46680 +#ifndef DWC_HOST_ONLY
46681 +#if !defined(__DWC_PCD_H__)
46682 +#define __DWC_PCD_H__
46683 +
46684 +#include "dwc_otg_os_dep.h"
46685 +#include "usb.h"
46686 +#include "dwc_otg_cil.h"
46687 +#include "dwc_otg_pcd_if.h"
46688 +struct cfiobject;
46689 +
46690 +/**
46691 + * @file
46692 + *
46693 + * This file contains the structures, constants, and interfaces for
46694 + * the Perpherial Contoller Driver (PCD).
46695 + *
46696 + * The Peripheral Controller Driver (PCD) for Linux will implement the
46697 + * Gadget API, so that the existing Gadget drivers can be used. For
46698 + * the Mass Storage Function driver the File-backed USB Storage Gadget
46699 + * (FBS) driver will be used.  The FBS driver supports the
46700 + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
46701 + * transports.
46702 + *
46703 + */
46704 +
46705 +/** Invalid DMA Address */
46706 +#define DWC_DMA_ADDR_INVALID   (~(dwc_dma_t)0)
46707 +
46708 +/** Max Transfer size for any EP */
46709 +#define DDMA_MAX_TRANSFER_SIZE 65535
46710 +
46711 +/**
46712 + * Get the pointer to the core_if from the pcd pointer.
46713 + */
46714 +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
46715 +
46716 +/**
46717 + * States of EP0.
46718 + */
46719 +typedef enum ep0_state {
46720 +       EP0_DISCONNECT,         /* no host */
46721 +       EP0_IDLE,
46722 +       EP0_IN_DATA_PHASE,
46723 +       EP0_OUT_DATA_PHASE,
46724 +       EP0_IN_STATUS_PHASE,
46725 +       EP0_OUT_STATUS_PHASE,
46726 +       EP0_STALL,
46727 +} ep0state_e;
46728 +
46729 +/** Fordward declaration.*/
46730 +struct dwc_otg_pcd;
46731 +
46732 +/** DWC_otg iso request structure.
46733 + *
46734 + */
46735 +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
46736 +
46737 +#ifdef DWC_UTE_PER_IO
46738 +
46739 +/**
46740 + * This shall be the exact analogy of the same type structure defined in the
46741 + * usb_gadget.h. Each descriptor contains
46742 + */
46743 +struct dwc_iso_pkt_desc_port {
46744 +       uint32_t offset;
46745 +       uint32_t length;        /* expected length */
46746 +       uint32_t actual_length;
46747 +       uint32_t status;
46748 +};
46749 +
46750 +struct dwc_iso_xreq_port {
46751 +       /** transfer/submission flag */
46752 +       uint32_t tr_sub_flags;
46753 +       /** Start the request ASAP */
46754 +#define DWC_EREQ_TF_ASAP               0x00000002
46755 +       /** Just enqueue the request w/o initiating a transfer */
46756 +#define DWC_EREQ_TF_ENQUEUE            0x00000004
46757 +
46758 +       /**
46759 +       * count of ISO packets attached to this request - shall
46760 +       * not exceed the pio_alloc_pkt_count
46761 +       */
46762 +       uint32_t pio_pkt_count;
46763 +       /** count of ISO packets allocated for this request */
46764 +       uint32_t pio_alloc_pkt_count;
46765 +       /** number of ISO packet errors */
46766 +       uint32_t error_count;
46767 +       /** reserved for future extension */
46768 +       uint32_t res;
46769 +       /** Will be allocated and freed in the UTE gadget and based on the CFC value */
46770 +       struct dwc_iso_pkt_desc_port *per_io_frame_descs;
46771 +};
46772 +#endif
46773 +/** DWC_otg request structure.
46774 + * This structure is a list of requests.
46775 + */
46776 +typedef struct dwc_otg_pcd_request {
46777 +       void *priv;
46778 +       void *buf;
46779 +       dwc_dma_t dma;
46780 +       uint32_t length;
46781 +       uint32_t actual;
46782 +       unsigned sent_zlp:1;
46783 +    /**
46784 +     * Used instead of original buffer if
46785 +     * it(physical address) is not dword-aligned.
46786 +     **/
46787 +     uint8_t *dw_align_buf;
46788 +     dwc_dma_t dw_align_buf_dma;
46789 +
46790 +        DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
46791 +#ifdef DWC_UTE_PER_IO
46792 +       struct dwc_iso_xreq_port ext_req;
46793 +       //void *priv_ereq_nport; /*  */
46794 +#endif
46795 +} dwc_otg_pcd_request_t;
46796 +
46797 +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
46798 +
46799 +/**      PCD EP structure.
46800 + * This structure describes an EP, there is an array of EPs in the PCD
46801 + * structure.
46802 + */
46803 +typedef struct dwc_otg_pcd_ep {
46804 +       /** USB EP Descriptor */
46805 +       const usb_endpoint_descriptor_t *desc;
46806 +
46807 +       /** queue of dwc_otg_pcd_requests. */
46808 +       struct req_list queue;
46809 +       unsigned stopped:1;
46810 +       unsigned disabling:1;
46811 +       unsigned dma:1;
46812 +       unsigned queue_sof:1;
46813 +
46814 +#ifdef DWC_EN_ISOC
46815 +       /** ISOC req handle passed */
46816 +       void *iso_req_handle;
46817 +#endif                         //_EN_ISOC_
46818 +
46819 +       /** DWC_otg ep data. */
46820 +       dwc_ep_t dwc_ep;
46821 +
46822 +       /** Pointer to PCD */
46823 +       struct dwc_otg_pcd *pcd;
46824 +
46825 +       void *priv;
46826 +} dwc_otg_pcd_ep_t;
46827 +
46828 +/** DWC_otg PCD Structure.
46829 + * This structure encapsulates the data for the dwc_otg PCD.
46830 + */
46831 +struct dwc_otg_pcd {
46832 +       const struct dwc_otg_pcd_function_ops *fops;
46833 +       /** The DWC otg device pointer */
46834 +       struct dwc_otg_device *otg_dev;
46835 +       /** Core Interface */
46836 +       dwc_otg_core_if_t *core_if;
46837 +       /** State of EP0 */
46838 +       ep0state_e ep0state;
46839 +       /** EP0 Request is pending */
46840 +       unsigned ep0_pending:1;
46841 +       /** Indicates when SET CONFIGURATION Request is in process */
46842 +       unsigned request_config:1;
46843 +       /** The state of the Remote Wakeup Enable. */
46844 +       unsigned remote_wakeup_enable:1;
46845 +       /** The state of the B-Device HNP Enable. */
46846 +       unsigned b_hnp_enable:1;
46847 +       /** The state of A-Device HNP Support. */
46848 +       unsigned a_hnp_support:1;
46849 +       /** The state of the A-Device Alt HNP support. */
46850 +       unsigned a_alt_hnp_support:1;
46851 +       /** Count of pending Requests */
46852 +       unsigned request_pending;
46853 +
46854 +       /** SETUP packet for EP0
46855 +        * This structure is allocated as a DMA buffer on PCD initialization
46856 +        * with enough space for up to 3 setup packets.
46857 +        */
46858 +       union {
46859 +               usb_device_request_t req;
46860 +               uint32_t d32[2];
46861 +       } *setup_pkt;
46862 +
46863 +       dwc_dma_t setup_pkt_dma_handle;
46864 +
46865 +       /* Additional buffer and flag for CTRL_WR premature case */
46866 +       uint8_t *backup_buf;
46867 +       unsigned data_terminated;
46868 +
46869 +       /** 2-byte dma buffer used to return status from GET_STATUS */
46870 +       uint16_t *status_buf;
46871 +       dwc_dma_t status_buf_dma_handle;
46872 +
46873 +       /** EP0 */
46874 +       dwc_otg_pcd_ep_t ep0;
46875 +
46876 +       /** Array of IN EPs. */
46877 +       dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
46878 +       /** Array of OUT EPs. */
46879 +       dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
46880 +       /** number of valid EPs in the above array. */
46881 +//        unsigned      num_eps : 4;
46882 +       dwc_spinlock_t *lock;
46883 +
46884 +       /** Tasklet to defer starting of TEST mode transmissions until
46885 +        *      Status Phase has been completed.
46886 +        */
46887 +       dwc_tasklet_t *test_mode_tasklet;
46888 +
46889 +       /** Tasklet to delay starting of xfer in DMA mode */
46890 +       dwc_tasklet_t *start_xfer_tasklet;
46891 +
46892 +       /** The test mode to enter when the tasklet is executed. */
46893 +       unsigned test_mode;
46894 +       /** The cfi_api structure that implements most of the CFI API
46895 +        * and OTG specific core configuration functionality
46896 +        */
46897 +#ifdef DWC_UTE_CFI
46898 +       struct cfiobject *cfi;
46899 +#endif
46900 +
46901 +};
46902 +
46903 +//FIXME this functions should be static, and this prototypes should be removed
46904 +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
46905 +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
46906 +                                dwc_otg_pcd_request_t * req, int32_t status);
46907 +
46908 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
46909 +                            void *req_handle);
46910 +
46911 +extern void do_test_mode(void *data);
46912 +#endif
46913 +#endif /* DWC_HOST_ONLY */
46914 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
46915 new file mode 100644
46916 index 0000000..c8d2e0e
46917 --- /dev/null
46918 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
46919 @@ -0,0 +1,360 @@
46920 +/* ==========================================================================
46921 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
46922 + * $Revision: #11 $
46923 + * $Date: 2011/10/26 $
46924 + * $Change: 1873028 $
46925 + *
46926 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46927 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46928 + * otherwise expressly agreed to in writing between Synopsys and you.
46929 + *
46930 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46931 + * any End User Software License Agreement or Agreement for Licensed Product
46932 + * with Synopsys or any supplement thereto. You are permitted to use and
46933 + * redistribute this Software in source and binary forms, with or without
46934 + * modification, provided that redistributions of source code must retain this
46935 + * notice. You may not view, use, disclose, copy or distribute this file or
46936 + * any information contained herein except pursuant to this license grant from
46937 + * Synopsys. If you do not agree with this notice, including the disclaimer
46938 + * below, then you are not authorized to use the Software.
46939 + *
46940 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46941 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46942 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46943 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46944 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46945 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46946 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46947 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46948 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46949 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46950 + * DAMAGE.
46951 + * ========================================================================== */
46952 +#ifndef DWC_HOST_ONLY
46953 +
46954 +#if !defined(__DWC_PCD_IF_H__)
46955 +#define __DWC_PCD_IF_H__
46956 +
46957 +//#include "dwc_os.h"
46958 +#include "dwc_otg_core_if.h"
46959 +
46960 +/** @file
46961 + * This file defines DWC_OTG PCD Core API.
46962 + */
46963 +
46964 +struct dwc_otg_pcd;
46965 +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
46966 +
46967 +/** Maxpacket size for EP0 */
46968 +#define MAX_EP0_SIZE   64
46969 +/** Maxpacket size for any EP */
46970 +#define MAX_PACKET_SIZE 1024
46971 +
46972 +/** @name Function Driver Callbacks */
46973 +/** @{ */
46974 +
46975 +/** This function will be called whenever a previously queued request has
46976 + * completed.  The status value will be set to -DWC_E_SHUTDOWN to indicated a
46977 + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
46978 + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
46979 + * parameters. */
46980 +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46981 +                                   void *req_handle, int32_t status,
46982 +                                   uint32_t actual);
46983 +/**
46984 + * This function will be called whenever a previousle queued ISOC request has
46985 + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
46986 + * function.
46987 + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
46988 + * functions.
46989 + */
46990 +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46991 +                                        void *req_handle, int proc_buf_num);
46992 +/** This function should handle any SETUP request that cannot be handled by the
46993 + * PCD Core.  This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
46994 + * class-specific requests, etc.  The function must non-blocking.
46995 + *
46996 + * Returns 0 on success.
46997 + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
46998 + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
46999 + * Returns -DWC_E_SHUTDOWN on any other error. */
47000 +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
47001 +/** This is called whenever the device has been disconnected.  The function
47002 + * driver should take appropriate action to clean up all pending requests in the
47003 + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
47004 + * state. */
47005 +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
47006 +/** This function is called when device has been connected. */
47007 +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
47008 +/** This function is called when device has been suspended */
47009 +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
47010 +/** This function is called when device has received LPM tokens, i.e.
47011 + * device has been sent to sleep state. */
47012 +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
47013 +/** This function is called when device has been resumed
47014 + * from suspend(L2) or L1 sleep state. */
47015 +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
47016 +/** This function is called whenever hnp params has been changed.
47017 + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
47018 + * to get hnp parameters. */
47019 +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
47020 +/** This function is called whenever USB RESET is detected. */
47021 +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
47022 +
47023 +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
47024 +
47025 +/**
47026 + *
47027 + * @param ep_handle    Void pointer to the usb_ep structure
47028 + * @param ereq_port Pointer to the extended request structure created in the
47029 + *                                     portable part.
47030 + */
47031 +typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
47032 +                                    void *req_handle, int32_t status,
47033 +                                    void *ereq_port);
47034 +/** Function Driver Ops Data Structure */
47035 +struct dwc_otg_pcd_function_ops {
47036 +       dwc_connect_cb_t connect;
47037 +       dwc_disconnect_cb_t disconnect;
47038 +       dwc_setup_cb_t setup;
47039 +       dwc_completion_cb_t complete;
47040 +       dwc_isoc_completion_cb_t isoc_complete;
47041 +       dwc_suspend_cb_t suspend;
47042 +       dwc_sleep_cb_t sleep;
47043 +       dwc_resume_cb_t resume;
47044 +       dwc_reset_cb_t reset;
47045 +       dwc_hnp_params_changed_cb_t hnp_changed;
47046 +       cfi_setup_cb_t cfi_setup;
47047 +#ifdef DWC_UTE_PER_IO
47048 +       xiso_completion_cb_t xisoc_complete;
47049 +#endif
47050 +};
47051 +/** @} */
47052 +
47053 +/** @name Function Driver Functions */
47054 +/** @{ */
47055 +
47056 +/** Call this function to get pointer on dwc_otg_pcd_t,
47057 + * this pointer will be used for all PCD API functions.
47058 + *
47059 + * @param core_if The DWC_OTG Core
47060 + */
47061 +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
47062 +
47063 +/** Frees PCD allocated by dwc_otg_pcd_init
47064 + *
47065 + * @param pcd The PCD
47066 + */
47067 +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
47068 +
47069 +/** Call this to bind the function driver to the PCD Core.
47070 + *
47071 + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
47072 + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
47073 + */
47074 +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
47075 +                             const struct dwc_otg_pcd_function_ops *fops);
47076 +
47077 +/** Enables an endpoint for use.  This function enables an endpoint in
47078 + * the PCD.  The endpoint is described by the ep_desc which has the
47079 + * same format as a USB ep descriptor.  The ep_handle parameter is used to refer
47080 + * to the endpoint from other API functions and in callbacks.  Normally this
47081 + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
47082 + * core for that interface.
47083 + *
47084 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47085 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47086 + * Returns 0 on success.
47087 + *
47088 + * @param pcd The PCD
47089 + * @param ep_desc Endpoint descriptor
47090 + * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
47091 + */
47092 +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
47093 +                                const uint8_t * ep_desc, void *usb_ep);
47094 +
47095 +/** Disable the endpoint referenced by ep_handle.
47096 + *
47097 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47098 + * Returns -DWC_E_SHUTDOWN if any other error occurred.
47099 + * Returns 0 on success. */
47100 +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
47101 +
47102 +/** Queue a data transfer request on the endpoint referenced by ep_handle.
47103 + * After the transfer is completes, the complete callback will be called with
47104 + * the request status.
47105 + *
47106 + * @param pcd The PCD
47107 + * @param ep_handle The handle of the endpoint
47108 + * @param buf The buffer for the data
47109 + * @param dma_buf The DMA buffer for the data
47110 + * @param buflen The length of the data transfer
47111 + * @param zero Specifies whether to send zero length last packet.
47112 + * @param req_handle Set this handle to any value to use to reference this
47113 + * request in the ep_dequeue function or from the complete callback
47114 + * @param atomic_alloc If driver need to perform atomic allocations
47115 + * for internal data structures.
47116 + *
47117 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47118 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47119 + * Returns 0 on success. */
47120 +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
47121 +                               uint8_t * buf, dwc_dma_t dma_buf,
47122 +                               uint32_t buflen, int zero, void *req_handle,
47123 +                               int atomic_alloc);
47124 +#ifdef DWC_UTE_PER_IO
47125 +/**
47126 + *
47127 + * @param ereq_nonport Pointer to the extended request part of the
47128 + *                                             usb_request structure defined in usb_gadget.h file.
47129 + */
47130 +extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
47131 +                                    uint8_t * buf, dwc_dma_t dma_buf,
47132 +                                    uint32_t buflen, int zero,
47133 +                                    void *req_handle, int atomic_alloc,
47134 +                                    void *ereq_nonport);
47135 +
47136 +#endif
47137 +
47138 +/** De-queue the specified data transfer that has not yet completed.
47139 + *
47140 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47141 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47142 + * Returns 0 on success. */
47143 +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
47144 +                                 void *req_handle);
47145 +
47146 +/** Halt (STALL) an endpoint or clear it.
47147 + *
47148 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47149 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47150 + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
47151 + * Returns 0 on success. */
47152 +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
47153 +
47154 +/** This function */
47155 +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
47156 +
47157 +/** This function should be called on every hardware interrupt */
47158 +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
47159 +
47160 +/** This function returns current frame number */
47161 +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
47162 +
47163 +/**
47164 + * Start isochronous transfers on the endpoint referenced by ep_handle.
47165 + * For isochronous transfers duble buffering is used.
47166 + * After processing each of buffers comlete callback will be called with
47167 + * status for each transaction.
47168 + *
47169 + * @param pcd The PCD
47170 + * @param ep_handle The handle of the endpoint
47171 + * @param buf0 The virtual address of first data buffer
47172 + * @param buf1 The virtual address of second data buffer
47173 + * @param dma0 The DMA address of first data buffer
47174 + * @param dma1 The DMA address of second data buffer
47175 + * @param sync_frame Data pattern frame number
47176 + * @param dp_frame Data size for pattern frame
47177 + * @param data_per_frame Data size for regular frame
47178 + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
47179 + * @param buf_proc_intrvl Interval of ISOC Buffer processing
47180 + * @param req_handle Handle of ISOC request
47181 + * @param atomic_alloc Specefies whether to perform atomic allocation for
47182 + *                     internal data structures.
47183 + *
47184 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
47185 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
47186 + * Returns -DW_E_SHUTDOWN for any other error.
47187 + * Returns 0 on success
47188 + */
47189 +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
47190 +                                   uint8_t * buf0, uint8_t * buf1,
47191 +                                   dwc_dma_t dma0, dwc_dma_t dma1,
47192 +                                   int sync_frame, int dp_frame,
47193 +                                   int data_per_frame, int start_frame,
47194 +                                   int buf_proc_intrvl, void *req_handle,
47195 +                                   int atomic_alloc);
47196 +
47197 +/** Stop ISOC transfers on endpoint referenced by ep_handle.
47198 + *
47199 + * @param pcd The PCD
47200 + * @param ep_handle The handle of the endpoint
47201 + * @param req_handle Handle of ISOC request
47202 + *
47203 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
47204 + * Returns 0 on success
47205 + */
47206 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
47207 +                           void *req_handle);
47208 +
47209 +/** Get ISOC packet status.
47210 + *
47211 + * @param pcd The PCD
47212 + * @param ep_handle The handle of the endpoint
47213 + * @param iso_req_handle Isochronoush request handle
47214 + * @param packet Number of packet
47215 + * @param status Out parameter for returning status
47216 + * @param actual Out parameter for returning actual length
47217 + * @param offset Out parameter for returning offset
47218 + *
47219 + */
47220 +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
47221 +                                             void *ep_handle,
47222 +                                             void *iso_req_handle, int packet,
47223 +                                             int *status, int *actual,
47224 +                                             int *offset);
47225 +
47226 +/** Get ISOC packet count.
47227 + *
47228 + * @param pcd The PCD
47229 + * @param ep_handle The handle of the endpoint
47230 + * @param iso_req_handle
47231 + */
47232 +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
47233 +                                           void *ep_handle,
47234 +                                           void *iso_req_handle);
47235 +
47236 +/** This function starts the SRP Protocol if no session is in progress. If
47237 + * a session is already in progress, but the device is suspended,
47238 + * remote wakeup signaling is started.
47239 + */
47240 +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
47241 +
47242 +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
47243 +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
47244 +
47245 +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
47246 +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
47247 +
47248 +/** Initiate SRP */
47249 +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
47250 +
47251 +/** Starts remote wakeup signaling. */
47252 +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
47253 +
47254 +/** Starts micorsecond soft disconnect. */
47255 +extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);
47256 +/** This function returns whether device is dualspeed.*/
47257 +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
47258 +
47259 +/** This function returns whether device is otg. */
47260 +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
47261 +
47262 +/** These functions allow to get hnp parameters */
47263 +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
47264 +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
47265 +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
47266 +
47267 +/** CFI specific Interface functions */
47268 +/** Allocate a cfi buffer */
47269 +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
47270 +                                    dwc_dma_t * addr, size_t buflen,
47271 +                                    int flags);
47272 +
47273 +/******************************************************************************/
47274 +
47275 +/** @} */
47276 +
47277 +#endif                         /* __DWC_PCD_IF_H__ */
47278 +
47279 +#endif                         /* DWC_HOST_ONLY */
47280 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47281 new file mode 100644
47282 index 0000000..1b1f83c
47283 --- /dev/null
47284 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47285 @@ -0,0 +1,5147 @@
47286 +/* ==========================================================================
47287 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
47288 + * $Revision: #116 $
47289 + * $Date: 2012/08/10 $
47290 + * $Change: 2047372 $
47291 + *
47292 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
47293 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
47294 + * otherwise expressly agreed to in writing between Synopsys and you.
47295 + *
47296 + * The Software IS NOT an item of Licensed Software or Licensed Product under
47297 + * any End User Software License Agreement or Agreement for Licensed Product
47298 + * with Synopsys or any supplement thereto. You are permitted to use and
47299 + * redistribute this Software in source and binary forms, with or without
47300 + * modification, provided that redistributions of source code must retain this
47301 + * notice. You may not view, use, disclose, copy or distribute this file or
47302 + * any information contained herein except pursuant to this license grant from
47303 + * Synopsys. If you do not agree with this notice, including the disclaimer
47304 + * below, then you are not authorized to use the Software.
47305 + *
47306 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
47307 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47308 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47309 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
47310 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47311 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47312 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47313 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47314 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47315 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
47316 + * DAMAGE.
47317 + * ========================================================================== */
47318 +#ifndef DWC_HOST_ONLY
47319 +
47320 +#include "dwc_otg_pcd.h"
47321 +
47322 +#ifdef DWC_UTE_CFI
47323 +#include "dwc_otg_cfi.h"
47324 +#endif
47325 +
47326 +#ifdef DWC_UTE_PER_IO
47327 +extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
47328 +#endif
47329 +//#define PRINT_CFI_DMA_DESCS
47330 +
47331 +#define DEBUG_EP0
47332 +
47333 +/**
47334 + * This function updates OTG.
47335 + */
47336 +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
47337 +{
47338 +
47339 +       if (reset) {
47340 +               pcd->b_hnp_enable = 0;
47341 +               pcd->a_hnp_support = 0;
47342 +               pcd->a_alt_hnp_support = 0;
47343 +       }
47344 +
47345 +       if (pcd->fops->hnp_changed) {
47346 +               pcd->fops->hnp_changed(pcd);
47347 +       }
47348 +}
47349 +
47350 +/** @file
47351 + * This file contains the implementation of the PCD Interrupt handlers.
47352 + *
47353 + * The PCD handles the device interrupts.  Many conditions can cause a
47354 + * device interrupt. When an interrupt occurs, the device interrupt
47355 + * service routine determines the cause of the interrupt and
47356 + * dispatches handling to the appropriate function. These interrupt
47357 + * handling functions are described below.
47358 + * All interrupt registers are processed from LSB to MSB.
47359 + */
47360 +
47361 +/**
47362 + * This function prints the ep0 state for debug purposes.
47363 + */
47364 +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
47365 +{
47366 +#ifdef DEBUG
47367 +       char str[40];
47368 +
47369 +       switch (pcd->ep0state) {
47370 +       case EP0_DISCONNECT:
47371 +               dwc_strcpy(str, "EP0_DISCONNECT");
47372 +               break;
47373 +       case EP0_IDLE:
47374 +               dwc_strcpy(str, "EP0_IDLE");
47375 +               break;
47376 +       case EP0_IN_DATA_PHASE:
47377 +               dwc_strcpy(str, "EP0_IN_DATA_PHASE");
47378 +               break;
47379 +       case EP0_OUT_DATA_PHASE:
47380 +               dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
47381 +               break;
47382 +       case EP0_IN_STATUS_PHASE:
47383 +               dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
47384 +               break;
47385 +       case EP0_OUT_STATUS_PHASE:
47386 +               dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
47387 +               break;
47388 +       case EP0_STALL:
47389 +               dwc_strcpy(str, "EP0_STALL");
47390 +               break;
47391 +       default:
47392 +               dwc_strcpy(str, "EP0_INVALID");
47393 +       }
47394 +
47395 +       DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
47396 +#endif
47397 +}
47398 +
47399 +/**
47400 + * This function calculate the size of the payload in the memory
47401 + * for out endpoints and prints size for debug purposes(used in
47402 + * 2.93a DevOutNak feature).
47403 + */
47404 +static inline void print_memory_payload(dwc_otg_pcd_t * pcd,  dwc_ep_t * ep)
47405 +{
47406 +#ifdef DEBUG
47407 +       deptsiz_data_t deptsiz_init = {.d32 = 0 };
47408 +       deptsiz_data_t deptsiz_updt = {.d32 = 0 };
47409 +       int pack_num;
47410 +       unsigned payload;
47411 +
47412 +       deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
47413 +       deptsiz_updt.d32 =
47414 +               DWC_READ_REG32(&pcd->core_if->dev_if->
47415 +                                               out_ep_regs[ep->num]->doeptsiz);
47416 +       /* Payload will be */
47417 +       payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
47418 +       /* Packet count is decremented every time a packet
47419 +        * is written to the RxFIFO not in to the external memory
47420 +        * So, if payload == 0, then it means no packet was sent to ext memory*/
47421 +       pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
47422 +       DWC_DEBUGPL(DBG_PCDV,
47423 +               "Payload for EP%d-%s\n",
47424 +               ep->num, (ep->is_in ? "IN" : "OUT"));
47425 +       DWC_DEBUGPL(DBG_PCDV,
47426 +               "Number of transfered bytes = 0x%08x\n", payload);
47427 +       DWC_DEBUGPL(DBG_PCDV,
47428 +               "Number of transfered packets = %d\n", pack_num);
47429 +#endif
47430 +}
47431 +
47432 +
47433 +#ifdef DWC_UTE_CFI
47434 +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
47435 +                             const uint8_t * epname, int descnum)
47436 +{
47437 +       CFI_INFO
47438 +           ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
47439 +            epname, descnum, ddesc->buf, ddesc->status.b.bytes,
47440 +            ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
47441 +            ddesc->status.b.bs);
47442 +}
47443 +#endif
47444 +
47445 +/**
47446 + * This function returns pointer to in ep struct with number ep_num
47447 + */
47448 +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47449 +{
47450 +       int i;
47451 +       int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47452 +       if (ep_num == 0) {
47453 +               return &pcd->ep0;
47454 +       } else {
47455 +               for (i = 0; i < num_in_eps; ++i) {
47456 +                       if (pcd->in_ep[i].dwc_ep.num == ep_num)
47457 +                               return &pcd->in_ep[i];
47458 +               }
47459 +               return 0;
47460 +       }
47461 +}
47462 +
47463 +/**
47464 + * This function returns pointer to out ep struct with number ep_num
47465 + */
47466 +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47467 +{
47468 +       int i;
47469 +       int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47470 +       if (ep_num == 0) {
47471 +               return &pcd->ep0;
47472 +       } else {
47473 +               for (i = 0; i < num_out_eps; ++i) {
47474 +                       if (pcd->out_ep[i].dwc_ep.num == ep_num)
47475 +                               return &pcd->out_ep[i];
47476 +               }
47477 +               return 0;
47478 +       }
47479 +}
47480 +
47481 +/**
47482 + * This functions gets a pointer to an EP from the wIndex address
47483 + * value of the control request.
47484 + */
47485 +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
47486 +{
47487 +       dwc_otg_pcd_ep_t *ep;
47488 +       uint32_t ep_num = UE_GET_ADDR(wIndex);
47489 +
47490 +       if (ep_num == 0) {
47491 +               ep = &pcd->ep0;
47492 +       } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {   /* in ep */
47493 +               ep = &pcd->in_ep[ep_num - 1];
47494 +       } else {
47495 +               ep = &pcd->out_ep[ep_num - 1];
47496 +       }
47497 +
47498 +       return ep;
47499 +}
47500 +
47501 +/**
47502 + * This function checks the EP request queue, if the queue is not
47503 + * empty the next request is started.
47504 + */
47505 +void start_next_request(dwc_otg_pcd_ep_t * ep)
47506 +{
47507 +       dwc_otg_pcd_request_t *req = 0;
47508 +       uint32_t max_transfer =
47509 +           GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
47510 +
47511 +#ifdef DWC_UTE_CFI
47512 +       struct dwc_otg_pcd *pcd;
47513 +       pcd = ep->pcd;
47514 +#endif
47515 +
47516 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
47517 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
47518 +
47519 +#ifdef DWC_UTE_CFI
47520 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
47521 +                       ep->dwc_ep.cfi_req_len = req->length;
47522 +                       pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
47523 +               } else {
47524 +#endif
47525 +                       /* Setup and start the Transfer */
47526 +                       if (req->dw_align_buf) {
47527 +                               ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
47528 +                               ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
47529 +                               ep->dwc_ep.xfer_buff = req->dw_align_buf;
47530 +                       } else {
47531 +                               ep->dwc_ep.dma_addr = req->dma;
47532 +                               ep->dwc_ep.start_xfer_buff = req->buf;
47533 +                               ep->dwc_ep.xfer_buff = req->buf;
47534 +                       }
47535 +                       ep->dwc_ep.sent_zlp = 0;
47536 +                       ep->dwc_ep.total_len = req->length;
47537 +                       ep->dwc_ep.xfer_len = 0;
47538 +                       ep->dwc_ep.xfer_count = 0;
47539 +
47540 +                       ep->dwc_ep.maxxfer = max_transfer;
47541 +                       if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
47542 +                               uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
47543 +                                   - (DDMA_MAX_TRANSFER_SIZE % 4);
47544 +                               if (ep->dwc_ep.is_in) {
47545 +                                       if (ep->dwc_ep.maxxfer >
47546 +                                           DDMA_MAX_TRANSFER_SIZE) {
47547 +                                               ep->dwc_ep.maxxfer =
47548 +                                                   DDMA_MAX_TRANSFER_SIZE;
47549 +                                       }
47550 +                               } else {
47551 +                                       if (ep->dwc_ep.maxxfer > out_max_xfer) {
47552 +                                               ep->dwc_ep.maxxfer =
47553 +                                                   out_max_xfer;
47554 +                                       }
47555 +                               }
47556 +                       }
47557 +                       if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
47558 +                               ep->dwc_ep.maxxfer -=
47559 +                                   (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
47560 +                       }
47561 +                       if (req->sent_zlp) {
47562 +                               if ((ep->dwc_ep.total_len %
47563 +                                    ep->dwc_ep.maxpacket == 0)
47564 +                                   && (ep->dwc_ep.total_len != 0)) {
47565 +                                       ep->dwc_ep.sent_zlp = 1;
47566 +                               }
47567 +
47568 +                       }
47569 +#ifdef DWC_UTE_CFI
47570 +               }
47571 +#endif
47572 +               dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
47573 +       } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
47574 +               DWC_PRINTF("There are no more ISOC requests \n");
47575 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
47576 +       }
47577 +}
47578 +
47579 +/**
47580 + * This function handles the SOF Interrupts. At this time the SOF
47581 + * Interrupt is disabled.
47582 + */
47583 +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
47584 +{
47585 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47586 +
47587 +       gintsts_data_t gintsts;
47588 +
47589 +       DWC_DEBUGPL(DBG_PCD, "SOF\n");
47590 +
47591 +       /* Clear interrupt */
47592 +       gintsts.d32 = 0;
47593 +       gintsts.b.sofintr = 1;
47594 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
47595 +
47596 +       return 1;
47597 +}
47598 +
47599 +/**
47600 + * This function handles the Rx Status Queue Level Interrupt, which
47601 + * indicates that there is a least one packet in the Rx FIFO.  The
47602 + * packets are moved from the FIFO to memory, where they will be
47603 + * processed when the Endpoint Interrupt Register indicates Transfer
47604 + * Complete or SETUP Phase Done.
47605 + *
47606 + * Repeat the following until the Rx Status Queue is empty:
47607 + *      -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
47608 + *             info
47609 + *      -# If Receive FIFO is empty then skip to step Clear the interrupt
47610 + *             and exit
47611 + *      -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
47612 + *             SETUP data to the buffer
47613 + *      -# If OUT Data Packet call dwc_otg_read_packet to copy the data
47614 + *             to the destination buffer
47615 + */
47616 +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
47617 +{
47618 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47619 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47620 +       gintmsk_data_t gintmask = {.d32 = 0 };
47621 +       device_grxsts_data_t status;
47622 +       dwc_otg_pcd_ep_t *ep;
47623 +       gintsts_data_t gintsts;
47624 +#ifdef DEBUG
47625 +       static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
47626 +#endif
47627 +
47628 +       //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
47629 +       /* Disable the Rx Status Queue Level interrupt */
47630 +       gintmask.b.rxstsqlvl = 1;
47631 +       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
47632 +
47633 +       /* Get the Status from the top of the FIFO */
47634 +       status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
47635 +
47636 +       DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
47637 +                   "pktsts:%x Frame:%d(0x%0x)\n",
47638 +                   status.b.epnum, status.b.bcnt,
47639 +                   dpid_str[status.b.dpid],
47640 +                   status.b.pktsts, status.b.fn, status.b.fn);
47641 +       /* Get pointer to EP structure */
47642 +       ep = get_out_ep(pcd, status.b.epnum);
47643 +
47644 +       switch (status.b.pktsts) {
47645 +       case DWC_DSTS_GOUT_NAK:
47646 +               DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
47647 +               break;
47648 +       case DWC_STS_DATA_UPDT:
47649 +               DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
47650 +               if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
47651 +                       /** @todo NGS Check for buffer overflow? */
47652 +                       dwc_otg_read_packet(core_if,
47653 +                                           ep->dwc_ep.xfer_buff,
47654 +                                           status.b.bcnt);
47655 +                       ep->dwc_ep.xfer_count += status.b.bcnt;
47656 +                       ep->dwc_ep.xfer_buff += status.b.bcnt;
47657 +               }
47658 +               break;
47659 +       case DWC_STS_XFER_COMP:
47660 +               DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
47661 +               break;
47662 +       case DWC_DSTS_SETUP_COMP:
47663 +#ifdef DEBUG_EP0
47664 +               DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
47665 +#endif
47666 +               break;
47667 +       case DWC_DSTS_SETUP_UPDT:
47668 +               dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
47669 +#ifdef DEBUG_EP0
47670 +               DWC_DEBUGPL(DBG_PCD,
47671 +                           "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
47672 +                           pcd->setup_pkt->req.bmRequestType,
47673 +                           pcd->setup_pkt->req.bRequest,
47674 +                           UGETW(pcd->setup_pkt->req.wValue),
47675 +                           UGETW(pcd->setup_pkt->req.wIndex),
47676 +                           UGETW(pcd->setup_pkt->req.wLength));
47677 +#endif
47678 +               ep->dwc_ep.xfer_count += status.b.bcnt;
47679 +               break;
47680 +       default:
47681 +               DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
47682 +                           status.b.pktsts);
47683 +               break;
47684 +       }
47685 +
47686 +       /* Enable the Rx Status Queue Level interrupt */
47687 +       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
47688 +       /* Clear interrupt */
47689 +       gintsts.d32 = 0;
47690 +       gintsts.b.rxstsqlvl = 1;
47691 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47692 +
47693 +       //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
47694 +       return 1;
47695 +}
47696 +
47697 +/**
47698 + * This function examines the Device IN Token Learning Queue to
47699 + * determine the EP number of the last IN token received.  This
47700 + * implementation is for the Mass Storage device where there are only
47701 + * 2 IN EPs (Control-IN and BULK-IN).
47702 + *
47703 + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
47704 + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
47705 + *
47706 + * @param core_if Programming view of DWC_otg controller.
47707 + *
47708 + */
47709 +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
47710 +{
47711 +       dwc_otg_device_global_regs_t *dev_global_regs =
47712 +           core_if->dev_if->dev_global_regs;
47713 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
47714 +       /* Number of Token Queue Registers */
47715 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
47716 +       dtknq1_data_t dtknqr1;
47717 +       uint32_t in_tkn_epnums[4];
47718 +       int ndx = 0;
47719 +       int i = 0;
47720 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
47721 +       int epnum = 0;
47722 +
47723 +       //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
47724 +
47725 +       /* Read the DTKNQ Registers */
47726 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
47727 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
47728 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
47729 +                           in_tkn_epnums[i]);
47730 +               if (addr == &dev_global_regs->dvbusdis) {
47731 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
47732 +               } else {
47733 +                       ++addr;
47734 +               }
47735 +
47736 +       }
47737 +
47738 +       /* Copy the DTKNQR1 data to the bit field. */
47739 +       dtknqr1.d32 = in_tkn_epnums[0];
47740 +       /* Get the EP numbers */
47741 +       in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
47742 +       ndx = dtknqr1.b.intknwptr - 1;
47743 +
47744 +       //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
47745 +       if (ndx == -1) {
47746 +               /** @todo Find a simpler way to calculate the max
47747 +                * queue position.*/
47748 +               int cnt = TOKEN_Q_DEPTH;
47749 +               if (TOKEN_Q_DEPTH <= 6) {
47750 +                       cnt = TOKEN_Q_DEPTH - 1;
47751 +               } else if (TOKEN_Q_DEPTH <= 14) {
47752 +                       cnt = TOKEN_Q_DEPTH - 7;
47753 +               } else if (TOKEN_Q_DEPTH <= 22) {
47754 +                       cnt = TOKEN_Q_DEPTH - 15;
47755 +               } else {
47756 +                       cnt = TOKEN_Q_DEPTH - 23;
47757 +               }
47758 +               epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
47759 +       } else {
47760 +               if (ndx <= 5) {
47761 +                       epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
47762 +               } else if (ndx <= 13) {
47763 +                       ndx -= 6;
47764 +                       epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
47765 +               } else if (ndx <= 21) {
47766 +                       ndx -= 14;
47767 +                       epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
47768 +               } else if (ndx <= 29) {
47769 +                       ndx -= 22;
47770 +                       epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
47771 +               }
47772 +       }
47773 +       //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
47774 +       return epnum;
47775 +}
47776 +
47777 +/**
47778 + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
47779 + * The active request is checked for the next packet to be loaded into
47780 + * the non-periodic Tx FIFO.
47781 + */
47782 +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
47783 +{
47784 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47785 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47786 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47787 +       gnptxsts_data_t txstatus = {.d32 = 0 };
47788 +       gintsts_data_t gintsts;
47789 +
47790 +       int epnum = 0;
47791 +       dwc_otg_pcd_ep_t *ep = 0;
47792 +       uint32_t len = 0;
47793 +       int dwords;
47794 +
47795 +       /* Get the epnum from the IN Token Learning Queue. */
47796 +       epnum = get_ep_of_last_in_token(core_if);
47797 +       ep = get_in_ep(pcd, epnum);
47798 +
47799 +       DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
47800 +
47801 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47802 +
47803 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47804 +       if (len > ep->dwc_ep.maxpacket) {
47805 +               len = ep->dwc_ep.maxpacket;
47806 +       }
47807 +       dwords = (len + 3) / 4;
47808 +
47809 +       /* While there is space in the queue and space in the FIFO and
47810 +        * More data to tranfer, Write packets to the Tx FIFO */
47811 +       txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47812 +       DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
47813 +
47814 +       while (txstatus.b.nptxqspcavail > 0 &&
47815 +              txstatus.b.nptxfspcavail > dwords &&
47816 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
47817 +               /* Write the FIFO */
47818 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47819 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47820 +
47821 +               if (len > ep->dwc_ep.maxpacket) {
47822 +                       len = ep->dwc_ep.maxpacket;
47823 +               }
47824 +
47825 +               dwords = (len + 3) / 4;
47826 +               txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47827 +               DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
47828 +       }
47829 +
47830 +       DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
47831 +                   DWC_READ_REG32(&global_regs->gnptxsts));
47832 +
47833 +       /* Clear interrupt */
47834 +       gintsts.d32 = 0;
47835 +       gintsts.b.nptxfempty = 1;
47836 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47837 +
47838 +       return 1;
47839 +}
47840 +
47841 +/**
47842 + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
47843 + * The active request is checked for the next packet to be loaded into
47844 + * apropriate Tx FIFO.
47845 + */
47846 +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
47847 +{
47848 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47849 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47850 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47851 +       dtxfsts_data_t txstatus = {.d32 = 0 };
47852 +       dwc_otg_pcd_ep_t *ep = 0;
47853 +       uint32_t len = 0;
47854 +       int dwords;
47855 +
47856 +       ep = get_in_ep(pcd, epnum);
47857 +
47858 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
47859 +
47860 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47861 +
47862 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47863 +
47864 +       if (len > ep->dwc_ep.maxpacket) {
47865 +               len = ep->dwc_ep.maxpacket;
47866 +       }
47867 +
47868 +       dwords = (len + 3) / 4;
47869 +
47870 +       /* While there is space in the queue and space in the FIFO and
47871 +        * More data to tranfer, Write packets to the Tx FIFO */
47872 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47873 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
47874 +
47875 +       while (txstatus.b.txfspcavail > dwords &&
47876 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
47877 +              ep->dwc_ep.xfer_len != 0) {
47878 +               /* Write the FIFO */
47879 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47880 +
47881 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47882 +               if (len > ep->dwc_ep.maxpacket) {
47883 +                       len = ep->dwc_ep.maxpacket;
47884 +               }
47885 +
47886 +               dwords = (len + 3) / 4;
47887 +               txstatus.d32 =
47888 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47889 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
47890 +                           txstatus.d32);
47891 +       }
47892 +
47893 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
47894 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
47895 +
47896 +       return 1;
47897 +}
47898 +
47899 +/**
47900 + * This function is called when the Device is disconnected. It stops
47901 + * any active requests and informs the Gadget driver of the
47902 + * disconnect.
47903 + */
47904 +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
47905 +{
47906 +       int i, num_in_eps, num_out_eps;
47907 +       dwc_otg_pcd_ep_t *ep;
47908 +
47909 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47910 +
47911 +       DWC_SPINLOCK(pcd->lock);
47912 +
47913 +       num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47914 +       num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47915 +
47916 +       DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
47917 +       /* don't disconnect drivers more than once */
47918 +       if (pcd->ep0state == EP0_DISCONNECT) {
47919 +               DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
47920 +               DWC_SPINUNLOCK(pcd->lock);
47921 +               return;
47922 +       }
47923 +       pcd->ep0state = EP0_DISCONNECT;
47924 +
47925 +       /* Reset the OTG state. */
47926 +       dwc_otg_pcd_update_otg(pcd, 1);
47927 +
47928 +       /* Disable the NP Tx Fifo Empty Interrupt. */
47929 +       intr_mask.b.nptxfempty = 1;
47930 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47931 +                        intr_mask.d32, 0);
47932 +
47933 +       /* Flush the FIFOs */
47934 +       /**@todo NGS Flush Periodic FIFOs */
47935 +       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
47936 +       dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
47937 +
47938 +       /* prevent new request submissions, kill any outstanding requests  */
47939 +       ep = &pcd->ep0;
47940 +       dwc_otg_request_nuke(ep);
47941 +       /* prevent new request submissions, kill any outstanding requests  */
47942 +       for (i = 0; i < num_in_eps; i++) {
47943 +               dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
47944 +               dwc_otg_request_nuke(ep);
47945 +       }
47946 +       /* prevent new request submissions, kill any outstanding requests  */
47947 +       for (i = 0; i < num_out_eps; i++) {
47948 +               dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
47949 +               dwc_otg_request_nuke(ep);
47950 +       }
47951 +
47952 +       /* report disconnect; the driver is already quiesced */
47953 +       if (pcd->fops->disconnect) {
47954 +               DWC_SPINUNLOCK(pcd->lock);
47955 +               pcd->fops->disconnect(pcd);
47956 +               DWC_SPINLOCK(pcd->lock);
47957 +       }
47958 +       DWC_SPINUNLOCK(pcd->lock);
47959 +}
47960 +
47961 +/**
47962 + * This interrupt indicates that ...
47963 + */
47964 +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
47965 +{
47966 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47967 +       gintsts_data_t gintsts;
47968 +
47969 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
47970 +       intr_mask.b.i2cintr = 1;
47971 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47972 +                        intr_mask.d32, 0);
47973 +
47974 +       /* Clear interrupt */
47975 +       gintsts.d32 = 0;
47976 +       gintsts.b.i2cintr = 1;
47977 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
47978 +                       gintsts.d32);
47979 +       return 1;
47980 +}
47981 +
47982 +/**
47983 + * This interrupt indicates that ...
47984 + */
47985 +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
47986 +{
47987 +       gintsts_data_t gintsts;
47988 +#if defined(VERBOSE)
47989 +       DWC_PRINTF("Early Suspend Detected\n");
47990 +#endif
47991 +
47992 +       /* Clear interrupt */
47993 +       gintsts.d32 = 0;
47994 +       gintsts.b.erlysuspend = 1;
47995 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
47996 +                       gintsts.d32);
47997 +       return 1;
47998 +}
47999 +
48000 +/**
48001 + * This function configures EPO to receive SETUP packets.
48002 + *
48003 + * @todo NGS: Update the comments from the HW FS.
48004 + *
48005 + *     -# Program the following fields in the endpoint specific registers
48006 + *     for Control OUT EP 0, in order to receive a setup packet
48007 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
48008 + *       setup packets)
48009 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
48010 + *       to back setup packets)
48011 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
48012 + *               store any setup packets received
48013 + *
48014 + * @param core_if Programming view of DWC_otg controller.
48015 + * @param pcd    Programming view of the PCD.
48016 + */
48017 +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
48018 +                                dwc_otg_pcd_t * pcd)
48019 +{
48020 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48021 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
48022 +       dwc_otg_dev_dma_desc_t *dma_desc;
48023 +       depctl_data_t doepctl = {.d32 = 0 };
48024 +
48025 +#ifdef VERBOSE
48026 +       DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
48027 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
48028 +#endif
48029 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
48030 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
48031 +               if (doepctl.b.epena) {
48032 +                       return;
48033 +               }
48034 +       }
48035 +
48036 +       doeptsize0.b.supcnt = 3;
48037 +       doeptsize0.b.pktcnt = 1;
48038 +       doeptsize0.b.xfersize = 8 * 3;
48039 +
48040 +       if (core_if->dma_enable) {
48041 +               if (!core_if->dma_desc_enable) {
48042 +                       /** put here as for Hermes mode deptisz register should not be written */
48043 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
48044 +                                       doeptsize0.d32);
48045 +
48046 +                       /** @todo dma needs to handle multiple setup packets (up to 3) */
48047 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
48048 +                                       pcd->setup_pkt_dma_handle);
48049 +               } else {
48050 +                       dev_if->setup_desc_index =
48051 +                           (dev_if->setup_desc_index + 1) & 1;
48052 +                       dma_desc =
48053 +                           dev_if->setup_desc_addr[dev_if->setup_desc_index];
48054 +
48055 +                       /** DMA Descriptor Setup */
48056 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
48057 +                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
48058 +                               dma_desc->status.b.sr = 0;
48059 +                               dma_desc->status.b.mtrf = 0;
48060 +                       }
48061 +                       dma_desc->status.b.l = 1;
48062 +                       dma_desc->status.b.ioc = 1;
48063 +                       dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
48064 +                       dma_desc->buf = pcd->setup_pkt_dma_handle;
48065 +                       dma_desc->status.b.sts = 0;
48066 +                       dma_desc->status.b.bs = BS_HOST_READY;
48067 +
48068 +                       /** DOEPDMA0 Register write */
48069 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
48070 +                                       dev_if->dma_setup_desc_addr
48071 +                                       [dev_if->setup_desc_index]);
48072 +               }
48073 +
48074 +       } else {
48075 +               /** put here as for Hermes mode deptisz register should not be written */
48076 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
48077 +                               doeptsize0.d32);
48078 +       }
48079 +
48080 +       /** DOEPCTL0 Register write cnak will be set after setup interrupt */
48081 +       doepctl.d32 = 0;
48082 +       doepctl.b.epena = 1;
48083 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
48084 +       doepctl.b.cnak = 1;
48085 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
48086 +       } else {
48087 +               DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
48088 +       }
48089 +
48090 +#ifdef VERBOSE
48091 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
48092 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
48093 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
48094 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
48095 +#endif
48096 +}
48097 +
48098 +/**
48099 + * This interrupt occurs when a USB Reset is detected. When the USB
48100 + * Reset Interrupt occurs the device state is set to DEFAULT and the
48101 + * EP0 state is set to IDLE.
48102 + *     -#      Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
48103 + *     -#      Unmask the following interrupt bits
48104 + *             - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
48105 + *     - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
48106 + *     - DOEPMSK.SETUP = 1
48107 + *     - DOEPMSK.XferCompl = 1
48108 + *     - DIEPMSK.XferCompl = 1
48109 + *     - DIEPMSK.TimeOut = 1
48110 + *     -# Program the following fields in the endpoint specific registers
48111 + *     for Control OUT EP 0, in order to receive a setup packet
48112 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
48113 + *       setup packets)
48114 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
48115 + *       to back setup packets)
48116 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
48117 + *               store any setup packets received
48118 + * At this point, all the required initialization, except for enabling
48119 + * the control 0 OUT endpoint is done, for receiving SETUP packets.
48120 + */
48121 +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
48122 +{
48123 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48124 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48125 +       depctl_data_t doepctl = {.d32 = 0 };
48126 +       depctl_data_t diepctl = {.d32 = 0 };
48127 +       daint_data_t daintmsk = {.d32 = 0 };
48128 +       doepmsk_data_t doepmsk = {.d32 = 0 };
48129 +       diepmsk_data_t diepmsk = {.d32 = 0 };
48130 +       dcfg_data_t dcfg = {.d32 = 0 };
48131 +       grstctl_t resetctl = {.d32 = 0 };
48132 +       dctl_data_t dctl = {.d32 = 0 };
48133 +       int i = 0;
48134 +       gintsts_data_t gintsts;
48135 +       pcgcctl_data_t power = {.d32 = 0 };
48136 +
48137 +       power.d32 = DWC_READ_REG32(core_if->pcgcctl);
48138 +       if (power.b.stoppclk) {
48139 +               power.d32 = 0;
48140 +               power.b.stoppclk = 1;
48141 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48142 +
48143 +               power.b.pwrclmp = 1;
48144 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48145 +
48146 +               power.b.rstpdwnmodule = 1;
48147 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48148 +       }
48149 +
48150 +       core_if->lx_state = DWC_OTG_L0;
48151 +
48152 +       DWC_PRINTF("USB RESET\n");
48153 +#ifdef DWC_EN_ISOC
48154 +       for (i = 1; i < 16; ++i) {
48155 +               dwc_otg_pcd_ep_t *ep;
48156 +               dwc_ep_t *dwc_ep;
48157 +               ep = get_in_ep(pcd, i);
48158 +               if (ep != 0) {
48159 +                       dwc_ep = &ep->dwc_ep;
48160 +                       dwc_ep->next_frame = 0xffffffff;
48161 +               }
48162 +       }
48163 +#endif /* DWC_EN_ISOC */
48164 +
48165 +       /* reset the HNP settings */
48166 +       dwc_otg_pcd_update_otg(pcd, 1);
48167 +
48168 +       /* Clear the Remote Wakeup Signalling */
48169 +       dctl.b.rmtwkupsig = 1;
48170 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
48171 +
48172 +       /* Set NAK for all OUT EPs */
48173 +       doepctl.b.snak = 1;
48174 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
48175 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
48176 +       }
48177 +
48178 +       /* Flush the NP Tx FIFO */
48179 +       dwc_otg_flush_tx_fifo(core_if, 0x10);
48180 +       /* Flush the Learning Queue */
48181 +       resetctl.b.intknqflsh = 1;
48182 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
48183 +
48184 +       if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
48185 +               core_if->start_predict = 0;
48186 +               for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
48187 +                       core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
48188 +               }
48189 +               core_if->nextep_seq[0] = 0;
48190 +               core_if->first_in_nextep_seq = 0;
48191 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
48192 +               diepctl.b.nextep = 0;
48193 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
48194 +
48195 +               /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
48196 +               dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48197 +               dcfg.b.epmscnt = 2;
48198 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48199 +
48200 +               DWC_DEBUGPL(DBG_PCDV,
48201 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
48202 +                       __func__, core_if->first_in_nextep_seq);
48203 +               for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
48204 +                       DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
48205 +               }
48206 +       }
48207 +
48208 +       if (core_if->multiproc_int_enable) {
48209 +               daintmsk.b.inep0 = 1;
48210 +               daintmsk.b.outep0 = 1;
48211 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
48212 +                               daintmsk.d32);
48213 +
48214 +               doepmsk.b.setup = 1;
48215 +               doepmsk.b.xfercompl = 1;
48216 +               doepmsk.b.ahberr = 1;
48217 +               doepmsk.b.epdisabled = 1;
48218 +
48219 +               if ((core_if->dma_desc_enable) ||
48220 +                   (core_if->dma_enable
48221 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48222 +                       doepmsk.b.stsphsercvd = 1;
48223 +               }
48224 +               if (core_if->dma_desc_enable)
48225 +                       doepmsk.b.bna = 1;
48226 +/*
48227 +               doepmsk.b.babble = 1;
48228 +               doepmsk.b.nyet = 1;
48229 +
48230 +               if (core_if->dma_enable) {
48231 +                       doepmsk.b.nak = 1;
48232 +               }
48233 +*/
48234 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
48235 +                               doepmsk.d32);
48236 +
48237 +               diepmsk.b.xfercompl = 1;
48238 +               diepmsk.b.timeout = 1;
48239 +               diepmsk.b.epdisabled = 1;
48240 +               diepmsk.b.ahberr = 1;
48241 +               diepmsk.b.intknepmis = 1;
48242 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48243 +                       diepmsk.b.intknepmis = 0;
48244 +
48245 +/*             if (core_if->dma_desc_enable) {
48246 +                       diepmsk.b.bna = 1;
48247 +               }
48248 +*/
48249 +/*
48250 +               if (core_if->dma_enable) {
48251 +                       diepmsk.b.nak = 1;
48252 +               }
48253 +*/
48254 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
48255 +                               diepmsk.d32);
48256 +       } else {
48257 +               daintmsk.b.inep0 = 1;
48258 +               daintmsk.b.outep0 = 1;
48259 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
48260 +                               daintmsk.d32);
48261 +
48262 +               doepmsk.b.setup = 1;
48263 +               doepmsk.b.xfercompl = 1;
48264 +               doepmsk.b.ahberr = 1;
48265 +               doepmsk.b.epdisabled = 1;
48266 +
48267 +               if ((core_if->dma_desc_enable) ||
48268 +                   (core_if->dma_enable
48269 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48270 +                       doepmsk.b.stsphsercvd = 1;
48271 +               }
48272 +               if (core_if->dma_desc_enable)
48273 +                       doepmsk.b.bna = 1;
48274 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
48275 +
48276 +               diepmsk.b.xfercompl = 1;
48277 +               diepmsk.b.timeout = 1;
48278 +               diepmsk.b.epdisabled = 1;
48279 +               diepmsk.b.ahberr = 1;
48280 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48281 +                       diepmsk.b.intknepmis = 0;
48282 +/*
48283 +               if (core_if->dma_desc_enable) {
48284 +                       diepmsk.b.bna = 1;
48285 +               }
48286 +*/
48287 +
48288 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
48289 +       }
48290 +
48291 +       /* Reset Device Address */
48292 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48293 +       dcfg.b.devaddr = 0;
48294 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48295 +
48296 +       /* setup EP0 to receive SETUP packets */
48297 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a)
48298 +               ep0_out_start(core_if, pcd);
48299 +
48300 +       /* Clear interrupt */
48301 +       gintsts.d32 = 0;
48302 +       gintsts.b.usbreset = 1;
48303 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48304 +
48305 +       return 1;
48306 +}
48307 +
48308 +/**
48309 + * Get the device speed from the device status register and convert it
48310 + * to USB speed constant.
48311 + *
48312 + * @param core_if Programming view of DWC_otg controller.
48313 + */
48314 +static int get_device_speed(dwc_otg_core_if_t * core_if)
48315 +{
48316 +       dsts_data_t dsts;
48317 +       int speed = 0;
48318 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
48319 +
48320 +       switch (dsts.b.enumspd) {
48321 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
48322 +               speed = USB_SPEED_HIGH;
48323 +               break;
48324 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
48325 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
48326 +               speed = USB_SPEED_FULL;
48327 +               break;
48328 +
48329 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
48330 +               speed = USB_SPEED_LOW;
48331 +               break;
48332 +       }
48333 +
48334 +       return speed;
48335 +}
48336 +
48337 +/**
48338 + * Read the device status register and set the device speed in the
48339 + * data structure.
48340 + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
48341 + */
48342 +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
48343 +{
48344 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48345 +       gintsts_data_t gintsts;
48346 +       gusbcfg_data_t gusbcfg;
48347 +       dwc_otg_core_global_regs_t *global_regs =
48348 +           GET_CORE_IF(pcd)->core_global_regs;
48349 +       uint8_t utmi16b, utmi8b;
48350 +       int speed;
48351 +       DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
48352 +
48353 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
48354 +               utmi16b = 6;    //vahrama old value was 6;
48355 +               utmi8b = 9;
48356 +       } else {
48357 +               utmi16b = 4;
48358 +               utmi8b = 8;
48359 +       }
48360 +       dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
48361 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
48362 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48363 +       }
48364 +
48365 +#ifdef DEBUG_EP0
48366 +       print_ep0_state(pcd);
48367 +#endif
48368 +
48369 +       if (pcd->ep0state == EP0_DISCONNECT) {
48370 +               pcd->ep0state = EP0_IDLE;
48371 +       } else if (pcd->ep0state == EP0_STALL) {
48372 +               pcd->ep0state = EP0_IDLE;
48373 +       }
48374 +
48375 +       pcd->ep0state = EP0_IDLE;
48376 +
48377 +       ep0->stopped = 0;
48378 +
48379 +       speed = get_device_speed(GET_CORE_IF(pcd));
48380 +       pcd->fops->connect(pcd, speed);
48381 +
48382 +       /* Set USB turnaround time based on device speed and PHY interface. */
48383 +       gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
48384 +       if (speed == USB_SPEED_HIGH) {
48385 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48386 +                   DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
48387 +                       /* ULPI interface */
48388 +                       gusbcfg.b.usbtrdtim = 9;
48389 +               }
48390 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48391 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
48392 +                       /* UTMI+ interface */
48393 +                       if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
48394 +                               gusbcfg.b.usbtrdtim = utmi8b;
48395 +                       } else if (GET_CORE_IF(pcd)->hwcfg4.
48396 +                                  b.utmi_phy_data_width == 1) {
48397 +                               gusbcfg.b.usbtrdtim = utmi16b;
48398 +                       } else if (GET_CORE_IF(pcd)->
48399 +                                  core_params->phy_utmi_width == 8) {
48400 +                               gusbcfg.b.usbtrdtim = utmi8b;
48401 +                       } else {
48402 +                               gusbcfg.b.usbtrdtim = utmi16b;
48403 +                       }
48404 +               }
48405 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48406 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
48407 +                       /* UTMI+  OR  ULPI interface */
48408 +                       if (gusbcfg.b.ulpi_utmi_sel == 1) {
48409 +                               /* ULPI interface */
48410 +                               gusbcfg.b.usbtrdtim = 9;
48411 +                       } else {
48412 +                               /* UTMI+ interface */
48413 +                               if (GET_CORE_IF(pcd)->
48414 +                                   core_params->phy_utmi_width == 16) {
48415 +                                       gusbcfg.b.usbtrdtim = utmi16b;
48416 +                               } else {
48417 +                                       gusbcfg.b.usbtrdtim = utmi8b;
48418 +                               }
48419 +                       }
48420 +               }
48421 +       } else {
48422 +               /* Full or low speed */
48423 +               gusbcfg.b.usbtrdtim = 9;
48424 +       }
48425 +       DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
48426 +
48427 +       /* Clear interrupt */
48428 +       gintsts.d32 = 0;
48429 +       gintsts.b.enumdone = 1;
48430 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48431 +                       gintsts.d32);
48432 +       return 1;
48433 +}
48434 +
48435 +/**
48436 + * This interrupt indicates that the ISO OUT Packet was dropped due to
48437 + * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs
48438 + * read all the data from the Rx FIFO.
48439 + */
48440 +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
48441 +{
48442 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48443 +       gintsts_data_t gintsts;
48444 +
48445 +       DWC_WARN("INTERRUPT Handler not implemented for %s\n",
48446 +                "ISOC Out Dropped");
48447 +
48448 +       intr_mask.b.isooutdrop = 1;
48449 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48450 +                        intr_mask.d32, 0);
48451 +
48452 +       /* Clear interrupt */
48453 +       gintsts.d32 = 0;
48454 +       gintsts.b.isooutdrop = 1;
48455 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48456 +                       gintsts.d32);
48457 +
48458 +       return 1;
48459 +}
48460 +
48461 +/**
48462 + * This interrupt indicates the end of the portion of the micro-frame
48463 + * for periodic transactions.  If there is a periodic transaction for
48464 + * the next frame, load the packets into the EP periodic Tx FIFO.
48465 + */
48466 +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
48467 +{
48468 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48469 +       gintsts_data_t gintsts;
48470 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
48471 +
48472 +       intr_mask.b.eopframe = 1;
48473 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48474 +                        intr_mask.d32, 0);
48475 +
48476 +       /* Clear interrupt */
48477 +       gintsts.d32 = 0;
48478 +       gintsts.b.eopframe = 1;
48479 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48480 +                       gintsts.d32);
48481 +
48482 +       return 1;
48483 +}
48484 +
48485 +/**
48486 + * This interrupt indicates that EP of the packet on the top of the
48487 + * non-periodic Tx FIFO does not match EP of the IN Token received.
48488 + *
48489 + * The "Device IN Token Queue" Registers are read to determine the
48490 + * order the IN Tokens have been received. The non-periodic Tx FIFO
48491 + * is flushed, so it can be reloaded in the order seen in the IN Token
48492 + * Queue.
48493 + */
48494 +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
48495 +{
48496 +       gintsts_data_t gintsts;
48497 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48498 +       dctl_data_t dctl;
48499 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48500 +
48501 +       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
48502 +               core_if->start_predict = 1;
48503 +
48504 +               DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48505 +
48506 +               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
48507 +               if (!gintsts.b.ginnakeff) {
48508 +                       /* Disable EP Mismatch interrupt */
48509 +                       intr_mask.d32 = 0;
48510 +                       intr_mask.b.epmismatch = 1;
48511 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
48512 +                       /* Enable the Global IN NAK Effective Interrupt */
48513 +                       intr_mask.d32 = 0;
48514 +                       intr_mask.b.ginnakeff = 1;
48515 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
48516 +                       /* Set the global non-periodic IN NAK handshake */
48517 +                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48518 +                       dctl.b.sgnpinnak = 1;
48519 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48520 +               } else {
48521 +                       DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
48522 +               }
48523 +               /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
48524 +                * handler after Global IN NAK Effective interrupt will be asserted */
48525 +       }
48526 +       /* Clear interrupt */
48527 +       gintsts.d32 = 0;
48528 +       gintsts.b.epmismatch = 1;
48529 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48530 +
48531 +       return 1;
48532 +}
48533 +
48534 +/**
48535 + * This interrupt is valid only in DMA mode. This interrupt indicates that the
48536 + * core has stopped fetching data for IN endpoints due to the unavailability of
48537 + * TxFIFO space or Request Queue space. This interrupt is used by the
48538 + * application for an endpoint mismatch algorithm.
48539 + *
48540 + * @param pcd The PCD
48541 + */
48542 +int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
48543 +{
48544 +       gintsts_data_t gintsts;
48545 +       gintmsk_data_t gintmsk_data;
48546 +       dctl_data_t dctl;
48547 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48548 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48549 +
48550 +       /* Clear the global non-periodic IN NAK handshake */
48551 +       dctl.d32 = 0;
48552 +       dctl.b.cgnpinnak = 1;
48553 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
48554 +
48555 +       /* Mask GINTSTS.FETSUSP interrupt */
48556 +       gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
48557 +       gintmsk_data.b.fetsusp = 0;
48558 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
48559 +
48560 +       /* Clear interrupt */
48561 +       gintsts.d32 = 0;
48562 +       gintsts.b.fetsusp = 1;
48563 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48564 +
48565 +       return 1;
48566 +}
48567 +/**
48568 + * This funcion stalls EP0.
48569 + */
48570 +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
48571 +{
48572 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48573 +       usb_device_request_t *ctrl = &pcd->setup_pkt->req;
48574 +       DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
48575 +                ctrl->bmRequestType, ctrl->bRequest, err_val);
48576 +
48577 +       ep0->dwc_ep.is_in = 1;
48578 +       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
48579 +       pcd->ep0.stopped = 1;
48580 +       pcd->ep0state = EP0_IDLE;
48581 +       ep0_out_start(GET_CORE_IF(pcd), pcd);
48582 +}
48583 +
48584 +/**
48585 + * This functions delegates the setup command to the gadget driver.
48586 + */
48587 +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
48588 +                                  usb_device_request_t * ctrl)
48589 +{
48590 +       int ret = 0;
48591 +       DWC_SPINUNLOCK(pcd->lock);
48592 +       ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
48593 +       DWC_SPINLOCK(pcd->lock);
48594 +       if (ret < 0) {
48595 +               ep0_do_stall(pcd, ret);
48596 +       }
48597 +
48598 +       /** @todo This is a g_file_storage gadget driver specific
48599 +        * workaround: a DELAYED_STATUS result from the fsg_setup
48600 +        * routine will result in the gadget queueing a EP0 IN status
48601 +        * phase for a two-stage control transfer. Exactly the same as
48602 +        * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
48603 +        * specific request.  Need a generic way to know when the gadget
48604 +        * driver will queue the status phase. Can we assume when we
48605 +        * call the gadget driver setup() function that it will always
48606 +        * queue and require the following flag? Need to look into
48607 +        * this.
48608 +        */
48609 +
48610 +       if (ret == 256 + 999) {
48611 +               pcd->request_config = 1;
48612 +       }
48613 +}
48614 +
48615 +#ifdef DWC_UTE_CFI
48616 +/**
48617 + * This functions delegates the CFI setup commands to the gadget driver.
48618 + * This function will return a negative value to indicate a failure.
48619 + */
48620 +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
48621 +                                  struct cfi_usb_ctrlrequest *ctrl_req)
48622 +{
48623 +       int ret = 0;
48624 +
48625 +       if (pcd->fops && pcd->fops->cfi_setup) {
48626 +               DWC_SPINUNLOCK(pcd->lock);
48627 +               ret = pcd->fops->cfi_setup(pcd, ctrl_req);
48628 +               DWC_SPINLOCK(pcd->lock);
48629 +               if (ret < 0) {
48630 +                       ep0_do_stall(pcd, ret);
48631 +                       return ret;
48632 +               }
48633 +       }
48634 +
48635 +       return ret;
48636 +}
48637 +#endif
48638 +
48639 +/**
48640 + * This function starts the Zero-Length Packet for the IN status phase
48641 + * of a 2 stage control transfer.
48642 + */
48643 +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
48644 +{
48645 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48646 +       if (pcd->ep0state == EP0_STALL) {
48647 +               return;
48648 +       }
48649 +
48650 +       pcd->ep0state = EP0_IN_STATUS_PHASE;
48651 +
48652 +       /* Prepare for more SETUP Packets */
48653 +       DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
48654 +       if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
48655 +           && (pcd->core_if->dma_desc_enable)
48656 +           && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
48657 +               DWC_DEBUGPL(DBG_PCDV,
48658 +                           "Data terminated wait next packet in out_desc_addr\n");
48659 +               pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
48660 +               pcd->data_terminated = 1;
48661 +       }
48662 +       ep0->dwc_ep.xfer_len = 0;
48663 +       ep0->dwc_ep.xfer_count = 0;
48664 +       ep0->dwc_ep.is_in = 1;
48665 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48666 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48667 +
48668 +       /* Prepare for more SETUP Packets */
48669 +       //ep0_out_start(GET_CORE_IF(pcd), pcd);
48670 +}
48671 +
48672 +/**
48673 + * This function starts the Zero-Length Packet for the OUT status phase
48674 + * of a 2 stage control transfer.
48675 + */
48676 +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
48677 +{
48678 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48679 +       if (pcd->ep0state == EP0_STALL) {
48680 +               DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
48681 +               return;
48682 +       }
48683 +       pcd->ep0state = EP0_OUT_STATUS_PHASE;
48684 +
48685 +       DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
48686 +       ep0->dwc_ep.xfer_len = 0;
48687 +       ep0->dwc_ep.xfer_count = 0;
48688 +       ep0->dwc_ep.is_in = 0;
48689 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48690 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48691 +
48692 +       /* Prepare for more SETUP Packets */
48693 +       if (GET_CORE_IF(pcd)->dma_enable == 0) {
48694 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48695 +       }
48696 +}
48697 +
48698 +/**
48699 + * Clear the EP halt (STALL) and if pending requests start the
48700 + * transfer.
48701 + */
48702 +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
48703 +{
48704 +       if (ep->dwc_ep.stall_clear_flag == 0)
48705 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
48706 +
48707 +       /* Reactive the EP */
48708 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
48709 +       if (ep->stopped) {
48710 +               ep->stopped = 0;
48711 +               /* If there is a request in the EP queue start it */
48712 +
48713 +               /** @todo FIXME: this causes an EP mismatch in DMA mode.
48714 +                * epmismatch not yet implemented. */
48715 +
48716 +               /*
48717 +                * Above fixme is solved by implmenting a tasklet to call the
48718 +                * start_next_request(), outside of interrupt context at some
48719 +                * time after the current time, after a clear-halt setup packet.
48720 +                * Still need to implement ep mismatch in the future if a gadget
48721 +                * ever uses more than one endpoint at once
48722 +                */
48723 +               ep->queue_sof = 1;
48724 +               DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
48725 +       }
48726 +       /* Start Control Status Phase */
48727 +       do_setup_in_status_phase(pcd);
48728 +}
48729 +
48730 +/**
48731 + * This function is called when the SET_FEATURE TEST_MODE Setup packet
48732 + * is sent from the host.  The Device Control register is written with
48733 + * the Test Mode bits set to the specified Test Mode.  This is done as
48734 + * a tasklet so that the "Status" phase of the control transfer
48735 + * completes before transmitting the TEST packets.
48736 + *
48737 + * @todo This has not been tested since the tasklet struct was put
48738 + * into the PCD struct!
48739 + *
48740 + */
48741 +void do_test_mode(void *data)
48742 +{
48743 +       dctl_data_t dctl;
48744 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
48745 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48746 +       int test_mode = pcd->test_mode;
48747 +
48748 +//        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
48749 +
48750 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48751 +       switch (test_mode) {
48752 +       case 1:         // TEST_J
48753 +               dctl.b.tstctl = 1;
48754 +               break;
48755 +
48756 +       case 2:         // TEST_K
48757 +               dctl.b.tstctl = 2;
48758 +               break;
48759 +
48760 +       case 3:         // TEST_SE0_NAK
48761 +               dctl.b.tstctl = 3;
48762 +               break;
48763 +
48764 +       case 4:         // TEST_PACKET
48765 +               dctl.b.tstctl = 4;
48766 +               break;
48767 +
48768 +       case 5:         // TEST_FORCE_ENABLE
48769 +               dctl.b.tstctl = 5;
48770 +               break;
48771 +       }
48772 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48773 +}
48774 +
48775 +/**
48776 + * This function process the GET_STATUS Setup Commands.
48777 + */
48778 +static inline void do_get_status(dwc_otg_pcd_t * pcd)
48779 +{
48780 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48781 +       dwc_otg_pcd_ep_t *ep;
48782 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48783 +       uint16_t *status = pcd->status_buf;
48784 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48785 +
48786 +#ifdef DEBUG_EP0
48787 +       DWC_DEBUGPL(DBG_PCD,
48788 +                   "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
48789 +                   ctrl.bmRequestType, ctrl.bRequest,
48790 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48791 +                   UGETW(ctrl.wLength));
48792 +#endif
48793 +
48794 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48795 +       case UT_DEVICE:
48796 +               if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
48797 +                       DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
48798 +                       DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
48799 +                       DWC_PRINTF("OTG CAP - %d, %d\n",
48800 +                                  core_if->core_params->otg_cap,
48801 +                                               DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
48802 +                       if (core_if->otg_ver == 1
48803 +                           && core_if->core_params->otg_cap ==
48804 +                           DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48805 +                               uint8_t *otgsts = (uint8_t*)pcd->status_buf;
48806 +                               *otgsts = (core_if->otg_sts & 0x1);
48807 +                               pcd->ep0_pending = 1;
48808 +                               ep0->dwc_ep.start_xfer_buff =
48809 +                                   (uint8_t *) otgsts;
48810 +                               ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
48811 +                               ep0->dwc_ep.dma_addr =
48812 +                                   pcd->status_buf_dma_handle;
48813 +                               ep0->dwc_ep.xfer_len = 1;
48814 +                               ep0->dwc_ep.xfer_count = 0;
48815 +                               ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48816 +                               dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
48817 +                                                          &ep0->dwc_ep);
48818 +                               return;
48819 +                       } else {
48820 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48821 +                               return;
48822 +                       }
48823 +                       break;
48824 +               } else {
48825 +                       *status = 0x1;  /* Self powered */
48826 +                       *status |= pcd->remote_wakeup_enable << 1;
48827 +                       break;
48828 +               }
48829 +       case UT_INTERFACE:
48830 +               *status = 0;
48831 +               break;
48832 +
48833 +       case UT_ENDPOINT:
48834 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48835 +               if (ep == 0 || UGETW(ctrl.wLength) > 2) {
48836 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48837 +                       return;
48838 +               }
48839 +               /** @todo check for EP stall */
48840 +               *status = ep->stopped;
48841 +               break;
48842 +       }
48843 +       pcd->ep0_pending = 1;
48844 +       ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
48845 +       ep0->dwc_ep.xfer_buff = (uint8_t *) status;
48846 +       ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
48847 +       ep0->dwc_ep.xfer_len = 2;
48848 +       ep0->dwc_ep.xfer_count = 0;
48849 +       ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48850 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48851 +}
48852 +
48853 +/**
48854 + * This function process the SET_FEATURE Setup Commands.
48855 + */
48856 +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
48857 +{
48858 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48859 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
48860 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48861 +       dwc_otg_pcd_ep_t *ep = 0;
48862 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
48863 +       gotgctl_data_t gotgctl = {.d32 = 0 };
48864 +
48865 +       DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48866 +                   ctrl.bmRequestType, ctrl.bRequest,
48867 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48868 +                   UGETW(ctrl.wLength));
48869 +       DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
48870 +
48871 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48872 +       case UT_DEVICE:
48873 +               switch (UGETW(ctrl.wValue)) {
48874 +               case UF_DEVICE_REMOTE_WAKEUP:
48875 +                       pcd->remote_wakeup_enable = 1;
48876 +                       break;
48877 +
48878 +               case UF_TEST_MODE:
48879 +                       /* Setup the Test Mode tasklet to do the Test
48880 +                        * Packet generation after the SETUP Status
48881 +                        * phase has completed. */
48882 +
48883 +                       /** @todo This has not been tested since the
48884 +                        * tasklet struct was put into the PCD
48885 +                        * struct! */
48886 +                       pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
48887 +                       DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
48888 +                       break;
48889 +
48890 +               case UF_DEVICE_B_HNP_ENABLE:
48891 +                       DWC_DEBUGPL(DBG_PCDV,
48892 +                                   "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
48893 +
48894 +                       /* dev may initiate HNP */
48895 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48896 +                               pcd->b_hnp_enable = 1;
48897 +                               dwc_otg_pcd_update_otg(pcd, 0);
48898 +                               DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
48899 +                               /**@todo Is the gotgctl.devhnpen cleared
48900 +                                * by a USB Reset? */
48901 +                               gotgctl.b.devhnpen = 1;
48902 +                               gotgctl.b.hnpreq = 1;
48903 +                               DWC_WRITE_REG32(&global_regs->gotgctl,
48904 +                                               gotgctl.d32);
48905 +                       } else {
48906 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48907 +                               return;
48908 +                       }
48909 +                       break;
48910 +
48911 +               case UF_DEVICE_A_HNP_SUPPORT:
48912 +                       /* RH port supports HNP */
48913 +                       DWC_DEBUGPL(DBG_PCDV,
48914 +                                   "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
48915 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48916 +                               pcd->a_hnp_support = 1;
48917 +                               dwc_otg_pcd_update_otg(pcd, 0);
48918 +                       } else {
48919 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48920 +                               return;
48921 +                       }
48922 +                       break;
48923 +
48924 +               case UF_DEVICE_A_ALT_HNP_SUPPORT:
48925 +                       /* other RH port does */
48926 +                       DWC_DEBUGPL(DBG_PCDV,
48927 +                                   "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
48928 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48929 +                               pcd->a_alt_hnp_support = 1;
48930 +                               dwc_otg_pcd_update_otg(pcd, 0);
48931 +                       } else {
48932 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48933 +                               return;
48934 +                       }
48935 +                       break;
48936 +
48937 +               default:
48938 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48939 +                       return;
48940 +
48941 +               }
48942 +               do_setup_in_status_phase(pcd);
48943 +               break;
48944 +
48945 +       case UT_INTERFACE:
48946 +               do_gadget_setup(pcd, &ctrl);
48947 +               break;
48948 +
48949 +       case UT_ENDPOINT:
48950 +               if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
48951 +                       ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48952 +                       if (ep == 0) {
48953 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48954 +                               return;
48955 +                       }
48956 +                       ep->stopped = 1;
48957 +                       dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
48958 +               }
48959 +               do_setup_in_status_phase(pcd);
48960 +               break;
48961 +       }
48962 +}
48963 +
48964 +/**
48965 + * This function process the CLEAR_FEATURE Setup Commands.
48966 + */
48967 +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
48968 +{
48969 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48970 +       dwc_otg_pcd_ep_t *ep = 0;
48971 +
48972 +       DWC_DEBUGPL(DBG_PCD,
48973 +                   "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48974 +                   ctrl.bmRequestType, ctrl.bRequest,
48975 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48976 +                   UGETW(ctrl.wLength));
48977 +
48978 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48979 +       case UT_DEVICE:
48980 +               switch (UGETW(ctrl.wValue)) {
48981 +               case UF_DEVICE_REMOTE_WAKEUP:
48982 +                       pcd->remote_wakeup_enable = 0;
48983 +                       break;
48984 +
48985 +               case UF_TEST_MODE:
48986 +                       /** @todo Add CLEAR_FEATURE for TEST modes. */
48987 +                       break;
48988 +
48989 +               default:
48990 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48991 +                       return;
48992 +               }
48993 +               do_setup_in_status_phase(pcd);
48994 +               break;
48995 +
48996 +       case UT_ENDPOINT:
48997 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48998 +               if (ep == 0) {
48999 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
49000 +                       return;
49001 +               }
49002 +
49003 +               pcd_clear_halt(pcd, ep);
49004 +
49005 +               break;
49006 +       }
49007 +}
49008 +
49009 +/**
49010 + * This function process the SET_ADDRESS Setup Commands.
49011 + */
49012 +static inline void do_set_address(dwc_otg_pcd_t * pcd)
49013 +{
49014 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
49015 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
49016 +
49017 +       if (ctrl.bmRequestType == UT_DEVICE) {
49018 +               dcfg_data_t dcfg = {.d32 = 0 };
49019 +
49020 +#ifdef DEBUG_EP0
49021 +//                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
49022 +#endif
49023 +               dcfg.b.devaddr = UGETW(ctrl.wValue);
49024 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
49025 +               do_setup_in_status_phase(pcd);
49026 +       }
49027 +}
49028 +
49029 +/**
49030 + *     This function processes SETUP commands. In Linux, the USB Command
49031 + *     processing is done in two places - the first being the PCD and the
49032 + *     second in the Gadget Driver (for example, the File-Backed Storage
49033 + *     Gadget Driver).
49034 + *
49035 + * <table>
49036 + * <tr><td>Command     </td><td>Driver </td><td>Description</td></tr>
49037 + *
49038 + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
49039 + * defined in chapter 9 of the USB 2.0 Specification chapter 9
49040 + * </td></tr>
49041 + *
49042 + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
49043 + * requests are the ENDPOINT_HALT feature is procesed, all others the
49044 + * interface requests are ignored.</td></tr>
49045 + *
49046 + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
49047 + * requests are processed by the PCD.  Interface requests are passed
49048 + * to the Gadget Driver.</td></tr>
49049 + *
49050 + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
49051 + * with device address received </td></tr>
49052 + *
49053 + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
49054 + * requested descriptor</td></tr>
49055 + *
49056 + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
49057 + * not implemented by any of the existing Gadget Drivers.</td></tr>
49058 + *
49059 + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
49060 + * all EPs and enable EPs for new configuration.</td></tr>
49061 + *
49062 + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
49063 + * the current configuration</td></tr>
49064 + *
49065 + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
49066 + * EPs and enable EPs for new configuration.</td></tr>
49067 + *
49068 + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
49069 + * current interface.</td></tr>
49070 + *
49071 + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
49072 + * message.</td></tr>
49073 + * </table>
49074 + *
49075 + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
49076 + * processed by pcd_setup. Calling the Function Driver's setup function from
49077 + * pcd_setup processes the gadget SETUP commands.
49078 + */
49079 +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
49080 +{
49081 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
49082 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49083 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
49084 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
49085 +
49086 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
49087 +
49088 +#ifdef DWC_UTE_CFI
49089 +       int retval = 0;
49090 +       struct cfi_usb_ctrlrequest cfi_req;
49091 +#endif
49092 +
49093 +       doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
49094 +
49095 +       /** In BDMA more then 1 setup packet is not supported till 3.00a */
49096 +       if (core_if->dma_enable && core_if->dma_desc_enable == 0
49097 +           && (doeptsize0.b.supcnt < 2)
49098 +           && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
49099 +               DWC_ERROR
49100 +                   ("\n\n-----------    CANNOT handle > 1 setup packet in DMA mode\n\n");
49101 +       }
49102 +       if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
49103 +           && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
49104 +               ctrl =
49105 +                   (pcd->setup_pkt +
49106 +                    (3 - doeptsize0.b.supcnt - 1 +
49107 +                     ep0->dwc_ep.stp_rollover))->req;
49108 +       }
49109 +#ifdef DEBUG_EP0
49110 +       DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
49111 +                   ctrl.bmRequestType, ctrl.bRequest,
49112 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
49113 +                   UGETW(ctrl.wLength));
49114 +#endif
49115 +
49116 +       /* Clean up the request queue */
49117 +       dwc_otg_request_nuke(ep0);
49118 +       ep0->stopped = 0;
49119 +
49120 +       if (ctrl.bmRequestType & UE_DIR_IN) {
49121 +               ep0->dwc_ep.is_in = 1;
49122 +               pcd->ep0state = EP0_IN_DATA_PHASE;
49123 +       } else {
49124 +               ep0->dwc_ep.is_in = 0;
49125 +               pcd->ep0state = EP0_OUT_DATA_PHASE;
49126 +       }
49127 +
49128 +       if (UGETW(ctrl.wLength) == 0) {
49129 +               ep0->dwc_ep.is_in = 1;
49130 +               pcd->ep0state = EP0_IN_STATUS_PHASE;
49131 +       }
49132 +
49133 +       if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
49134 +
49135 +#ifdef DWC_UTE_CFI
49136 +               DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
49137 +
49138 +               //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",
49139 +                               ctrl.bRequestType, ctrl.bRequest);
49140 +               if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
49141 +                       if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
49142 +                               retval = cfi_setup(pcd, &cfi_req);
49143 +                               if (retval < 0) {
49144 +                                       ep0_do_stall(pcd, retval);
49145 +                                       pcd->ep0_pending = 0;
49146 +                                       return;
49147 +                               }
49148 +
49149 +                               /* if need gadget setup then call it and check the retval */
49150 +                               if (pcd->cfi->need_gadget_att) {
49151 +                                       retval =
49152 +                                           cfi_gadget_setup(pcd,
49153 +                                                            &pcd->
49154 +                                                            cfi->ctrl_req);
49155 +                                       if (retval < 0) {
49156 +                                               pcd->ep0_pending = 0;
49157 +                                               return;
49158 +                                       }
49159 +                               }
49160 +
49161 +                               if (pcd->cfi->need_status_in_complete) {
49162 +                                       do_setup_in_status_phase(pcd);
49163 +                               }
49164 +                               return;
49165 +                       }
49166 +               }
49167 +#endif
49168 +
49169 +               /* handle non-standard (class/vendor) requests in the gadget driver */
49170 +               do_gadget_setup(pcd, &ctrl);
49171 +               return;
49172 +       }
49173 +
49174 +       /** @todo NGS: Handle bad setup packet? */
49175 +
49176 +///////////////////////////////////////////
49177 +//// --- Standard Request handling --- ////
49178 +
49179 +       switch (ctrl.bRequest) {
49180 +       case UR_GET_STATUS:
49181 +               do_get_status(pcd);
49182 +               break;
49183 +
49184 +       case UR_CLEAR_FEATURE:
49185 +               do_clear_feature(pcd);
49186 +               break;
49187 +
49188 +       case UR_SET_FEATURE:
49189 +               do_set_feature(pcd);
49190 +               break;
49191 +
49192 +       case UR_SET_ADDRESS:
49193 +               do_set_address(pcd);
49194 +               break;
49195 +
49196 +       case UR_SET_INTERFACE:
49197 +       case UR_SET_CONFIG:
49198 +//              _pcd->request_config = 1;       /* Configuration changed */
49199 +               do_gadget_setup(pcd, &ctrl);
49200 +               break;
49201 +
49202 +       case UR_SYNCH_FRAME:
49203 +               do_gadget_setup(pcd, &ctrl);
49204 +               break;
49205 +
49206 +       default:
49207 +               /* Call the Gadget Driver's setup functions */
49208 +               do_gadget_setup(pcd, &ctrl);
49209 +               break;
49210 +       }
49211 +}
49212 +
49213 +/**
49214 + * This function completes the ep0 control transfer.
49215 + */
49216 +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
49217 +{
49218 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49219 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49220 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49221 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49222 +#ifdef DEBUG_EP0
49223 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49224 +           dev_if->out_ep_regs[ep->dwc_ep.num];
49225 +#endif
49226 +       deptsiz0_data_t deptsiz;
49227 +       dev_dma_desc_sts_t desc_sts;
49228 +       dwc_otg_pcd_request_t *req;
49229 +       int is_last = 0;
49230 +       dwc_otg_pcd_t *pcd = ep->pcd;
49231 +
49232 +#ifdef DWC_UTE_CFI
49233 +       struct cfi_usb_ctrlrequest *ctrlreq;
49234 +       int retval = -DWC_E_NOT_SUPPORTED;
49235 +#endif
49236 +
49237 +        desc_sts.b.bytes = 0;
49238 +
49239 +       if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49240 +               if (ep->dwc_ep.is_in) {
49241 +#ifdef DEBUG_EP0
49242 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
49243 +#endif
49244 +                       do_setup_out_status_phase(pcd);
49245 +               } else {
49246 +#ifdef DEBUG_EP0
49247 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
49248 +#endif
49249 +
49250 +#ifdef DWC_UTE_CFI
49251 +                       ctrlreq = &pcd->cfi->ctrl_req;
49252 +
49253 +                       if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
49254 +                               if (ctrlreq->bRequest > 0xB0
49255 +                                   && ctrlreq->bRequest < 0xBF) {
49256 +
49257 +                                       /* Return if the PCD failed to handle the request */
49258 +                                       if ((retval =
49259 +                                            pcd->cfi->ops.
49260 +                                            ctrl_write_complete(pcd->cfi,
49261 +                                                                pcd)) < 0) {
49262 +                                               CFI_INFO
49263 +                                                   ("ERROR setting a new value in the PCD(%d)\n",
49264 +                                                    retval);
49265 +                                               ep0_do_stall(pcd, retval);
49266 +                                               pcd->ep0_pending = 0;
49267 +                                               return 0;
49268 +                                       }
49269 +
49270 +                                       /* If the gadget needs to be notified on the request */
49271 +                                       if (pcd->cfi->need_gadget_att == 1) {
49272 +                                               //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
49273 +                                               retval =
49274 +                                                   cfi_gadget_setup(pcd,
49275 +                                                                    &pcd->cfi->
49276 +                                                                    ctrl_req);
49277 +
49278 +                                               /* Return from the function if the gadget failed to process
49279 +                                                * the request properly - this should never happen !!!
49280 +                                                */
49281 +                                               if (retval < 0) {
49282 +                                                       CFI_INFO
49283 +                                                           ("ERROR setting a new value in the gadget(%d)\n",
49284 +                                                            retval);
49285 +                                                       pcd->ep0_pending = 0;
49286 +                                                       return 0;
49287 +                                               }
49288 +                                       }
49289 +
49290 +                                       CFI_INFO("%s: RETVAL=%d\n", __func__,
49291 +                                                retval);
49292 +                                       /* If we hit here then the PCD and the gadget has properly
49293 +                                        * handled the request - so send the ZLP IN to the host.
49294 +                                        */
49295 +                                       /* @todo: MAS - decide whether we need to start the setup
49296 +                                        * stage based on the need_setup value of the cfi object
49297 +                                        */
49298 +                                       do_setup_in_status_phase(pcd);
49299 +                                       pcd->ep0_pending = 0;
49300 +                                       return 1;
49301 +                               }
49302 +                       }
49303 +#endif
49304 +
49305 +                       do_setup_in_status_phase(pcd);
49306 +               }
49307 +               pcd->ep0_pending = 0;
49308 +               return 1;
49309 +       }
49310 +
49311 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49312 +               return 0;
49313 +       }
49314 +       req = DWC_CIRCLEQ_FIRST(&ep->queue);
49315 +
49316 +       if (pcd->ep0state == EP0_OUT_STATUS_PHASE
49317 +           || pcd->ep0state == EP0_IN_STATUS_PHASE) {
49318 +               is_last = 1;
49319 +       } else if (ep->dwc_ep.is_in) {
49320 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49321 +               if (core_if->dma_desc_enable != 0)
49322 +                       desc_sts = dev_if->in_desc_addr->status;
49323 +#ifdef DEBUG_EP0
49324 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",
49325 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49326 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49327 +#endif
49328 +
49329 +               if (((core_if->dma_desc_enable == 0)
49330 +                    && (deptsiz.b.xfersize == 0))
49331 +                   || ((core_if->dma_desc_enable != 0)
49332 +                       && (desc_sts.b.bytes == 0))) {
49333 +                       req->actual = ep->dwc_ep.xfer_count;
49334 +                       /* Is a Zero Len Packet needed? */
49335 +                       if (req->sent_zlp) {
49336 +#ifdef DEBUG_EP0
49337 +                               DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
49338 +#endif
49339 +                               req->sent_zlp = 0;
49340 +                       }
49341 +                       do_setup_out_status_phase(pcd);
49342 +               }
49343 +       } else {
49344 +               /* ep0-OUT */
49345 +#ifdef DEBUG_EP0
49346 +               deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
49347 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
49348 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49349 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49350 +#endif
49351 +               req->actual = ep->dwc_ep.xfer_count;
49352 +
49353 +               /* Is a Zero Len Packet needed? */
49354 +               if (req->sent_zlp) {
49355 +#ifdef DEBUG_EP0
49356 +                       DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
49357 +#endif
49358 +                       req->sent_zlp = 0;
49359 +               }
49360 +               /* For older cores do setup in status phase in Slave/BDMA modes,
49361 +                * starting from 3.00 do that only in slave, and for DMA modes
49362 +                * just re-enable ep 0 OUT here*/
49363 +               if (core_if->dma_enable == 0
49364 +                   || (core_if->dma_desc_enable == 0
49365 +                       && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
49366 +                       do_setup_in_status_phase(pcd);
49367 +               } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
49368 +                       DWC_DEBUGPL(DBG_PCDV,
49369 +                                   "Enable out ep before in status phase\n");
49370 +                       ep0_out_start(core_if, pcd);
49371 +               }
49372 +       }
49373 +
49374 +       /* Complete the request */
49375 +       if (is_last) {
49376 +               dwc_otg_request_done(ep, req, 0);
49377 +               ep->dwc_ep.start_xfer_buff = 0;
49378 +               ep->dwc_ep.xfer_buff = 0;
49379 +               ep->dwc_ep.xfer_len = 0;
49380 +               return 1;
49381 +       }
49382 +       return 0;
49383 +}
49384 +
49385 +#ifdef DWC_UTE_CFI
49386 +/**
49387 + * This function calculates traverses all the CFI DMA descriptors and
49388 + * and accumulates the bytes that are left to be transfered.
49389 + *
49390 + * @return The total bytes left to transfered, or a negative value as failure
49391 + */
49392 +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
49393 +{
49394 +       int32_t ret = 0;
49395 +       int i;
49396 +       struct dwc_otg_dma_desc *ddesc = NULL;
49397 +       struct cfi_ep *cfiep;
49398 +
49399 +       /* See if the pcd_ep has its respective cfi_ep mapped */
49400 +       cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
49401 +       if (!cfiep) {
49402 +               CFI_INFO("%s: Failed to find ep\n", __func__);
49403 +               return -1;
49404 +       }
49405 +
49406 +       ddesc = ep->dwc_ep.descs;
49407 +
49408 +       for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
49409 +
49410 +#if defined(PRINT_CFI_DMA_DESCS)
49411 +               print_desc(ddesc, ep->ep.name, i);
49412 +#endif
49413 +               ret += ddesc->status.b.bytes;
49414 +               ddesc++;
49415 +       }
49416 +
49417 +       if (ret)
49418 +               CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
49419 +                        ret);
49420 +
49421 +       return ret;
49422 +}
49423 +#endif
49424 +
49425 +/**
49426 + * This function completes the request for the EP. If there are
49427 + * additional requests for the EP in the queue they will be started.
49428 + */
49429 +static void complete_ep(dwc_otg_pcd_ep_t * ep)
49430 +{
49431 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49432 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49433 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49434 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49435 +       deptsiz_data_t deptsiz;
49436 +       dev_dma_desc_sts_t desc_sts;
49437 +       dwc_otg_pcd_request_t *req = 0;
49438 +       dwc_otg_dev_dma_desc_t *dma_desc;
49439 +       uint32_t byte_count = 0;
49440 +       int is_last = 0;
49441 +       int i;
49442 +
49443 +       DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
49444 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"));
49445 +
49446 +       /* Get any pending requests */
49447 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49448 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
49449 +               if (!req) {
49450 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
49451 +                       return;
49452 +               }
49453 +       } else {
49454 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
49455 +               return;
49456 +       }
49457 +
49458 +       DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
49459 +
49460 +       if (ep->dwc_ep.is_in) {
49461 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49462 +
49463 +               if (core_if->dma_enable) {
49464 +                       if (core_if->dma_desc_enable == 0) {
49465 +                               if (deptsiz.b.xfersize == 0
49466 +                                   && deptsiz.b.pktcnt == 0) {
49467 +                                       byte_count =
49468 +                                           ep->dwc_ep.xfer_len -
49469 +                                           ep->dwc_ep.xfer_count;
49470 +
49471 +                                       ep->dwc_ep.xfer_buff += byte_count;
49472 +                                       ep->dwc_ep.dma_addr += byte_count;
49473 +                                       ep->dwc_ep.xfer_count += byte_count;
49474 +
49475 +                                       DWC_DEBUGPL(DBG_PCDV,
49476 +                                                   "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49477 +                                                   ep->dwc_ep.num,
49478 +                                                   (ep->dwc_ep.
49479 +                                                    is_in ? "IN" : "OUT"),
49480 +                                                   ep->dwc_ep.xfer_len,
49481 +                                                   deptsiz.b.xfersize,
49482 +                                                   deptsiz.b.pktcnt);
49483 +
49484 +                                       if (ep->dwc_ep.xfer_len <
49485 +                                           ep->dwc_ep.total_len) {
49486 +                                               dwc_otg_ep_start_transfer
49487 +                                                   (core_if, &ep->dwc_ep);
49488 +                                       } else if (ep->dwc_ep.sent_zlp) {
49489 +                                               /*
49490 +                                                * This fragment of code should initiate 0
49491 +                                                * length transfer in case if it is queued
49492 +                                                * a transfer with size divisible to EPs max
49493 +                                                * packet size and with usb_request zero field
49494 +                                                * is set, which means that after data is transfered,
49495 +                                                * it is also should be transfered
49496 +                                                * a 0 length packet at the end. For Slave and
49497 +                                                * Buffer DMA modes in this case SW has
49498 +                                                * to initiate 2 transfers one with transfer size,
49499 +                                                * and the second with 0 size. For Descriptor
49500 +                                                * DMA mode SW is able to initiate a transfer,
49501 +                                                * which will handle all the packets including
49502 +                                                * the last  0 length.
49503 +                                                */
49504 +                                               ep->dwc_ep.sent_zlp = 0;
49505 +                                               dwc_otg_ep_start_zl_transfer
49506 +                                                   (core_if, &ep->dwc_ep);
49507 +                                       } else {
49508 +                                               is_last = 1;
49509 +                                       }
49510 +                               } else {
49511 +                                       if (ep->dwc_ep.type ==
49512 +                                           DWC_OTG_EP_TYPE_ISOC) {
49513 +                                               req->actual = 0;
49514 +                                               dwc_otg_request_done(ep, req, 0);
49515 +
49516 +                                               ep->dwc_ep.start_xfer_buff = 0;
49517 +                                               ep->dwc_ep.xfer_buff = 0;
49518 +                                               ep->dwc_ep.xfer_len = 0;
49519 +
49520 +                                               /* If there is a request in the queue start it. */
49521 +                                               start_next_request(ep);
49522 +                                       } else
49523 +                                               DWC_WARN
49524 +                                               ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
49525 +                                               ep->dwc_ep.num,
49526 +                                               (ep->dwc_ep.is_in ? "IN" : "OUT"),
49527 +                                               deptsiz.b.xfersize,
49528 +                                               deptsiz.b.pktcnt);
49529 +                               }
49530 +                       } else {
49531 +                               dma_desc = ep->dwc_ep.desc_addr;
49532 +                               byte_count = 0;
49533 +                               ep->dwc_ep.sent_zlp = 0;
49534 +
49535 +#ifdef DWC_UTE_CFI
49536 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49537 +                                        ep->dwc_ep.buff_mode);
49538 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49539 +                                       int residue;
49540 +
49541 +                                       residue = cfi_calc_desc_residue(ep);
49542 +                                       if (residue < 0)
49543 +                                               return;
49544 +
49545 +                                       byte_count = residue;
49546 +                               } else {
49547 +#endif
49548 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49549 +                                            ++i) {
49550 +                                       desc_sts = dma_desc->status;
49551 +                                       byte_count += desc_sts.b.bytes;
49552 +                                       dma_desc++;
49553 +                               }
49554 +#ifdef DWC_UTE_CFI
49555 +                               }
49556 +#endif
49557 +                               if (byte_count == 0) {
49558 +                                       ep->dwc_ep.xfer_count =
49559 +                                           ep->dwc_ep.total_len;
49560 +                                       is_last = 1;
49561 +                               } else {
49562 +                                       DWC_WARN("Incomplete transfer\n");
49563 +                               }
49564 +                       }
49565 +               } else {
49566 +                       if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
49567 +                               DWC_DEBUGPL(DBG_PCDV,
49568 +                                           "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49569 +                                           ep->dwc_ep.num,
49570 +                                           ep->dwc_ep.is_in ? "IN" : "OUT",
49571 +                                           ep->dwc_ep.xfer_len,
49572 +                                           deptsiz.b.xfersize,
49573 +                                           deptsiz.b.pktcnt);
49574 +
49575 +                               /*      Check if the whole transfer was completed,
49576 +                                *      if no, setup transfer for next portion of data
49577 +                                */
49578 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49579 +                                       dwc_otg_ep_start_transfer(core_if,
49580 +                                                                 &ep->dwc_ep);
49581 +                               } else if (ep->dwc_ep.sent_zlp) {
49582 +                                       /*
49583 +                                        * This fragment of code should initiate 0
49584 +                                        * length trasfer in case if it is queued
49585 +                                        * a trasfer with size divisible to EPs max
49586 +                                        * packet size and with usb_request zero field
49587 +                                        * is set, which means that after data is transfered,
49588 +                                        * it is also should be transfered
49589 +                                        * a 0 length packet at the end. For Slave and
49590 +                                        * Buffer DMA modes in this case SW has
49591 +                                        * to initiate 2 transfers one with transfer size,
49592 +                                        * and the second with 0 size. For Desriptor
49593 +                                        * DMA mode SW is able to initiate a transfer,
49594 +                                        * which will handle all the packets including
49595 +                                        * the last  0 legth.
49596 +                                        */
49597 +                                       ep->dwc_ep.sent_zlp = 0;
49598 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49599 +                                                                    &ep->dwc_ep);
49600 +                               } else {
49601 +                                       is_last = 1;
49602 +                               }
49603 +                       } else {
49604 +                               DWC_WARN
49605 +                                   ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
49606 +                                    ep->dwc_ep.num,
49607 +                                    (ep->dwc_ep.is_in ? "IN" : "OUT"),
49608 +                                    deptsiz.b.xfersize, deptsiz.b.pktcnt);
49609 +                       }
49610 +               }
49611 +       } else {
49612 +               dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49613 +                   dev_if->out_ep_regs[ep->dwc_ep.num];
49614 +               desc_sts.d32 = 0;
49615 +               if (core_if->dma_enable) {
49616 +                       if (core_if->dma_desc_enable) {
49617 +                               dma_desc = ep->dwc_ep.desc_addr;
49618 +                               byte_count = 0;
49619 +                               ep->dwc_ep.sent_zlp = 0;
49620 +
49621 +#ifdef DWC_UTE_CFI
49622 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49623 +                                        ep->dwc_ep.buff_mode);
49624 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49625 +                                       int residue;
49626 +                                       residue = cfi_calc_desc_residue(ep);
49627 +                                       if (residue < 0)
49628 +                                               return;
49629 +                                       byte_count = residue;
49630 +                               } else {
49631 +#endif
49632 +
49633 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49634 +                                            ++i) {
49635 +                                               desc_sts = dma_desc->status;
49636 +                                               byte_count += desc_sts.b.bytes;
49637 +                                               dma_desc++;
49638 +                                       }
49639 +
49640 +#ifdef DWC_UTE_CFI
49641 +                               }
49642 +#endif
49643 +                               /* Checking for interrupt Out transfers with not
49644 +                                * dword aligned mps sizes
49645 +                                */
49646 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
49647 +                                                       (ep->dwc_ep.maxpacket%4)) {
49648 +                                       ep->dwc_ep.xfer_count =
49649 +                                           ep->dwc_ep.total_len - byte_count;
49650 +                                       if ((ep->dwc_ep.xfer_len %
49651 +                                            ep->dwc_ep.maxpacket)
49652 +                                           && (ep->dwc_ep.xfer_len /
49653 +                                               ep->dwc_ep.maxpacket <
49654 +                                               MAX_DMA_DESC_CNT))
49655 +                                               ep->dwc_ep.xfer_len -=
49656 +                                                   (ep->dwc_ep.desc_cnt -
49657 +                                                    1) * ep->dwc_ep.maxpacket +
49658 +                                                   ep->dwc_ep.xfer_len %
49659 +                                                   ep->dwc_ep.maxpacket;
49660 +                                       else
49661 +                                               ep->dwc_ep.xfer_len -=
49662 +                                                   ep->dwc_ep.desc_cnt *
49663 +                                                   ep->dwc_ep.maxpacket;
49664 +                                       if (ep->dwc_ep.xfer_len > 0) {
49665 +                                               dwc_otg_ep_start_transfer
49666 +                                                   (core_if, &ep->dwc_ep);
49667 +                                       } else {
49668 +                                               is_last = 1;
49669 +                                       }
49670 +                               } else {
49671 +                                       ep->dwc_ep.xfer_count =
49672 +                                           ep->dwc_ep.total_len - byte_count +
49673 +                                           ((4 -
49674 +                                             (ep->dwc_ep.
49675 +                                              total_len & 0x3)) & 0x3);
49676 +                                       is_last = 1;
49677 +                               }
49678 +                       } else {
49679 +                               deptsiz.d32 = 0;
49680 +                               deptsiz.d32 =
49681 +                                   DWC_READ_REG32(&out_ep_regs->doeptsiz);
49682 +
49683 +                               byte_count = (ep->dwc_ep.xfer_len -
49684 +                                             ep->dwc_ep.xfer_count -
49685 +                                             deptsiz.b.xfersize);
49686 +                               ep->dwc_ep.xfer_buff += byte_count;
49687 +                               ep->dwc_ep.dma_addr += byte_count;
49688 +                               ep->dwc_ep.xfer_count += byte_count;
49689 +
49690 +                               /*      Check if the whole transfer was completed,
49691 +                                *      if no, setup transfer for next portion of data
49692 +                                */
49693 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49694 +                                       dwc_otg_ep_start_transfer(core_if,
49695 +                                                                 &ep->dwc_ep);
49696 +                               } else if (ep->dwc_ep.sent_zlp) {
49697 +                                       /*
49698 +                                        * This fragment of code should initiate 0
49699 +                                        * length trasfer in case if it is queued
49700 +                                        * a trasfer with size divisible to EPs max
49701 +                                        * packet size and with usb_request zero field
49702 +                                        * is set, which means that after data is transfered,
49703 +                                        * it is also should be transfered
49704 +                                        * a 0 length packet at the end. For Slave and
49705 +                                        * Buffer DMA modes in this case SW has
49706 +                                        * to initiate 2 transfers one with transfer size,
49707 +                                        * and the second with 0 size. For Desriptor
49708 +                                        * DMA mode SW is able to initiate a transfer,
49709 +                                        * which will handle all the packets including
49710 +                                        * the last  0 legth.
49711 +                                        */
49712 +                                       ep->dwc_ep.sent_zlp = 0;
49713 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49714 +                                                                    &ep->dwc_ep);
49715 +                               } else {
49716 +                                       is_last = 1;
49717 +                               }
49718 +                       }
49719 +               } else {
49720 +                       /*      Check if the whole transfer was completed,
49721 +                        *      if no, setup transfer for next portion of data
49722 +                        */
49723 +                       if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49724 +                               dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
49725 +                       } else if (ep->dwc_ep.sent_zlp) {
49726 +                               /*
49727 +                                * This fragment of code should initiate 0
49728 +                                * length transfer in case if it is queued
49729 +                                * a transfer with size divisible to EPs max
49730 +                                * packet size and with usb_request zero field
49731 +                                * is set, which means that after data is transfered,
49732 +                                * it is also should be transfered
49733 +                                * a 0 length packet at the end. For Slave and
49734 +                                * Buffer DMA modes in this case SW has
49735 +                                * to initiate 2 transfers one with transfer size,
49736 +                                * and the second with 0 size. For Descriptor
49737 +                                * DMA mode SW is able to initiate a transfer,
49738 +                                * which will handle all the packets including
49739 +                                * the last  0 length.
49740 +                                */
49741 +                               ep->dwc_ep.sent_zlp = 0;
49742 +                               dwc_otg_ep_start_zl_transfer(core_if,
49743 +                                                            &ep->dwc_ep);
49744 +                       } else {
49745 +                               is_last = 1;
49746 +                       }
49747 +               }
49748 +
49749 +               DWC_DEBUGPL(DBG_PCDV,
49750 +                           "addr %p,    %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
49751 +                           &out_ep_regs->doeptsiz, ep->dwc_ep.num,
49752 +                           ep->dwc_ep.is_in ? "IN" : "OUT",
49753 +                           ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
49754 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49755 +       }
49756 +
49757 +       /* Complete the request */
49758 +       if (is_last) {
49759 +#ifdef DWC_UTE_CFI
49760 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49761 +                       req->actual = ep->dwc_ep.cfi_req_len - byte_count;
49762 +               } else {
49763 +#endif
49764 +                       req->actual = ep->dwc_ep.xfer_count;
49765 +#ifdef DWC_UTE_CFI
49766 +               }
49767 +#endif
49768 +               if (req->dw_align_buf) {
49769 +                       if (!ep->dwc_ep.is_in) {
49770 +                               dwc_memcpy(req->buf, req->dw_align_buf, req->length);
49771 +                       }
49772 +                       DWC_DMA_FREE(req->length, req->dw_align_buf,
49773 +                                    req->dw_align_buf_dma);
49774 +               }
49775 +
49776 +               dwc_otg_request_done(ep, req, 0);
49777 +
49778 +               ep->dwc_ep.start_xfer_buff = 0;
49779 +               ep->dwc_ep.xfer_buff = 0;
49780 +               ep->dwc_ep.xfer_len = 0;
49781 +
49782 +               /* If there is a request in the queue start it. */
49783 +               start_next_request(ep);
49784 +       }
49785 +}
49786 +
49787 +#ifdef DWC_EN_ISOC
49788 +
49789 +/**
49790 + * This function BNA interrupt for Isochronous EPs
49791 + *
49792 + */
49793 +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
49794 +{
49795 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
49796 +       volatile uint32_t *addr;
49797 +       depctl_data_t depctl = {.d32 = 0 };
49798 +       dwc_otg_pcd_t *pcd = ep->pcd;
49799 +       dwc_otg_dev_dma_desc_t *dma_desc;
49800 +       int i;
49801 +
49802 +       dma_desc =
49803 +           dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
49804 +
49805 +       if (dwc_ep->is_in) {
49806 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49807 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49808 +                       sts.d32 = dma_desc->status.d32;
49809 +                       sts.b_iso_in.bs = BS_HOST_READY;
49810 +                       dma_desc->status.d32 = sts.d32;
49811 +               }
49812 +       } else {
49813 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49814 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49815 +                       sts.d32 = dma_desc->status.d32;
49816 +                       sts.b_iso_out.bs = BS_HOST_READY;
49817 +                       dma_desc->status.d32 = sts.d32;
49818 +               }
49819 +       }
49820 +
49821 +       if (dwc_ep->is_in == 0) {
49822 +               addr =
49823 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
49824 +                                                          num]->doepctl;
49825 +       } else {
49826 +               addr =
49827 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
49828 +       }
49829 +       depctl.b.epena = 1;
49830 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
49831 +}
49832 +
49833 +/**
49834 + * This function sets latest iso packet information(non-PTI mode)
49835 + *
49836 + * @param core_if Programming view of DWC_otg controller.
49837 + * @param ep The EP to start the transfer on.
49838 + *
49839 + */
49840 +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
49841 +{
49842 +       deptsiz_data_t deptsiz = {.d32 = 0 };
49843 +       dma_addr_t dma_addr;
49844 +       uint32_t offset;
49845 +
49846 +       if (ep->proc_buf_num)
49847 +               dma_addr = ep->dma_addr1;
49848 +       else
49849 +               dma_addr = ep->dma_addr0;
49850 +
49851 +       if (ep->is_in) {
49852 +               deptsiz.d32 =
49853 +                   DWC_READ_REG32(&core_if->dev_if->
49854 +                                  in_ep_regs[ep->num]->dieptsiz);
49855 +               offset = ep->data_per_frame;
49856 +       } else {
49857 +               deptsiz.d32 =
49858 +                   DWC_READ_REG32(&core_if->dev_if->
49859 +                                  out_ep_regs[ep->num]->doeptsiz);
49860 +               offset =
49861 +                   ep->data_per_frame +
49862 +                   (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
49863 +       }
49864 +
49865 +       if (!deptsiz.b.xfersize) {
49866 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49867 +               ep->pkt_info[ep->cur_pkt].offset =
49868 +                   ep->cur_pkt_dma_addr - dma_addr;
49869 +               ep->pkt_info[ep->cur_pkt].status = 0;
49870 +       } else {
49871 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49872 +               ep->pkt_info[ep->cur_pkt].offset =
49873 +                   ep->cur_pkt_dma_addr - dma_addr;
49874 +               ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
49875 +       }
49876 +       ep->cur_pkt_addr += offset;
49877 +       ep->cur_pkt_dma_addr += offset;
49878 +       ep->cur_pkt++;
49879 +}
49880 +
49881 +/**
49882 + * This function sets latest iso packet information(DDMA mode)
49883 + *
49884 + * @param core_if Programming view of DWC_otg controller.
49885 + * @param dwc_ep The EP to start the transfer on.
49886 + *
49887 + */
49888 +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
49889 +                                  dwc_ep_t * dwc_ep)
49890 +{
49891 +       dwc_otg_dev_dma_desc_t *dma_desc;
49892 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
49893 +       iso_pkt_info_t *iso_packet;
49894 +       uint32_t data_per_desc;
49895 +       uint32_t offset;
49896 +       int i, j;
49897 +
49898 +       iso_packet = dwc_ep->pkt_info;
49899 +
49900 +       /** Reinit closed DMA Descriptors*/
49901 +       /** ISO OUT EP */
49902 +       if (dwc_ep->is_in == 0) {
49903 +               dma_desc =
49904 +                   dwc_ep->iso_desc_addr +
49905 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49906 +               offset = 0;
49907 +
49908 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
49909 +                    i += dwc_ep->pkt_per_frm) {
49910 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
49911 +                               data_per_desc =
49912 +                                   ((j + 1) * dwc_ep->maxpacket >
49913 +                                    dwc_ep->
49914 +                                    data_per_frame) ? dwc_ep->data_per_frame -
49915 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49916 +                               data_per_desc +=
49917 +                                   (data_per_desc % 4) ? (4 -
49918 +                                                          data_per_desc %
49919 +                                                          4) : 0;
49920 +
49921 +                               sts.d32 = dma_desc->status.d32;
49922 +
49923 +                               /* Write status in iso_packet_decsriptor  */
49924 +                               iso_packet->status =
49925 +                                   sts.b_iso_out.rxsts +
49926 +                                   (sts.b_iso_out.bs ^ BS_DMA_DONE);
49927 +                               if (iso_packet->status) {
49928 +                                       iso_packet->status = -DWC_E_NO_DATA;
49929 +                               }
49930 +
49931 +                               /* Received data length */
49932 +                               if (!sts.b_iso_out.rxbytes) {
49933 +                                       iso_packet->length =
49934 +                                           data_per_desc -
49935 +                                           sts.b_iso_out.rxbytes;
49936 +                               } else {
49937 +                                       iso_packet->length =
49938 +                                           data_per_desc -
49939 +                                           sts.b_iso_out.rxbytes + (4 -
49940 +                                                                    dwc_ep->data_per_frame
49941 +                                                                    % 4);
49942 +                               }
49943 +
49944 +                               iso_packet->offset = offset;
49945 +
49946 +                               offset += data_per_desc;
49947 +                               dma_desc++;
49948 +                               iso_packet++;
49949 +                       }
49950 +               }
49951 +
49952 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
49953 +                       data_per_desc =
49954 +                           ((j + 1) * dwc_ep->maxpacket >
49955 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49956 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49957 +                       data_per_desc +=
49958 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49959 +
49960 +                       sts.d32 = dma_desc->status.d32;
49961 +
49962 +                       /* Write status in iso_packet_decsriptor  */
49963 +                       iso_packet->status =
49964 +                           sts.b_iso_out.rxsts +
49965 +                           (sts.b_iso_out.bs ^ BS_DMA_DONE);
49966 +                       if (iso_packet->status) {
49967 +                               iso_packet->status = -DWC_E_NO_DATA;
49968 +                       }
49969 +
49970 +                       /* Received data length */
49971 +                       iso_packet->length =
49972 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49973 +
49974 +                       iso_packet->offset = offset;
49975 +
49976 +                       offset += data_per_desc;
49977 +                       iso_packet++;
49978 +                       dma_desc++;
49979 +               }
49980 +
49981 +               sts.d32 = dma_desc->status.d32;
49982 +
49983 +               /* Write status in iso_packet_decsriptor  */
49984 +               iso_packet->status =
49985 +                   sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
49986 +               if (iso_packet->status) {
49987 +                       iso_packet->status = -DWC_E_NO_DATA;
49988 +               }
49989 +               /* Received data length */
49990 +               if (!sts.b_iso_out.rxbytes) {
49991 +                       iso_packet->length =
49992 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49993 +               } else {
49994 +                       iso_packet->length =
49995 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
49996 +                           (4 - dwc_ep->data_per_frame % 4);
49997 +               }
49998 +
49999 +               iso_packet->offset = offset;
50000 +       } else {
50001 +/** ISO IN EP */
50002 +
50003 +               dma_desc =
50004 +                   dwc_ep->iso_desc_addr +
50005 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50006 +
50007 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50008 +                       sts.d32 = dma_desc->status.d32;
50009 +
50010 +                       /* Write status in iso packet descriptor */
50011 +                       iso_packet->status =
50012 +                           sts.b_iso_in.txsts +
50013 +                           (sts.b_iso_in.bs ^ BS_DMA_DONE);
50014 +                       if (iso_packet->status != 0) {
50015 +                               iso_packet->status = -DWC_E_NO_DATA;
50016 +
50017 +                       }
50018 +                       /* Bytes has been transfered */
50019 +                       iso_packet->length =
50020 +                           dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
50021 +
50022 +                       dma_desc++;
50023 +                       iso_packet++;
50024 +               }
50025 +
50026 +               sts.d32 = dma_desc->status.d32;
50027 +               while (sts.b_iso_in.bs == BS_DMA_BUSY) {
50028 +                       sts.d32 = dma_desc->status.d32;
50029 +               }
50030 +
50031 +               /* Write status in iso packet descriptor ??? do be done with ERROR codes */
50032 +               iso_packet->status =
50033 +                   sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
50034 +               if (iso_packet->status != 0) {
50035 +                       iso_packet->status = -DWC_E_NO_DATA;
50036 +               }
50037 +
50038 +               /* Bytes has been transfered */
50039 +               iso_packet->length =
50040 +                   dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
50041 +       }
50042 +}
50043 +
50044 +/**
50045 + * This function reinitialize DMA Descriptors for Isochronous transfer
50046 + *
50047 + * @param core_if Programming view of DWC_otg controller.
50048 + * @param dwc_ep The EP to start the transfer on.
50049 + *
50050 + */
50051 +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
50052 +{
50053 +       int i, j;
50054 +       dwc_otg_dev_dma_desc_t *dma_desc;
50055 +       dma_addr_t dma_ad;
50056 +       volatile uint32_t *addr;
50057 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
50058 +       uint32_t data_per_desc;
50059 +
50060 +       if (dwc_ep->is_in == 0) {
50061 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
50062 +       } else {
50063 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50064 +       }
50065 +
50066 +       if (dwc_ep->proc_buf_num == 0) {
50067 +               /** Buffer 0 descriptors setup */
50068 +               dma_ad = dwc_ep->dma_addr0;
50069 +       } else {
50070 +               /** Buffer 1 descriptors setup */
50071 +               dma_ad = dwc_ep->dma_addr1;
50072 +       }
50073 +
50074 +       /** Reinit closed DMA Descriptors*/
50075 +       /** ISO OUT EP */
50076 +       if (dwc_ep->is_in == 0) {
50077 +               dma_desc =
50078 +                   dwc_ep->iso_desc_addr +
50079 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50080 +
50081 +               sts.b_iso_out.bs = BS_HOST_READY;
50082 +               sts.b_iso_out.rxsts = 0;
50083 +               sts.b_iso_out.l = 0;
50084 +               sts.b_iso_out.sp = 0;
50085 +               sts.b_iso_out.ioc = 0;
50086 +               sts.b_iso_out.pid = 0;
50087 +               sts.b_iso_out.framenum = 0;
50088 +
50089 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
50090 +                    i += dwc_ep->pkt_per_frm) {
50091 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
50092 +                               data_per_desc =
50093 +                                   ((j + 1) * dwc_ep->maxpacket >
50094 +                                    dwc_ep->
50095 +                                    data_per_frame) ? dwc_ep->data_per_frame -
50096 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50097 +                               data_per_desc +=
50098 +                                   (data_per_desc % 4) ? (4 -
50099 +                                                          data_per_desc %
50100 +                                                          4) : 0;
50101 +                               sts.b_iso_out.rxbytes = data_per_desc;
50102 +                               dma_desc->buf = dma_ad;
50103 +                               dma_desc->status.d32 = sts.d32;
50104 +
50105 +                               dma_ad += data_per_desc;
50106 +                               dma_desc++;
50107 +                       }
50108 +               }
50109 +
50110 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
50111 +
50112 +                       data_per_desc =
50113 +                           ((j + 1) * dwc_ep->maxpacket >
50114 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50115 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50116 +                       data_per_desc +=
50117 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50118 +                       sts.b_iso_out.rxbytes = data_per_desc;
50119 +
50120 +                       dma_desc->buf = dma_ad;
50121 +                       dma_desc->status.d32 = sts.d32;
50122 +
50123 +                       dma_desc++;
50124 +                       dma_ad += data_per_desc;
50125 +               }
50126 +
50127 +               sts.b_iso_out.ioc = 1;
50128 +               sts.b_iso_out.l = dwc_ep->proc_buf_num;
50129 +
50130 +               data_per_desc =
50131 +                   ((j + 1) * dwc_ep->maxpacket >
50132 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
50133 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
50134 +               data_per_desc +=
50135 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
50136 +               sts.b_iso_out.rxbytes = data_per_desc;
50137 +
50138 +               dma_desc->buf = dma_ad;
50139 +               dma_desc->status.d32 = sts.d32;
50140 +       } else {
50141 +/** ISO IN EP */
50142 +
50143 +               dma_desc =
50144 +                   dwc_ep->iso_desc_addr +
50145 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
50146 +
50147 +               sts.b_iso_in.bs = BS_HOST_READY;
50148 +               sts.b_iso_in.txsts = 0;
50149 +               sts.b_iso_in.sp = 0;
50150 +               sts.b_iso_in.ioc = 0;
50151 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
50152 +               sts.b_iso_in.framenum = dwc_ep->next_frame;
50153 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
50154 +               sts.b_iso_in.l = 0;
50155 +
50156 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50157 +                       dma_desc->buf = dma_ad;
50158 +                       dma_desc->status.d32 = sts.d32;
50159 +
50160 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
50161 +                       dma_ad += dwc_ep->data_per_frame;
50162 +                       dma_desc++;
50163 +               }
50164 +
50165 +               sts.b_iso_in.ioc = 1;
50166 +               sts.b_iso_in.l = dwc_ep->proc_buf_num;
50167 +
50168 +               dma_desc->buf = dma_ad;
50169 +               dma_desc->status.d32 = sts.d32;
50170 +
50171 +               dwc_ep->next_frame =
50172 +                   sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
50173 +       }
50174 +       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50175 +}
50176 +
50177 +/**
50178 + * This function is to handle Iso EP transfer complete interrupt
50179 + * in case Iso out packet was dropped
50180 + *
50181 + * @param core_if Programming view of DWC_otg controller.
50182 + * @param dwc_ep The EP for wihich transfer complete was asserted
50183 + *
50184 + */
50185 +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
50186 +                                          dwc_ep_t * dwc_ep)
50187 +{
50188 +       uint32_t dma_addr;
50189 +       uint32_t drp_pkt;
50190 +       uint32_t drp_pkt_cnt;
50191 +       deptsiz_data_t deptsiz = {.d32 = 0 };
50192 +       depctl_data_t depctl = {.d32 = 0 };
50193 +       int i;
50194 +
50195 +       deptsiz.d32 =
50196 +           DWC_READ_REG32(&core_if->dev_if->
50197 +                          out_ep_regs[dwc_ep->num]->doeptsiz);
50198 +
50199 +       drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
50200 +       drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
50201 +
50202 +       /* Setting dropped packets status */
50203 +       for (i = 0; i < drp_pkt_cnt; ++i) {
50204 +               dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
50205 +               drp_pkt++;
50206 +               deptsiz.b.pktcnt--;
50207 +       }
50208 +
50209 +       if (deptsiz.b.pktcnt > 0) {
50210 +               deptsiz.b.xfersize =
50211 +                   dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
50212 +                                       deptsiz.b.pktcnt) * dwc_ep->maxpacket;
50213 +       } else {
50214 +               deptsiz.b.xfersize = 0;
50215 +               deptsiz.b.pktcnt = 0;
50216 +       }
50217 +
50218 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
50219 +                       deptsiz.d32);
50220 +
50221 +       if (deptsiz.b.pktcnt > 0) {
50222 +               if (dwc_ep->proc_buf_num) {
50223 +                       dma_addr =
50224 +                           dwc_ep->dma_addr1 + dwc_ep->xfer_len -
50225 +                           deptsiz.b.xfersize;
50226 +               } else {
50227 +                       dma_addr =
50228 +                           dwc_ep->dma_addr0 + dwc_ep->xfer_len -
50229 +                           deptsiz.b.xfersize;;
50230 +               }
50231 +
50232 +               DWC_WRITE_REG32(&core_if->dev_if->
50233 +                               out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
50234 +
50235 +               /** Re-enable endpoint, clear nak  */
50236 +               depctl.d32 = 0;
50237 +               depctl.b.epena = 1;
50238 +               depctl.b.cnak = 1;
50239 +
50240 +               DWC_MODIFY_REG32(&core_if->dev_if->
50241 +                                out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
50242 +                                depctl.d32);
50243 +               return 0;
50244 +       } else {
50245 +               return 1;
50246 +       }
50247 +}
50248 +
50249 +/**
50250 + * This function sets iso packets information(PTI mode)
50251 + *
50252 + * @param core_if Programming view of DWC_otg controller.
50253 + * @param ep The EP to start the transfer on.
50254 + *
50255 + */
50256 +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
50257 +{
50258 +       int i, j;
50259 +       dma_addr_t dma_ad;
50260 +       iso_pkt_info_t *packet_info = ep->pkt_info;
50261 +       uint32_t offset;
50262 +       uint32_t frame_data;
50263 +       deptsiz_data_t deptsiz;
50264 +
50265 +       if (ep->proc_buf_num == 0) {
50266 +               /** Buffer 0 descriptors setup */
50267 +               dma_ad = ep->dma_addr0;
50268 +       } else {
50269 +               /** Buffer 1 descriptors setup */
50270 +               dma_ad = ep->dma_addr1;
50271 +       }
50272 +
50273 +       if (ep->is_in) {
50274 +               deptsiz.d32 =
50275 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
50276 +                                  dieptsiz);
50277 +       } else {
50278 +               deptsiz.d32 =
50279 +                   DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
50280 +                                  doeptsiz);
50281 +       }
50282 +
50283 +       if (!deptsiz.b.xfersize) {
50284 +               offset = 0;
50285 +               for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
50286 +                       frame_data = ep->data_per_frame;
50287 +                       for (j = 0; j < ep->pkt_per_frm; ++j) {
50288 +
50289 +                               /* Packet status - is not set as initially
50290 +                                * it is set to 0 and if packet was sent
50291 +                                successfully, status field will remain 0*/
50292 +
50293 +                               /* Bytes has been transfered */
50294 +                               packet_info->length =
50295 +                                   (ep->maxpacket <
50296 +                                    frame_data) ? ep->maxpacket : frame_data;
50297 +
50298 +                               /* Received packet offset */
50299 +                               packet_info->offset = offset;
50300 +                               offset += packet_info->length;
50301 +                               frame_data -= packet_info->length;
50302 +
50303 +                               packet_info++;
50304 +                       }
50305 +               }
50306 +               return 1;
50307 +       } else {
50308 +               /* This is a workaround for in case of Transfer Complete with
50309 +                * PktDrpSts interrupts merging - in this case Transfer complete
50310 +                * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
50311 +                * set and with DOEPTSIZ register non zero. Investigations showed,
50312 +                * that this happens when Out packet is dropped, but because of
50313 +                * interrupts merging during first interrupt handling PktDrpSts
50314 +                * bit is cleared and for next merged interrupts it is not reset.
50315 +                * In this case SW hadles the interrupt as if PktDrpSts bit is set.
50316 +                */
50317 +               if (ep->is_in) {
50318 +                       return 1;
50319 +               } else {
50320 +                       return handle_iso_out_pkt_dropped(core_if, ep);
50321 +               }
50322 +       }
50323 +}
50324 +
50325 +/**
50326 + * This function is to handle Iso EP transfer complete interrupt
50327 + *
50328 + * @param pcd The PCD
50329 + * @param ep The EP for which transfer complete was asserted
50330 + *
50331 + */
50332 +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
50333 +{
50334 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
50335 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50336 +       uint8_t is_last = 0;
50337 +
50338 +       if (ep->dwc_ep.next_frame == 0xffffffff) {
50339 +               DWC_WARN("Next frame is not set!\n");
50340 +               return;
50341 +       }
50342 +
50343 +       if (core_if->dma_enable) {
50344 +               if (core_if->dma_desc_enable) {
50345 +                       set_ddma_iso_pkts_info(core_if, dwc_ep);
50346 +                       reinit_ddma_iso_xfer(core_if, dwc_ep);
50347 +                       is_last = 1;
50348 +               } else {
50349 +                       if (core_if->pti_enh_enable) {
50350 +                               if (set_iso_pkts_info(core_if, dwc_ep)) {
50351 +                                       dwc_ep->proc_buf_num =
50352 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50353 +                                       dwc_otg_iso_ep_start_buf_transfer
50354 +                                           (core_if, dwc_ep);
50355 +                                       is_last = 1;
50356 +                               }
50357 +                       } else {
50358 +                               set_current_pkt_info(core_if, dwc_ep);
50359 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50360 +                                       is_last = 1;
50361 +                                       dwc_ep->cur_pkt = 0;
50362 +                                       dwc_ep->proc_buf_num =
50363 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50364 +                                       if (dwc_ep->proc_buf_num) {
50365 +                                               dwc_ep->cur_pkt_addr =
50366 +                                                   dwc_ep->xfer_buff1;
50367 +                                               dwc_ep->cur_pkt_dma_addr =
50368 +                                                   dwc_ep->dma_addr1;
50369 +                                       } else {
50370 +                                               dwc_ep->cur_pkt_addr =
50371 +                                                   dwc_ep->xfer_buff0;
50372 +                                               dwc_ep->cur_pkt_dma_addr =
50373 +                                                   dwc_ep->dma_addr0;
50374 +                                       }
50375 +
50376 +                               }
50377 +                               dwc_otg_iso_ep_start_frm_transfer(core_if,
50378 +                                                                 dwc_ep);
50379 +                       }
50380 +               }
50381 +       } else {
50382 +               set_current_pkt_info(core_if, dwc_ep);
50383 +               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50384 +                       is_last = 1;
50385 +                       dwc_ep->cur_pkt = 0;
50386 +                       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50387 +                       if (dwc_ep->proc_buf_num) {
50388 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
50389 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
50390 +                       } else {
50391 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
50392 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
50393 +                       }
50394 +
50395 +               }
50396 +               dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
50397 +       }
50398 +       if (is_last)
50399 +               dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
50400 +}
50401 +#endif /* DWC_EN_ISOC */
50402 +
50403 +/**
50404 + * This function handle BNA interrupt for Non Isochronous EPs
50405 + *
50406 + */
50407 +static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
50408 +{
50409 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50410 +       volatile uint32_t *addr;
50411 +       depctl_data_t depctl = {.d32 = 0 };
50412 +       dwc_otg_pcd_t *pcd = ep->pcd;
50413 +       dwc_otg_dev_dma_desc_t *dma_desc;
50414 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
50415 +       dwc_otg_core_if_t *core_if = ep->pcd->core_if;
50416 +       int i, start;
50417 +
50418 +       if (!dwc_ep->desc_cnt)
50419 +               DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
50420 +                        (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
50421 +
50422 +       if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
50423 +                                                       && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
50424 +               uint32_t doepdma;
50425 +               dwc_otg_dev_out_ep_regs_t *out_regs =
50426 +                       core_if->dev_if->out_ep_regs[dwc_ep->num];
50427 +               doepdma = DWC_READ_REG32(&(out_regs->doepdma));
50428 +               start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
50429 +               dma_desc = &(dwc_ep->desc_addr[start]);
50430 +       } else {
50431 +               start = 0;
50432 +               dma_desc = dwc_ep->desc_addr;
50433 +       }
50434 +
50435 +
50436 +       for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
50437 +               sts.d32 = dma_desc->status.d32;
50438 +               sts.b.bs = BS_HOST_READY;
50439 +               dma_desc->status.d32 = sts.d32;
50440 +       }
50441 +
50442 +       if (dwc_ep->is_in == 0) {
50443 +               addr =
50444 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
50445 +                   doepctl;
50446 +       } else {
50447 +               addr =
50448 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50449 +       }
50450 +       depctl.b.epena = 1;
50451 +       depctl.b.cnak = 1;
50452 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
50453 +}
50454 +
50455 +/**
50456 + * This function handles EP0 Control transfers.
50457 + *
50458 + * The state of the control transfers are tracked in
50459 + * <code>ep0state</code>.
50460 + */
50461 +static void handle_ep0(dwc_otg_pcd_t * pcd)
50462 +{
50463 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50464 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
50465 +       dev_dma_desc_sts_t desc_sts;
50466 +       deptsiz0_data_t deptsiz;
50467 +       uint32_t byte_count;
50468 +
50469 +#ifdef DEBUG_EP0
50470 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
50471 +       print_ep0_state(pcd);
50472 +#endif
50473 +
50474 +//      DWC_PRINTF("HANDLE EP0\n");
50475 +
50476 +       switch (pcd->ep0state) {
50477 +       case EP0_DISCONNECT:
50478 +               break;
50479 +
50480 +       case EP0_IDLE:
50481 +               pcd->request_config = 0;
50482 +
50483 +               pcd_setup(pcd);
50484 +               break;
50485 +
50486 +       case EP0_IN_DATA_PHASE:
50487 +#ifdef DEBUG_EP0
50488 +               DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
50489 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50490 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50491 +#endif
50492 +
50493 +               if (core_if->dma_enable != 0) {
50494 +                       /*
50495 +                        * For EP0 we can only program 1 packet at a time so we
50496 +                        * need to do the make calculations after each complete.
50497 +                        * Call write_packet to make the calculations, as in
50498 +                        * slave mode, and use those values to determine if we
50499 +                        * can complete.
50500 +                        */
50501 +                       if (core_if->dma_desc_enable == 0) {
50502 +                               deptsiz.d32 =
50503 +                                   DWC_READ_REG32(&core_if->
50504 +                                                  dev_if->in_ep_regs[0]->
50505 +                                                  dieptsiz);
50506 +                               byte_count =
50507 +                                   ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
50508 +                       } else {
50509 +                               desc_sts =
50510 +                                   core_if->dev_if->in_desc_addr->status;
50511 +                               byte_count =
50512 +                                   ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
50513 +                       }
50514 +                       ep0->dwc_ep.xfer_count += byte_count;
50515 +                       ep0->dwc_ep.xfer_buff += byte_count;
50516 +                       ep0->dwc_ep.dma_addr += byte_count;
50517 +               }
50518 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50519 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50520 +                                                     &ep0->dwc_ep);
50521 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50522 +               } else if (ep0->dwc_ep.sent_zlp) {
50523 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50524 +                                                     &ep0->dwc_ep);
50525 +                       ep0->dwc_ep.sent_zlp = 0;
50526 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50527 +               } else {
50528 +                       ep0_complete_request(ep0);
50529 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50530 +               }
50531 +               break;
50532 +       case EP0_OUT_DATA_PHASE:
50533 +#ifdef DEBUG_EP0
50534 +               DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
50535 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50536 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50537 +#endif
50538 +               if (core_if->dma_enable != 0) {
50539 +                       if (core_if->dma_desc_enable == 0) {
50540 +                               deptsiz.d32 =
50541 +                                   DWC_READ_REG32(&core_if->
50542 +                                                  dev_if->out_ep_regs[0]->
50543 +                                                  doeptsiz);
50544 +                               byte_count =
50545 +                                   ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
50546 +                       } else {
50547 +                               desc_sts =
50548 +                                   core_if->dev_if->out_desc_addr->status;
50549 +                               byte_count =
50550 +                                   ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
50551 +                       }
50552 +                       ep0->dwc_ep.xfer_count += byte_count;
50553 +                       ep0->dwc_ep.xfer_buff += byte_count;
50554 +                       ep0->dwc_ep.dma_addr += byte_count;
50555 +               }
50556 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50557 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50558 +                                                     &ep0->dwc_ep);
50559 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50560 +               } else if (ep0->dwc_ep.sent_zlp) {
50561 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50562 +                                                     &ep0->dwc_ep);
50563 +                       ep0->dwc_ep.sent_zlp = 0;
50564 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50565 +               } else {
50566 +                       ep0_complete_request(ep0);
50567 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50568 +               }
50569 +               break;
50570 +
50571 +       case EP0_IN_STATUS_PHASE:
50572 +       case EP0_OUT_STATUS_PHASE:
50573 +               DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
50574 +               ep0_complete_request(ep0);
50575 +               pcd->ep0state = EP0_IDLE;
50576 +               ep0->stopped = 1;
50577 +               ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
50578 +
50579 +               /* Prepare for more SETUP Packets */
50580 +               if (core_if->dma_enable) {
50581 +                       ep0_out_start(core_if, pcd);
50582 +               }
50583 +               break;
50584 +
50585 +       case EP0_STALL:
50586 +               DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
50587 +               break;
50588 +       }
50589 +#ifdef DEBUG_EP0
50590 +       print_ep0_state(pcd);
50591 +#endif
50592 +}
50593 +
50594 +/**
50595 + * Restart transfer
50596 + */
50597 +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
50598 +{
50599 +       dwc_otg_core_if_t *core_if;
50600 +       dwc_otg_dev_if_t *dev_if;
50601 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50602 +       dwc_otg_pcd_ep_t *ep;
50603 +
50604 +       ep = get_in_ep(pcd, epnum);
50605 +
50606 +#ifdef DWC_EN_ISOC
50607 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
50608 +               return;
50609 +       }
50610 +#endif /* DWC_EN_ISOC  */
50611 +
50612 +       core_if = GET_CORE_IF(pcd);
50613 +       dev_if = core_if->dev_if;
50614 +
50615 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50616 +
50617 +       DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
50618 +                   " stopped=%d\n", ep->dwc_ep.xfer_buff,
50619 +                   ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
50620 +       /*
50621 +        * If xfersize is 0 and pktcnt in not 0, resend the last packet.
50622 +        */
50623 +       if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
50624 +           ep->dwc_ep.start_xfer_buff != 0) {
50625 +               if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
50626 +                       ep->dwc_ep.xfer_count = 0;
50627 +                       ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
50628 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50629 +               } else {
50630 +                       ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
50631 +                       /* convert packet size to dwords. */
50632 +                       ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
50633 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50634 +               }
50635 +               ep->stopped = 0;
50636 +               DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
50637 +                           "xfer_len=%0x stopped=%d\n",
50638 +                           ep->dwc_ep.xfer_buff,
50639 +                           ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
50640 +                           ep->stopped);
50641 +               if (epnum == 0) {
50642 +                       dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
50643 +               } else {
50644 +                       dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
50645 +               }
50646 +       }
50647 +}
50648 +
50649 +/*
50650 + * This function create new nextep sequnce based on Learn Queue.
50651 + *
50652 + * @param core_if Programming view of DWC_otg controller
50653 + */
50654 +void predict_nextep_seq( dwc_otg_core_if_t * core_if)
50655 +{
50656 +       dwc_otg_device_global_regs_t *dev_global_regs =
50657 +           core_if->dev_if->dev_global_regs;
50658 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
50659 +       /* Number of Token Queue Registers */
50660 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
50661 +       dtknq1_data_t dtknqr1;
50662 +       uint32_t in_tkn_epnums[4];
50663 +       uint8_t seqnum[MAX_EPS_CHANNELS];
50664 +       uint8_t intkn_seq[TOKEN_Q_DEPTH];
50665 +       grstctl_t resetctl = {.d32 = 0 };
50666 +       uint8_t temp;
50667 +       int ndx = 0;
50668 +       int start = 0;
50669 +       int end = 0;
50670 +       int sort_done = 0;
50671 +       int i = 0;
50672 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
50673 +
50674 +
50675 +       DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
50676 +
50677 +       /* Read the DTKNQ Registers */
50678 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
50679 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
50680 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
50681 +                           in_tkn_epnums[i]);
50682 +               if (addr == &dev_global_regs->dvbusdis) {
50683 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
50684 +               } else {
50685 +                       ++addr;
50686 +               }
50687 +
50688 +       }
50689 +
50690 +       /* Copy the DTKNQR1 data to the bit field. */
50691 +       dtknqr1.d32 = in_tkn_epnums[0];
50692 +       if (dtknqr1.b.wrap_bit) {
50693 +               ndx = dtknqr1.b.intknwptr;
50694 +               end = ndx -1;
50695 +               if (end < 0)
50696 +                       end = TOKEN_Q_DEPTH -1;
50697 +       } else {
50698 +               ndx = 0;
50699 +               end = dtknqr1.b.intknwptr -1;
50700 +               if (end < 0)
50701 +                       end = 0;
50702 +       }
50703 +       start = ndx;
50704 +
50705 +       /* Fill seqnum[] by initial values: EP number + 31 */
50706 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50707 +               seqnum[i] = i +31;
50708 +       }
50709 +
50710 +       /* Fill intkn_seq[] from in_tkn_epnums[0] */
50711 +       for (i=0; i < 6; i++)
50712 +               intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
50713 +
50714 +       if (TOKEN_Q_DEPTH > 6) {
50715 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50716 +               for (i=6; i < 14; i++)
50717 +                       intkn_seq[i] =
50718 +                           (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
50719 +       }
50720 +
50721 +       if (TOKEN_Q_DEPTH > 14) {
50722 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50723 +               for (i=14; i < 22; i++)
50724 +                       intkn_seq[i] =
50725 +                           (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
50726 +       }
50727 +
50728 +       if (TOKEN_Q_DEPTH > 22) {
50729 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50730 +               for (i=22; i < 30; i++)
50731 +                       intkn_seq[i] =
50732 +                           (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
50733 +       }
50734 +
50735 +       DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
50736 +                   start, end);
50737 +       for (i=0; i<TOKEN_Q_DEPTH; i++)
50738 +               DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
50739 +
50740 +       /* Update seqnum based on intkn_seq[] */
50741 +       i = 0;
50742 +       do {
50743 +               seqnum[intkn_seq[ndx]] = i;
50744 +               ndx++;
50745 +               i++;
50746 +               if (ndx == TOKEN_Q_DEPTH)
50747 +                       ndx = 0;
50748 +       } while ( i < TOKEN_Q_DEPTH );
50749 +
50750 +       /* Mark non active EP's in seqnum[] by 0xff */
50751 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50752 +               if (core_if->nextep_seq[i] == 0xff )
50753 +                       seqnum[i] = 0xff;
50754 +       }
50755 +
50756 +       /* Sort seqnum[] */
50757 +       sort_done = 0;
50758 +       while (!sort_done) {
50759 +               sort_done = 1;
50760 +               for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50761 +                       if (seqnum[i] > seqnum[i+1]) {
50762 +                               temp = seqnum[i];
50763 +                               seqnum[i] = seqnum[i+1];
50764 +                               seqnum[i+1] = temp;
50765 +                               sort_done = 0;
50766 +                       }
50767 +               }
50768 +       }
50769 +
50770 +       ndx = start + seqnum[0];
50771 +       if (ndx >= TOKEN_Q_DEPTH)
50772 +               ndx = ndx % TOKEN_Q_DEPTH;
50773 +       core_if->first_in_nextep_seq = intkn_seq[ndx];
50774 +
50775 +       /* Update seqnum[] by EP numbers  */
50776 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50777 +               ndx = start + i;
50778 +               if (seqnum[i] < 31) {
50779 +                       ndx = start + seqnum[i];
50780 +                       if (ndx >= TOKEN_Q_DEPTH)
50781 +                               ndx = ndx % TOKEN_Q_DEPTH;
50782 +                       seqnum[i] = intkn_seq[ndx];
50783 +               } else {
50784 +                       if (seqnum[i] < 0xff) {
50785 +                               seqnum[i] = seqnum[i] - 31;
50786 +                       } else {
50787 +                               break;
50788 +                       }
50789 +               }
50790 +       }
50791 +
50792 +       /* Update nextep_seq[] based on seqnum[] */
50793 +       for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50794 +               if (seqnum[i] != 0xff) {
50795 +                       if (seqnum[i+1] != 0xff) {
50796 +                               core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
50797 +                       } else {
50798 +                               core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
50799 +                               break;
50800 +                       }
50801 +               } else {
50802 +                       break;
50803 +               }
50804 +       }
50805 +
50806 +       DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
50807 +               __func__, core_if->first_in_nextep_seq);
50808 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50809 +               DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
50810 +       }
50811 +
50812 +       /* Flush the Learning Queue */
50813 +       resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
50814 +       resetctl.b.intknqflsh = 1;
50815 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
50816 +
50817 +
50818 +}
50819 +
50820 +/**
50821 + * handle the IN EP disable interrupt.
50822 + */
50823 +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
50824 +                                            const uint32_t epnum)
50825 +{
50826 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50827 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50828 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50829 +       dctl_data_t dctl = {.d32 = 0 };
50830 +       dwc_otg_pcd_ep_t *ep;
50831 +       dwc_ep_t *dwc_ep;
50832 +       gintmsk_data_t gintmsk_data;
50833 +       depctl_data_t depctl;
50834 +       uint32_t diepdma;
50835 +       uint32_t remain_to_transfer = 0;
50836 +       uint8_t i;
50837 +       uint32_t xfer_size;
50838 +
50839 +       ep = get_in_ep(pcd, epnum);
50840 +       dwc_ep = &ep->dwc_ep;
50841 +
50842 +       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
50843 +               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50844 +               complete_ep(ep);
50845 +               return;
50846 +       }
50847 +
50848 +       DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
50849 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
50850 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50851 +       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
50852 +
50853 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
50854 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
50855 +
50856 +       if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {
50857 +               if (ep->stopped) {
50858 +                       if (core_if->en_multiple_tx_fifo)
50859 +                               /* Flush the Tx FIFO */
50860 +                               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50861 +                       /* Clear the Global IN NP NAK */
50862 +                       dctl.d32 = 0;
50863 +                       dctl.b.cgnpinnak = 1;
50864 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50865 +                       /* Restart the transaction */
50866 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50867 +                               restart_transfer(pcd, epnum);
50868 +                       }
50869 +               } else {
50870 +                       /* Restart the transaction */
50871 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50872 +                               restart_transfer(pcd, epnum);
50873 +                       }
50874 +                       DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
50875 +               }
50876 +               return;
50877 +       }
50878 +
50879 +       if (core_if->start_predict > 2) {       // NP IN EP
50880 +               core_if->start_predict--;
50881 +               return;
50882 +       }
50883 +
50884 +       core_if->start_predict--;
50885 +
50886 +       if (core_if->start_predict == 1) {      // All NP IN Ep's disabled now
50887 +
50888 +               predict_nextep_seq(core_if);
50889 +
50890 +               /* Update all active IN EP's NextEP field based of nextep_seq[] */
50891 +               for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
50892 +                       depctl.d32 =
50893 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50894 +                       if (core_if->nextep_seq[i] != 0xff) {   // Active NP IN EP
50895 +                               depctl.b.nextep = core_if->nextep_seq[i];
50896 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50897 +                       }
50898 +               }
50899 +               /* Flush Shared NP TxFIFO */
50900 +               dwc_otg_flush_tx_fifo(core_if, 0);
50901 +               /* Rewind buffers */
50902 +               if (!core_if->dma_desc_enable) {
50903 +                       i = core_if->first_in_nextep_seq;
50904 +                       do {
50905 +                               ep = get_in_ep(pcd, i);
50906 +                               dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50907 +                               xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
50908 +                               if (xfer_size > ep->dwc_ep.maxxfer)
50909 +                                       xfer_size = ep->dwc_ep.maxxfer;
50910 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50911 +                               if (dieptsiz.b.pktcnt != 0) {
50912 +                                       if (xfer_size == 0) {
50913 +                                               remain_to_transfer = 0;
50914 +                                       } else {
50915 +                                               if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
50916 +                                                       remain_to_transfer =
50917 +                                                               dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
50918 +                                               } else {
50919 +                                                       remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)
50920 +                                                               + (xfer_size % ep->dwc_ep.maxpacket);
50921 +                                               }
50922 +                                       }
50923 +                                       diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
50924 +                                       dieptsiz.b.xfersize = remain_to_transfer;
50925 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
50926 +                                       diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
50927 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
50928 +                               }
50929 +                               i = core_if->nextep_seq[i];
50930 +                       } while (i != core_if->first_in_nextep_seq);
50931 +               } else { // dma_desc_enable
50932 +                               DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
50933 +               }
50934 +
50935 +               /* Restart transfers in predicted sequences */
50936 +               i = core_if->first_in_nextep_seq;
50937 +               do {
50938 +                       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50939 +                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50940 +                       if (dieptsiz.b.pktcnt != 0) {
50941 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50942 +                               depctl.b.epena = 1;
50943 +                               depctl.b.cnak = 1;
50944 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50945 +                       }
50946 +                       i = core_if->nextep_seq[i];
50947 +               } while (i != core_if->first_in_nextep_seq);
50948 +
50949 +               /* Clear the global non-periodic IN NAK handshake */
50950 +               dctl.d32 = 0;
50951 +               dctl.b.cgnpinnak = 1;
50952 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50953 +
50954 +               /* Unmask EP Mismatch interrupt */
50955 +               gintmsk_data.d32 = 0;
50956 +               gintmsk_data.b.epmismatch = 1;
50957 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
50958 +
50959 +               core_if->start_predict = 0;
50960 +
50961 +       }
50962 +}
50963 +
50964 +/**
50965 + * Handler for the IN EP timeout handshake interrupt.
50966 + */
50967 +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
50968 +                                            const uint32_t epnum)
50969 +{
50970 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50971 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50972 +
50973 +#ifdef DEBUG
50974 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50975 +       uint32_t num = 0;
50976 +#endif
50977 +       dctl_data_t dctl = {.d32 = 0 };
50978 +       dwc_otg_pcd_ep_t *ep;
50979 +
50980 +       gintmsk_data_t intr_mask = {.d32 = 0 };
50981 +
50982 +       ep = get_in_ep(pcd, epnum);
50983 +
50984 +       /* Disable the NP Tx Fifo Empty Interrrupt */
50985 +       if (!core_if->dma_enable) {
50986 +               intr_mask.b.nptxfempty = 1;
50987 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
50988 +                                intr_mask.d32, 0);
50989 +       }
50990 +       /** @todo NGS Check EP type.
50991 +        * Implement for Periodic EPs */
50992 +       /*
50993 +        * Non-periodic EP
50994 +        */
50995 +       /* Enable the Global IN NAK Effective Interrupt */
50996 +       intr_mask.b.ginnakeff = 1;
50997 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
50998 +
50999 +       /* Set Global IN NAK */
51000 +       dctl.b.sgnpinnak = 1;
51001 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
51002 +
51003 +       ep->stopped = 1;
51004 +
51005 +#ifdef DEBUG
51006 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
51007 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
51008 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
51009 +#endif
51010 +
51011 +#ifdef DISABLE_PERIODIC_EP
51012 +       /*
51013 +        * Set the NAK bit for this EP to
51014 +        * start the disable process.
51015 +        */
51016 +       diepctl.d32 = 0;
51017 +       diepctl.b.snak = 1;
51018 +       DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
51019 +                        diepctl.d32);
51020 +       ep->disabling = 1;
51021 +       ep->stopped = 1;
51022 +#endif
51023 +}
51024 +
51025 +/**
51026 + * Handler for the IN EP NAK interrupt.
51027 + */
51028 +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
51029 +                                           const uint32_t epnum)
51030 +{
51031 +       /** @todo implement ISR */
51032 +       dwc_otg_core_if_t *core_if;
51033 +       diepmsk_data_t intr_mask = {.d32 = 0 };
51034 +
51035 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
51036 +       core_if = GET_CORE_IF(pcd);
51037 +       intr_mask.b.nak = 1;
51038 +
51039 +       if (core_if->multiproc_int_enable) {
51040 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51041 +                                diepeachintmsk[epnum], intr_mask.d32, 0);
51042 +       } else {
51043 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
51044 +                                intr_mask.d32, 0);
51045 +       }
51046 +
51047 +       return 1;
51048 +}
51049 +
51050 +/**
51051 + * Handler for the OUT EP Babble interrupt.
51052 + */
51053 +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
51054 +                                               const uint32_t epnum)
51055 +{
51056 +       /** @todo implement ISR */
51057 +       dwc_otg_core_if_t *core_if;
51058 +       doepmsk_data_t intr_mask = {.d32 = 0 };
51059 +
51060 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
51061 +                  "OUT EP Babble");
51062 +       core_if = GET_CORE_IF(pcd);
51063 +       intr_mask.b.babble = 1;
51064 +
51065 +       if (core_if->multiproc_int_enable) {
51066 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51067 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
51068 +       } else {
51069 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51070 +                                intr_mask.d32, 0);
51071 +       }
51072 +
51073 +       return 1;
51074 +}
51075 +
51076 +/**
51077 + * Handler for the OUT EP NAK interrupt.
51078 + */
51079 +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
51080 +                                            const uint32_t epnum)
51081 +{
51082 +       /** @todo implement ISR */
51083 +       dwc_otg_core_if_t *core_if;
51084 +       doepmsk_data_t intr_mask = {.d32 = 0 };
51085 +
51086 +       DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
51087 +       core_if = GET_CORE_IF(pcd);
51088 +       intr_mask.b.nak = 1;
51089 +
51090 +       if (core_if->multiproc_int_enable) {
51091 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51092 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
51093 +       } else {
51094 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51095 +                                intr_mask.d32, 0);
51096 +       }
51097 +
51098 +       return 1;
51099 +}
51100 +
51101 +/**
51102 + * Handler for the OUT EP NYET interrupt.
51103 + */
51104 +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
51105 +                                             const uint32_t epnum)
51106 +{
51107 +       /** @todo implement ISR */
51108 +       dwc_otg_core_if_t *core_if;
51109 +       doepmsk_data_t intr_mask = {.d32 = 0 };
51110 +
51111 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
51112 +       core_if = GET_CORE_IF(pcd);
51113 +       intr_mask.b.nyet = 1;
51114 +
51115 +       if (core_if->multiproc_int_enable) {
51116 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
51117 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
51118 +       } else {
51119 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51120 +                                intr_mask.d32, 0);
51121 +       }
51122 +
51123 +       return 1;
51124 +}
51125 +
51126 +/**
51127 + * This interrupt indicates that an IN EP has a pending Interrupt.
51128 + * The sequence for handling the IN EP interrupt is shown below:
51129 + * -#  Read the Device All Endpoint Interrupt register
51130 + * -#  Repeat the following for each IN EP interrupt bit set (from
51131 + *             LSB to MSB).
51132 + * -#  Read the Device Endpoint Interrupt (DIEPINTn) register
51133 + * -#  If "Transfer Complete" call the request complete function
51134 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
51135 + * -#  If "AHB Error Interrupt" log error
51136 + * -#  If "Time-out Handshake" log error
51137 + * -#  If "IN Token Received when TxFIFO Empty" write packet to Tx
51138 + *             FIFO.
51139 + * -#  If "IN Token EP Mismatch" (disable, this is handled by EP
51140 + *             Mismatch Interrupt)
51141 + */
51142 +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
51143 +{
51144 +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
51145 +do { \
51146 +               diepint_data_t diepint = {.d32=0}; \
51147 +               diepint.b.__intr = 1; \
51148 +               DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
51149 +               diepint.d32); \
51150 +} while (0)
51151 +
51152 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51153 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
51154 +       diepint_data_t diepint = {.d32 = 0 };
51155 +       depctl_data_t depctl = {.d32 = 0 };
51156 +       uint32_t ep_intr;
51157 +       uint32_t epnum = 0;
51158 +       dwc_otg_pcd_ep_t *ep;
51159 +       dwc_ep_t *dwc_ep;
51160 +       gintmsk_data_t intr_mask = {.d32 = 0 };
51161 +
51162 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
51163 +
51164 +       /* Read in the device interrupt bits */
51165 +       ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
51166 +
51167 +       /* Service the Device IN interrupts for each endpoint */
51168 +       while (ep_intr) {
51169 +               if (ep_intr & 0x1) {
51170 +                       uint32_t empty_msk;
51171 +                       /* Get EP pointer */
51172 +                       ep = get_in_ep(pcd, epnum);
51173 +                       dwc_ep = &ep->dwc_ep;
51174 +
51175 +                       depctl.d32 =
51176 +                           DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51177 +                       empty_msk =
51178 +                           DWC_READ_REG32(&dev_if->
51179 +                                          dev_global_regs->dtknqr4_fifoemptymsk);
51180 +
51181 +                       DWC_DEBUGPL(DBG_PCDV,
51182 +                                   "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",
51183 +                                   epnum, empty_msk, depctl.d32);
51184 +
51185 +                       DWC_DEBUGPL(DBG_PCD,
51186 +                                   "EP%d-%s: type=%d, mps=%d\n",
51187 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51188 +                                   dwc_ep->type, dwc_ep->maxpacket);
51189 +
51190 +                       diepint.d32 =
51191 +                           dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
51192 +
51193 +                       DWC_DEBUGPL(DBG_PCDV,
51194 +                                   "EP %d Interrupt Register - 0x%x\n", epnum,
51195 +                                   diepint.d32);
51196 +                       /* Transfer complete */
51197 +                       if (diepint.b.xfercompl) {
51198 +                               /* Disable the NP Tx FIFO Empty
51199 +                                * Interrupt */
51200 +                               if (core_if->en_multiple_tx_fifo == 0) {
51201 +                                       intr_mask.b.nptxfempty = 1;
51202 +                                       DWC_MODIFY_REG32
51203 +                                           (&core_if->core_global_regs->gintmsk,
51204 +                                            intr_mask.d32, 0);
51205 +                               } else {
51206 +                                       /* Disable the Tx FIFO Empty Interrupt for this EP */
51207 +                                       uint32_t fifoemptymsk =
51208 +                                           0x1 << dwc_ep->num;
51209 +                                       DWC_MODIFY_REG32(&core_if->
51210 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
51211 +                                                        fifoemptymsk, 0);
51212 +                               }
51213 +                               /* Clear the bit in DIEPINTn for this interrupt */
51214 +                               CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
51215 +
51216 +                               /* Complete the transfer */
51217 +                               if (epnum == 0) {
51218 +                                       handle_ep0(pcd);
51219 +                               }
51220 +#ifdef DWC_EN_ISOC
51221 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51222 +                                       if (!ep->stopped)
51223 +                                               complete_iso_ep(pcd, ep);
51224 +                               }
51225 +#endif /* DWC_EN_ISOC */
51226 +#ifdef DWC_UTE_PER_IO
51227 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51228 +                                       if (!ep->stopped)
51229 +                                               complete_xiso_ep(ep);
51230 +                               }
51231 +#endif /* DWC_UTE_PER_IO */
51232 +                               else {
51233 +                                       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&
51234 +                                                       dwc_ep->bInterval > 1) {
51235 +                                               dwc_ep->frame_num += dwc_ep->bInterval;
51236 +                                               if (dwc_ep->frame_num > 0x3FFF)
51237 +                                               {
51238 +                                                       dwc_ep->frm_overrun = 1;
51239 +                                                       dwc_ep->frame_num &= 0x3FFF;
51240 +                                               } else
51241 +                                                       dwc_ep->frm_overrun = 0;
51242 +                                       }
51243 +                                       complete_ep(ep);
51244 +                                       if(diepint.b.nak)
51245 +                                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51246 +                               }
51247 +                       }
51248 +                       /* Endpoint disable      */
51249 +                       if (diepint.b.epdisabled) {
51250 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
51251 +                                           epnum);
51252 +                               handle_in_ep_disable_intr(pcd, epnum);
51253 +
51254 +                               /* Clear the bit in DIEPINTn for this interrupt */
51255 +                               CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
51256 +                       }
51257 +                       /* AHB Error */
51258 +                       if (diepint.b.ahberr) {
51259 +                               DWC_ERROR("EP%d IN AHB Error\n", epnum);
51260 +                               /* Clear the bit in DIEPINTn for this interrupt */
51261 +                               CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
51262 +                       }
51263 +                       /* TimeOUT Handshake (non-ISOC IN EPs) */
51264 +                       if (diepint.b.timeout) {
51265 +                               DWC_ERROR("EP%d IN Time-out\n", epnum);
51266 +                               handle_in_ep_timeout_intr(pcd, epnum);
51267 +
51268 +                               CLEAR_IN_EP_INTR(core_if, epnum, timeout);
51269 +                       }
51270 +                       /** IN Token received with TxF Empty */
51271 +                       if (diepint.b.intktxfemp) {
51272 +                               DWC_DEBUGPL(DBG_ANY,
51273 +                                           "EP%d IN TKN TxFifo Empty\n",
51274 +                                           epnum);
51275 +                               if (!ep->stopped && epnum != 0) {
51276 +
51277 +                                       diepmsk_data_t diepmsk = {.d32 = 0 };
51278 +                                       diepmsk.b.intktxfemp = 1;
51279 +
51280 +                                       if (core_if->multiproc_int_enable) {
51281 +                                               DWC_MODIFY_REG32
51282 +                                                   (&dev_if->dev_global_regs->diepeachintmsk
51283 +                                                    [epnum], diepmsk.d32, 0);
51284 +                                       } else {
51285 +                                               DWC_MODIFY_REG32
51286 +                                                   (&dev_if->dev_global_regs->diepmsk,
51287 +                                                    diepmsk.d32, 0);
51288 +                                       }
51289 +                               } else if (core_if->dma_desc_enable
51290 +                                          && epnum == 0
51291 +                                          && pcd->ep0state ==
51292 +                                          EP0_OUT_STATUS_PHASE) {
51293 +                                       // EP0 IN set STALL
51294 +                                       depctl.d32 =
51295 +                                           DWC_READ_REG32(&dev_if->in_ep_regs
51296 +                                                          [epnum]->diepctl);
51297 +
51298 +                                       /* set the disable and stall bits */
51299 +                                       if (depctl.b.epena) {
51300 +                                               depctl.b.epdis = 1;
51301 +                                       }
51302 +                                       depctl.b.stall = 1;
51303 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs
51304 +                                                       [epnum]->diepctl,
51305 +                                                       depctl.d32);
51306 +                               }
51307 +                               CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
51308 +                       }
51309 +                       /** IN Token Received with EP mismatch */
51310 +                       if (diepint.b.intknepmis) {
51311 +                               DWC_DEBUGPL(DBG_ANY,
51312 +                                           "EP%d IN TKN EP Mismatch\n", epnum);
51313 +                               CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
51314 +                       }
51315 +                       /** IN Endpoint NAK Effective */
51316 +                       if (diepint.b.inepnakeff) {
51317 +                               DWC_DEBUGPL(DBG_ANY,
51318 +                                           "EP%d IN EP NAK Effective\n",
51319 +                                           epnum);
51320 +                               /* Periodic EP */
51321 +                               if (ep->disabling) {
51322 +                                       depctl.d32 = 0;
51323 +                                       depctl.b.snak = 1;
51324 +                                       depctl.b.epdis = 1;
51325 +                                       DWC_MODIFY_REG32(&dev_if->in_ep_regs
51326 +                                                        [epnum]->diepctl,
51327 +                                                        depctl.d32,
51328 +                                                        depctl.d32);
51329 +                               }
51330 +                               CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
51331 +
51332 +                       }
51333 +
51334 +                       /** IN EP Tx FIFO Empty Intr */
51335 +                       if (diepint.b.emptyintr) {
51336 +                               DWC_DEBUGPL(DBG_ANY,
51337 +                                           "EP%d Tx FIFO Empty Intr \n",
51338 +                                           epnum);
51339 +                               write_empty_tx_fifo(pcd, epnum);
51340 +
51341 +                               CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
51342 +
51343 +                       }
51344 +
51345 +                       /** IN EP BNA Intr */
51346 +                       if (diepint.b.bna) {
51347 +                               CLEAR_IN_EP_INTR(core_if, epnum, bna);
51348 +                               if (core_if->dma_desc_enable) {
51349 +#ifdef DWC_EN_ISOC
51350 +                                       if (dwc_ep->type ==
51351 +                                           DWC_OTG_EP_TYPE_ISOC) {
51352 +                                               /*
51353 +                                                * This checking is performed to prevent first "false" BNA
51354 +                                                * handling occuring right after reconnect
51355 +                                                */
51356 +                                               if (dwc_ep->next_frame !=
51357 +                                                   0xffffffff)
51358 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51359 +                                       } else
51360 +#endif                         /* DWC_EN_ISOC */
51361 +                                       {
51362 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51363 +                                       }
51364 +                               }
51365 +                       }
51366 +                       /* NAK Interrutp */
51367 +                       if (diepint.b.nak) {
51368 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
51369 +                                           epnum);
51370 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51371 +                                       depctl_data_t depctl;
51372 +                                       if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
51373 +                                               ep->dwc_ep.frame_num = core_if->frame_num;
51374 +                                               if (ep->dwc_ep.bInterval > 1) {
51375 +                                                       depctl.d32 = 0;
51376 +                                                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51377 +                                                       if (ep->dwc_ep.frame_num & 0x1) {
51378 +                                                               depctl.b.setd1pid = 1;
51379 +                                                               depctl.b.setd0pid = 0;
51380 +                                                       } else {
51381 +                                                               depctl.b.setd0pid = 1;
51382 +                                                               depctl.b.setd1pid = 0;
51383 +                                                       }
51384 +                                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
51385 +                                               }
51386 +                                               start_next_request(ep);
51387 +                                       }
51388 +                                       ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
51389 +                                       if (dwc_ep->frame_num > 0x3FFF) {
51390 +                                               dwc_ep->frm_overrun = 1;
51391 +                                               dwc_ep->frame_num &= 0x3FFF;
51392 +                                       } else
51393 +                                               dwc_ep->frm_overrun = 0;
51394 +                               }
51395 +
51396 +                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51397 +                       }
51398 +               }
51399 +               epnum++;
51400 +               ep_intr >>= 1;
51401 +       }
51402 +
51403 +       return 1;
51404 +#undef CLEAR_IN_EP_INTR
51405 +}
51406 +
51407 +/**
51408 + * This interrupt indicates that an OUT EP has a pending Interrupt.
51409 + * The sequence for handling the OUT EP interrupt is shown below:
51410 + * -#  Read the Device All Endpoint Interrupt register
51411 + * -#  Repeat the following for each OUT EP interrupt bit set (from
51412 + *             LSB to MSB).
51413 + * -#  Read the Device Endpoint Interrupt (DOEPINTn) register
51414 + * -#  If "Transfer Complete" call the request complete function
51415 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
51416 + * -#  If "AHB Error Interrupt" log error
51417 + * -#  If "Setup Phase Done" process Setup Packet (See Standard USB
51418 + *             Command Processing)
51419 + */
51420 +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
51421 +{
51422 +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
51423 +do { \
51424 +               doepint_data_t doepint = {.d32=0}; \
51425 +               doepint.b.__intr = 1; \
51426 +               DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
51427 +               doepint.d32); \
51428 +} while (0)
51429 +
51430 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51431 +       uint32_t ep_intr;
51432 +       doepint_data_t doepint = {.d32 = 0 };
51433 +       uint32_t epnum = 0;
51434 +       dwc_otg_pcd_ep_t *ep;
51435 +       dwc_ep_t *dwc_ep;
51436 +       dctl_data_t dctl = {.d32 = 0 };
51437 +       gintmsk_data_t gintmsk = {.d32 = 0 };
51438 +
51439 +
51440 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
51441 +
51442 +       /* Read in the device interrupt bits */
51443 +       ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
51444 +
51445 +       while (ep_intr) {
51446 +               if (ep_intr & 0x1) {
51447 +                       /* Get EP pointer */
51448 +                       ep = get_out_ep(pcd, epnum);
51449 +                       dwc_ep = &ep->dwc_ep;
51450 +
51451 +#ifdef VERBOSE
51452 +                       DWC_DEBUGPL(DBG_PCDV,
51453 +                                   "EP%d-%s: type=%d, mps=%d\n",
51454 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51455 +                                   dwc_ep->type, dwc_ep->maxpacket);
51456 +#endif
51457 +                       doepint.d32 =
51458 +                           dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
51459 +                       /* Moved this interrupt upper due to core deffect of asserting
51460 +                        * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
51461 +                       if (doepint.b.stsphsercvd) {
51462 +                               deptsiz0_data_t deptsiz;
51463 +                               CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
51464 +                               deptsiz.d32 =
51465 +                                   DWC_READ_REG32(&core_if->dev_if->
51466 +                                                  out_ep_regs[0]->doeptsiz);
51467 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51468 +                                   && core_if->dma_enable
51469 +                                   && core_if->dma_desc_enable == 0
51470 +                                   && doepint.b.xfercompl
51471 +                                   && deptsiz.b.xfersize == 24) {
51472 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51473 +                                                         xfercompl);
51474 +                                       doepint.b.xfercompl = 0;
51475 +                                       ep0_out_start(core_if, pcd);
51476 +                               }
51477 +                               if ((core_if->dma_desc_enable) ||
51478 +                                   (core_if->dma_enable
51479 +                                    && core_if->snpsid >=
51480 +                                    OTG_CORE_REV_3_00a)) {
51481 +                                       do_setup_in_status_phase(pcd);
51482 +                               }
51483 +                       }
51484 +                       /* Transfer complete */
51485 +                       if (doepint.b.xfercompl) {
51486 +
51487 +                               if (epnum == 0) {
51488 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51489 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51490 +                                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
51491 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51492 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
51493 +                                                       doepint.d32);
51494 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
51495 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
51496 +
51497 +                                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51498 +                                                       && core_if->dma_enable == 0) {
51499 +                                                       doepint_data_t doepint;
51500 +                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51501 +                                                                                                               out_ep_regs[0]->doepint);
51502 +                                                       if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
51503 +                                                               CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51504 +                                                               goto exit_xfercompl;
51505 +                                                       }
51506 +                                               }
51507 +                                               /* In case of DDMA  look at SR bit to go to the Data Stage */
51508 +                                               if (core_if->dma_desc_enable) {
51509 +                                                       dev_dma_desc_sts_t status = {.d32 = 0};
51510 +                                                       if (pcd->ep0state == EP0_IDLE) {
51511 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51512 +                                                                                       dev_if->setup_desc_index]->status.d32;
51513 +                                                               if(pcd->data_terminated) {
51514 +                                                                        pcd->data_terminated = 0;
51515 +                                                                        status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51516 +                                                                        dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
51517 +                                                               }
51518 +                                                               if (status.b.sr) {
51519 +                                                                       if (doepint.b.setup) {
51520 +                                                                               DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
51521 +                                                                               /* Already started data stage, clear setup */
51522 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51523 +                                                                               doepint.b.setup = 0;
51524 +                                                                               handle_ep0(pcd);
51525 +                                                                               /* Prepare for more setup packets */
51526 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51527 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51528 +                                                                                       ep0_out_start(core_if, pcd);
51529 +                                                                               }
51530 +
51531 +                                                                               goto exit_xfercompl;
51532 +                                                                       } else {
51533 +                                                                               /* Prepare for more setup packets */
51534 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51535 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51536 +                                                                               ep0_out_start(core_if, pcd);
51537 +                                                                       }
51538 +                                                               }
51539 +                                                       } else {
51540 +                                                               dwc_otg_pcd_request_t *req;
51541 +                                                               dev_dma_desc_sts_t status = {.d32 = 0};
51542 +                                                               diepint_data_t diepint0;
51543 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51544 +                                                                                                                       in_ep_regs[0]->diepint);
51545 +
51546 +                                                               if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
51547 +                                                                       DWC_ERROR("EP0 is stalled/disconnected\n");
51548 +                                                               }
51549 +
51550 +                                                               /* Clear IN xfercompl if set */
51551 +                                                               if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
51552 +                                                                       || pcd->ep0state == EP0_IN_DATA_PHASE)) {
51553 +                                                                       DWC_WRITE_REG32(&core_if->dev_if->
51554 +                                                                               in_ep_regs[0]->diepint, diepint0.d32);
51555 +                                                               }
51556 +
51557 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51558 +                                                                       dev_if->setup_desc_index]->status.d32;
51559 +
51560 +                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
51561 +                                                                       && (pcd->ep0state == EP0_OUT_DATA_PHASE))
51562 +                                                                       status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51563 +                                                               if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
51564 +                                                                       status.d32 = status.d32 = core_if->dev_if->
51565 +                                                                       out_desc_addr->status.d32;
51566 +
51567 +                                                               if (status.b.sr) {
51568 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51569 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51570 +                                                                       } else {
51571 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51572 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51573 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51574 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51575 +                                                                                               /* Read arrived setup packet from req->buf */
51576 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51577 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51578 +                                                                               }
51579 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51580 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51581 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51582 +                                                                               ep->dwc_ep.xfer_buff = 0;
51583 +                                                                               ep->dwc_ep.xfer_len = 0;
51584 +                                                                       }
51585 +                                                                       pcd->ep0state = EP0_IDLE;
51586 +                                                                       if (doepint.b.setup) {
51587 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51588 +                                                                               /* Data stage started, clear setup */
51589 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51590 +                                                                               doepint.b.setup = 0;
51591 +                                                                               handle_ep0(pcd);
51592 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51593 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51594 +                                                                                       ep0_out_start(core_if, pcd);
51595 +                                                                               }
51596 +
51597 +                                                                               goto exit_xfercompl;
51598 +                                                                       } else {
51599 +                                                                               /* Prepare for more setup packets */
51600 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51601 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51602 +                                                                               ep0_out_start(core_if, pcd);
51603 +                                                                       }
51604 +                                                               }
51605 +                                                       }
51606 +                                               }
51607 +                                               if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
51608 +                                                       && core_if->dma_desc_enable == 0) {
51609 +                                                       doepint_data_t doepint_temp = {.d32 = 0};
51610 +                                                       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
51611 +                                                       doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51612 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doepint);
51613 +                                                       doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
51614 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doeptsiz);
51615 +                                                       if (pcd->ep0state == EP0_IDLE) {
51616 +                                                               if (doepint_temp.b.sr) {
51617 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51618 +                                                               }
51619 +                                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51620 +                                                                                                                                       out_ep_regs[0]->doepint);
51621 +                                                                       if (doeptsize0.b.supcnt == 3) {
51622 +                                                                               DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
51623 +                                                                               ep->dwc_ep.stp_rollover = 1;
51624 +                                                                       }
51625 +                                                                       if (doepint.b.setup) {
51626 +retry:
51627 +                                                                               /* Already started data stage, clear setup */
51628 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51629 +                                                                               doepint.b.setup = 0;
51630 +                                                                               handle_ep0(pcd);
51631 +                                                                               ep->dwc_ep.stp_rollover = 0;
51632 +                                                                               /* Prepare for more setup packets */
51633 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51634 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51635 +                                                                                       ep0_out_start(core_if, pcd);
51636 +                                                                               }
51637 +                                                                               goto exit_xfercompl;
51638 +                                                                       } else {
51639 +                                                                               /* Prepare for more setup packets */
51640 +                                                                               DWC_DEBUGPL(DBG_ANY,
51641 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51642 +                                                                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51643 +                                                                                                                                       out_ep_regs[0]->doepint);
51644 +                                                                               if(doepint.b.setup)
51645 +                                                                                       goto retry;
51646 +                                                                               ep0_out_start(core_if, pcd);
51647 +                                                                       }
51648 +                                                       } else {
51649 +                                                               dwc_otg_pcd_request_t *req;
51650 +                                                               diepint_data_t diepint0 = {.d32 = 0};
51651 +                                                               doepint_data_t doepint_temp = {.d32 = 0};
51652 +                                                               depctl_data_t diepctl0;
51653 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51654 +                                                                                                                               in_ep_regs[0]->diepint);
51655 +                                                               diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
51656 +                                                                                                                               in_ep_regs[0]->diepctl);
51657 +
51658 +                                                               if (pcd->ep0state == EP0_IN_DATA_PHASE
51659 +                                                                       || pcd->ep0state == EP0_IN_STATUS_PHASE) {
51660 +                                                                       if (diepint0.b.xfercompl) {
51661 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51662 +                                                                                       in_ep_regs[0]->diepint, diepint0.d32);
51663 +                                                                       }
51664 +                                                                       if (diepctl0.b.epena) {
51665 +                                                                               diepint_data_t diepint = {.d32 = 0};
51666 +                                                                               diepctl0.b.snak = 1;
51667 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51668 +                                                                                                               in_ep_regs[0]->diepctl, diepctl0.d32);
51669 +                                                                               do {
51670 +                                                                                       dwc_udelay(10);
51671 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51672 +                                                                                               in_ep_regs[0]->diepint);
51673 +                                                                               } while (!diepint.b.inepnakeff);
51674 +                                                                               diepint.b.inepnakeff = 1;
51675 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51676 +                                                                                       in_ep_regs[0]->diepint, diepint.d32);
51677 +                                                                               diepctl0.d32 = 0;
51678 +                                                                               diepctl0.b.epdis = 1;
51679 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
51680 +                                                                                                               diepctl0.d32);
51681 +                                                                               do {
51682 +                                                                                       dwc_udelay(10);
51683 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51684 +                                                                                               in_ep_regs[0]->diepint);
51685 +                                                                               } while (!diepint.b.epdisabled);
51686 +                                                                               diepint.b.epdisabled = 1;
51687 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
51688 +                                                                                                                       diepint.d32);
51689 +                                                                       }
51690 +                                                               }
51691 +                                                               doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51692 +                                                                                                                               out_ep_regs[ep->dwc_ep.num]->doepint);
51693 +                                                               if (doepint_temp.b.sr) {
51694 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51695 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51696 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51697 +                                                                       } else {
51698 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51699 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51700 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51701 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51702 +                                                                                               /* Read arrived setup packet from req->buf */
51703 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51704 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51705 +                                                                               }
51706 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51707 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51708 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51709 +                                                                               ep->dwc_ep.xfer_buff = 0;
51710 +                                                                               ep->dwc_ep.xfer_len = 0;
51711 +                                                                       }
51712 +                                                                       pcd->ep0state = EP0_IDLE;
51713 +                                                                       if (doepint.b.setup) {
51714 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51715 +                                                                               /* Data stage started, clear setup */
51716 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51717 +                                                                               doepint.b.setup = 0;
51718 +                                                                               handle_ep0(pcd);
51719 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51720 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51721 +                                                                                       ep0_out_start(core_if, pcd);
51722 +                                                                               }
51723 +                                                                               goto exit_xfercompl;
51724 +                                                                       } else {
51725 +                                                                               /* Prepare for more setup packets */
51726 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51727 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51728 +                                                                               ep0_out_start(core_if, pcd);
51729 +                                                                       }
51730 +                                                               }
51731 +                                                       }
51732 +                                               }
51733 +                                               if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
51734 +                                                       handle_ep0(pcd);
51735 +exit_xfercompl:
51736 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51737 +                                                       dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
51738 +                                       } else {
51739 +                                       if (core_if->dma_desc_enable == 0
51740 +                                           || pcd->ep0state != EP0_IDLE)
51741 +                                               handle_ep0(pcd);
51742 +                                       }
51743 +#ifdef DWC_EN_ISOC
51744 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51745 +                                       if (doepint.b.pktdrpsts == 0) {
51746 +                                               /* Clear the bit in DOEPINTn for this interrupt */
51747 +                                               CLEAR_OUT_EP_INTR(core_if,
51748 +                                                                 epnum,
51749 +                                                                 xfercompl);
51750 +                                               complete_iso_ep(pcd, ep);
51751 +                                       } else {
51752 +
51753 +                                               doepint_data_t doepint = {.d32 = 0 };
51754 +                                               doepint.b.xfercompl = 1;
51755 +                                               doepint.b.pktdrpsts = 1;
51756 +                                               DWC_WRITE_REG32
51757 +                                                   (&core_if->dev_if->out_ep_regs
51758 +                                                    [epnum]->doepint,
51759 +                                                    doepint.d32);
51760 +                                               if (handle_iso_out_pkt_dropped
51761 +                                                   (core_if, dwc_ep)) {
51762 +                                                       complete_iso_ep(pcd,
51763 +                                                                       ep);
51764 +                                               }
51765 +                                       }
51766 +#endif /* DWC_EN_ISOC */
51767 +#ifdef DWC_UTE_PER_IO
51768 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51769 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51770 +                                       if (!ep->stopped)
51771 +                                               complete_xiso_ep(ep);
51772 +#endif /* DWC_UTE_PER_IO */
51773 +                               } else {
51774 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51775 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51776 +                                                         xfercompl);
51777 +
51778 +                                       if (core_if->core_params->dev_out_nak) {
51779 +                                               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
51780 +                                               pcd->core_if->ep_xfer_info[epnum].state = 0;
51781 +#ifdef DEBUG
51782 +                                               print_memory_payload(pcd, dwc_ep);
51783 +#endif
51784 +                                       }
51785 +                                       complete_ep(ep);
51786 +                               }
51787 +
51788 +                       }
51789 +
51790 +                       /* Endpoint disable      */
51791 +                       if (doepint.b.epdisabled) {
51792 +
51793 +                               /* Clear the bit in DOEPINTn for this interrupt */
51794 +                               CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
51795 +                               if (core_if->core_params->dev_out_nak) {
51796 +#ifdef DEBUG
51797 +                                       print_memory_payload(pcd, dwc_ep);
51798 +#endif
51799 +                                       /* In case of timeout condition */
51800 +                                       if (core_if->ep_xfer_info[epnum].state == 2) {
51801 +                                               dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51802 +                                                                               dev_global_regs->dctl);
51803 +                                               dctl.b.cgoutnak = 1;
51804 +                                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51805 +                                                                                                                               dctl.d32);
51806 +                                               /* Unmask goutnakeff interrupt which was masked
51807 +                                                * during handle nak out interrupt */
51808 +                                               gintmsk.b.goutnakeff = 1;
51809 +                                               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51810 +                                                                                                                               0, gintmsk.d32);
51811 +
51812 +                                               complete_ep(ep);
51813 +                                       }
51814 +                               }
51815 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
51816 +                               {
51817 +                                       dctl_data_t dctl;
51818 +                                       gintmsk_data_t intr_mask = {.d32 = 0};
51819 +                                       dwc_otg_pcd_request_t *req = 0;
51820 +
51821 +                                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51822 +                                               dev_global_regs->dctl);
51823 +                                       dctl.b.cgoutnak = 1;
51824 +                                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51825 +                                               dctl.d32);
51826 +
51827 +                                       intr_mask.d32 = 0;
51828 +                                       intr_mask.b.incomplisoout = 1;
51829 +
51830 +                                       /* Get any pending requests */
51831 +                                       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51832 +                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51833 +                                               if (!req) {
51834 +                                                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
51835 +                                               } else {
51836 +                                                       dwc_otg_request_done(ep, req, 0);
51837 +                                                       start_next_request(ep);
51838 +                                               }
51839 +                                       } else {
51840 +                                               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
51841 +                                       }
51842 +                               }
51843 +                       }
51844 +                       /* AHB Error */
51845 +                       if (doepint.b.ahberr) {
51846 +                               DWC_ERROR("EP%d OUT AHB Error\n", epnum);
51847 +                               DWC_ERROR("EP%d DEPDMA=0x%08x \n",
51848 +                                         epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
51849 +                               CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
51850 +                       }
51851 +                       /* Setup Phase Done (contorl EPs) */
51852 +                       if (doepint.b.setup) {
51853 +#ifdef DEBUG_EP0
51854 +                               DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
51855 +#endif
51856 +                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51857 +
51858 +                               handle_ep0(pcd);
51859 +                       }
51860 +
51861 +                       /** OUT EP BNA Intr */
51862 +                       if (doepint.b.bna) {
51863 +                               CLEAR_OUT_EP_INTR(core_if, epnum, bna);
51864 +                               if (core_if->dma_desc_enable) {
51865 +#ifdef DWC_EN_ISOC
51866 +                                       if (dwc_ep->type ==
51867 +                                           DWC_OTG_EP_TYPE_ISOC) {
51868 +                                               /*
51869 +                                                * This checking is performed to prevent first "false" BNA
51870 +                                                * handling occuring right after reconnect
51871 +                                                */
51872 +                                               if (dwc_ep->next_frame !=
51873 +                                                   0xffffffff)
51874 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51875 +                                       } else
51876 +#endif                         /* DWC_EN_ISOC */
51877 +                                       {
51878 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51879 +                                       }
51880 +                               }
51881 +                       }
51882 +                       /* Babble Interrupt */
51883 +                       if (doepint.b.babble) {
51884 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
51885 +                                           epnum);
51886 +                               handle_out_ep_babble_intr(pcd, epnum);
51887 +
51888 +                               CLEAR_OUT_EP_INTR(core_if, epnum, babble);
51889 +                       }
51890 +                       if (doepint.b.outtknepdis) {
51891 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
51892 +                                       disabled\n",epnum);
51893 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51894 +                                       doepmsk_data_t doepmsk = {.d32 = 0};
51895 +                                       ep->dwc_ep.frame_num = core_if->frame_num;
51896 +                                       if (ep->dwc_ep.bInterval > 1) {
51897 +                                               depctl_data_t depctl;
51898 +                                               depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51899 +                                                                                                       out_ep_regs[epnum]->doepctl);
51900 +                                               if (ep->dwc_ep.frame_num & 0x1) {
51901 +                                                       depctl.b.setd1pid = 1;
51902 +                                                       depctl.b.setd0pid = 0;
51903 +                                               } else {
51904 +                                                       depctl.b.setd0pid = 1;
51905 +                                                       depctl.b.setd1pid = 0;
51906 +                                               }
51907 +                                               DWC_WRITE_REG32(&core_if->dev_if->
51908 +                                                                               out_ep_regs[epnum]->doepctl, depctl.d32);
51909 +                                       }
51910 +                                       start_next_request(ep);
51911 +                                       doepmsk.b.outtknepdis = 1;
51912 +                                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51913 +                                                                doepmsk.d32, 0);
51914 +                               }
51915 +                               CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
51916 +                       }
51917 +
51918 +                       /* NAK Interrutp */
51919 +                       if (doepint.b.nak) {
51920 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
51921 +                               handle_out_ep_nak_intr(pcd, epnum);
51922 +
51923 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nak);
51924 +                       }
51925 +                       /* NYET Interrutp */
51926 +                       if (doepint.b.nyet) {
51927 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
51928 +                               handle_out_ep_nyet_intr(pcd, epnum);
51929 +
51930 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
51931 +                       }
51932 +               }
51933 +
51934 +               epnum++;
51935 +               ep_intr >>= 1;
51936 +       }
51937 +
51938 +       return 1;
51939 +
51940 +#undef CLEAR_OUT_EP_INTR
51941 +}
51942 +static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
51943 +{
51944 +       int retval = 0;
51945 +       if(!frm_overrun && curr_fr >= trgt_fr)
51946 +               retval = 1;
51947 +       else if (frm_overrun
51948 +                && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
51949 +               retval = 1;
51950 +       return retval;
51951 +}
51952 +/**
51953 + * Incomplete ISO IN Transfer Interrupt.
51954 + * This interrupt indicates one of the following conditions occurred
51955 + * while transmitting an ISOC transaction.
51956 + * - Corrupted IN Token for ISOC EP.
51957 + * - Packet not complete in FIFO.
51958 + * The follow actions will be taken:
51959 + *     -#      Determine the EP
51960 + *     -#      Set incomplete flag in dwc_ep structure
51961 + *     -#      Disable EP; when "Endpoint Disabled" interrupt is received
51962 + *             Flush FIFO
51963 + */
51964 +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
51965 +{
51966 +       gintsts_data_t gintsts;
51967 +
51968 +#ifdef DWC_EN_ISOC
51969 +       dwc_otg_dev_if_t *dev_if;
51970 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51971 +       depctl_data_t depctl = {.d32 = 0 };
51972 +       dsts_data_t dsts = {.d32 = 0 };
51973 +       dwc_ep_t *dwc_ep;
51974 +       int i;
51975 +
51976 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51977 +
51978 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
51979 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
51980 +               if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51981 +                       deptsiz.d32 =
51982 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
51983 +                       depctl.d32 =
51984 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51985 +
51986 +                       if (depctl.b.epdis && deptsiz.d32) {
51987 +                               set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
51988 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
51989 +                                       dwc_ep->cur_pkt = 0;
51990 +                                       dwc_ep->proc_buf_num =
51991 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
51992 +
51993 +                                       if (dwc_ep->proc_buf_num) {
51994 +                                               dwc_ep->cur_pkt_addr =
51995 +                                                   dwc_ep->xfer_buff1;
51996 +                                               dwc_ep->cur_pkt_dma_addr =
51997 +                                                   dwc_ep->dma_addr1;
51998 +                                       } else {
51999 +                                               dwc_ep->cur_pkt_addr =
52000 +                                                   dwc_ep->xfer_buff0;
52001 +                                               dwc_ep->cur_pkt_dma_addr =
52002 +                                                   dwc_ep->dma_addr0;
52003 +                                       }
52004 +
52005 +                               }
52006 +
52007 +                               dsts.d32 =
52008 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
52009 +                                                  dev_global_regs->dsts);
52010 +                               dwc_ep->next_frame = dsts.b.soffn;
52011 +
52012 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
52013 +                                                                 (pcd),
52014 +                                                                 dwc_ep);
52015 +                       }
52016 +               }
52017 +       }
52018 +
52019 +#else
52020 +       depctl_data_t depctl = {.d32 = 0 };
52021 +       dwc_ep_t *dwc_ep;
52022 +       dwc_otg_dev_if_t *dev_if;
52023 +       int i;
52024 +       dev_if = GET_CORE_IF(pcd)->dev_if;
52025 +
52026 +       DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
52027 +
52028 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
52029 +               dwc_ep = &pcd->in_ep[i-1].dwc_ep;
52030 +               depctl.d32 =
52031 +                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52032 +               if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
52033 +                       if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,
52034 +                                                       dwc_ep->frm_overrun))
52035 +                       {
52036 +                               depctl.d32 =
52037 +                                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52038 +                               depctl.b.snak = 1;
52039 +                               depctl.b.epdis = 1;
52040 +                               DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
52041 +                       }
52042 +               }
52043 +       }
52044 +
52045 +       /*intr_mask.b.incomplisoin = 1;
52046 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52047 +                        intr_mask.d32, 0);      */
52048 +#endif                         //DWC_EN_ISOC
52049 +
52050 +       /* Clear interrupt */
52051 +       gintsts.d32 = 0;
52052 +       gintsts.b.incomplisoin = 1;
52053 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52054 +                       gintsts.d32);
52055 +
52056 +       return 1;
52057 +}
52058 +
52059 +/**
52060 + * Incomplete ISO OUT Transfer Interrupt.
52061 + *
52062 + * This interrupt indicates that the core has dropped an ISO OUT
52063 + * packet. The following conditions can be the cause:
52064 + * - FIFO Full, the entire packet would not fit in the FIFO.
52065 + * - CRC Error
52066 + * - Corrupted Token
52067 + * The follow actions will be taken:
52068 + *     -#      Determine the EP
52069 + *     -#      Set incomplete flag in dwc_ep structure
52070 + *     -#      Read any data from the FIFO
52071 + *     -#      Disable EP. When "Endpoint Disabled" interrupt is received
52072 + *             re-enable EP.
52073 + */
52074 +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
52075 +{
52076 +
52077 +       gintsts_data_t gintsts;
52078 +
52079 +#ifdef DWC_EN_ISOC
52080 +       dwc_otg_dev_if_t *dev_if;
52081 +       deptsiz_data_t deptsiz = {.d32 = 0 };
52082 +       depctl_data_t depctl = {.d32 = 0 };
52083 +       dsts_data_t dsts = {.d32 = 0 };
52084 +       dwc_ep_t *dwc_ep;
52085 +       int i;
52086 +
52087 +       dev_if = GET_CORE_IF(pcd)->dev_if;
52088 +
52089 +       for (i = 1; i <= dev_if->num_out_eps; ++i) {
52090 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
52091 +               if (pcd->out_ep[i].dwc_ep.active &&
52092 +                   pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
52093 +                       deptsiz.d32 =
52094 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
52095 +                       depctl.d32 =
52096 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52097 +
52098 +                       if (depctl.b.epdis && deptsiz.d32) {
52099 +                               set_current_pkt_info(GET_CORE_IF(pcd),
52100 +                                                    &pcd->out_ep[i].dwc_ep);
52101 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
52102 +                                       dwc_ep->cur_pkt = 0;
52103 +                                       dwc_ep->proc_buf_num =
52104 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
52105 +
52106 +                                       if (dwc_ep->proc_buf_num) {
52107 +                                               dwc_ep->cur_pkt_addr =
52108 +                                                   dwc_ep->xfer_buff1;
52109 +                                               dwc_ep->cur_pkt_dma_addr =
52110 +                                                   dwc_ep->dma_addr1;
52111 +                                       } else {
52112 +                                               dwc_ep->cur_pkt_addr =
52113 +                                                   dwc_ep->xfer_buff0;
52114 +                                               dwc_ep->cur_pkt_dma_addr =
52115 +                                                   dwc_ep->dma_addr0;
52116 +                                       }
52117 +
52118 +                               }
52119 +
52120 +                               dsts.d32 =
52121 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
52122 +                                                  dev_global_regs->dsts);
52123 +                               dwc_ep->next_frame = dsts.b.soffn;
52124 +
52125 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
52126 +                                                                 (pcd),
52127 +                                                                 dwc_ep);
52128 +                       }
52129 +               }
52130 +       }
52131 +#else
52132 +       /** @todo implement ISR */
52133 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52134 +       dwc_otg_core_if_t *core_if;
52135 +       deptsiz_data_t deptsiz = {.d32 = 0 };
52136 +       depctl_data_t depctl = {.d32 = 0 };
52137 +       dctl_data_t dctl = {.d32 = 0 };
52138 +       dwc_ep_t *dwc_ep = NULL;
52139 +       int i;
52140 +       core_if = GET_CORE_IF(pcd);
52141 +
52142 +       for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
52143 +               dwc_ep = &pcd->out_ep[i].dwc_ep;
52144 +               depctl.d32 =
52145 +                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52146 +               if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
52147 +                       core_if->dev_if->isoc_ep = dwc_ep;
52148 +                       deptsiz.d32 =
52149 +                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
52150 +                               break;
52151 +               }
52152 +       }
52153 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
52154 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
52155 +       intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
52156 +
52157 +       if (!intr_mask.b.goutnakeff) {
52158 +               /* Unmask it */
52159 +               intr_mask.b.goutnakeff = 1;
52160 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
52161 +       }
52162 +       if (!gintsts.b.goutnakeff) {
52163 +               dctl.b.sgoutnak = 1;
52164 +       }
52165 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
52166 +
52167 +       depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52168 +       if (depctl.b.epena) {
52169 +               depctl.b.epdis = 1;
52170 +               depctl.b.snak = 1;
52171 +       }
52172 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
52173 +
52174 +       intr_mask.d32 = 0;
52175 +       intr_mask.b.incomplisoout = 1;
52176 +
52177 +#endif /* DWC_EN_ISOC */
52178 +
52179 +       /* Clear interrupt */
52180 +       gintsts.d32 = 0;
52181 +       gintsts.b.incomplisoout = 1;
52182 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52183 +                       gintsts.d32);
52184 +
52185 +       return 1;
52186 +}
52187 +
52188 +/**
52189 + * This function handles the Global IN NAK Effective interrupt.
52190 + *
52191 + */
52192 +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
52193 +{
52194 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52195 +       depctl_data_t diepctl = {.d32 = 0 };
52196 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52197 +       gintsts_data_t gintsts;
52198 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52199 +       int i;
52200 +
52201 +       DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
52202 +
52203 +       /* Disable all active IN EPs */
52204 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
52205 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52206 +               if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
52207 +                       if (core_if->start_predict > 0)
52208 +                               core_if->start_predict++;
52209 +                       diepctl.b.epdis = 1;
52210 +                       diepctl.b.snak = 1;
52211 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
52212 +               }
52213 +       }
52214 +
52215 +
52216 +       /* Disable the Global IN NAK Effective Interrupt */
52217 +       intr_mask.b.ginnakeff = 1;
52218 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52219 +                        intr_mask.d32, 0);
52220 +
52221 +       /* Clear interrupt */
52222 +       gintsts.d32 = 0;
52223 +       gintsts.b.ginnakeff = 1;
52224 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52225 +                       gintsts.d32);
52226 +
52227 +       return 1;
52228 +}
52229 +
52230 +/**
52231 + * OUT NAK Effective.
52232 + *
52233 + */
52234 +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
52235 +{
52236 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52237 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52238 +       gintsts_data_t gintsts;
52239 +       depctl_data_t doepctl;
52240 +       int i;
52241 +
52242 +       /* Disable the Global OUT NAK Effective Interrupt */
52243 +       intr_mask.b.goutnakeff = 1;
52244 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52245 +               intr_mask.d32, 0);
52246 +
52247 +       /* If DEV OUT NAK enabled*/
52248 +       if (pcd->core_if->core_params->dev_out_nak) {
52249 +               /* Run over all out endpoints to determine the ep number on
52250 +                * which the timeout has happened
52251 +                */
52252 +               for (i = 0; i <= dev_if->num_out_eps; i++) {
52253 +                       if ( pcd->core_if->ep_xfer_info[i].state == 2 )
52254 +                               break;
52255 +               }
52256 +               if (i > dev_if->num_out_eps) {
52257 +                       dctl_data_t dctl;
52258 +                       dctl.d32 =
52259 +                           DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
52260 +                       dctl.b.cgoutnak = 1;
52261 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
52262 +                               dctl.d32);
52263 +                       goto out;
52264 +               }
52265 +
52266 +               /* Disable the endpoint */
52267 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52268 +               if (doepctl.b.epena) {
52269 +                       doepctl.b.epdis = 1;
52270 +                       doepctl.b.snak = 1;
52271 +               }
52272 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
52273 +               return 1;
52274 +       }
52275 +       /* We come here from Incomplete ISO OUT handler */
52276 +       if (dev_if->isoc_ep) {
52277 +               dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
52278 +               uint32_t epnum = dwc_ep->num;
52279 +               doepint_data_t doepint;
52280 +               doepint.d32 =
52281 +                   DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
52282 +               dev_if->isoc_ep = NULL;
52283 +               doepctl.d32 =
52284 +                   DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
52285 +               DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
52286 +               if (doepctl.b.epena) {
52287 +                       doepctl.b.epdis = 1;
52288 +                       doepctl.b.snak = 1;
52289 +               }
52290 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
52291 +                               doepctl.d32);
52292 +               return 1;
52293 +       } else
52294 +               DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
52295 +                          "Global OUT NAK Effective\n");
52296 +
52297 +out:
52298 +       /* Clear interrupt */
52299 +       gintsts.d32 = 0;
52300 +       gintsts.b.goutnakeff = 1;
52301 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52302 +                       gintsts.d32);
52303 +
52304 +       return 1;
52305 +}
52306 +
52307 +/**
52308 + * PCD interrupt handler.
52309 + *
52310 + * The PCD handles the device interrupts.  Many conditions can cause a
52311 + * device interrupt. When an interrupt occurs, the device interrupt
52312 + * service routine determines the cause of the interrupt and
52313 + * dispatches handling to the appropriate function. These interrupt
52314 + * handling functions are described below.
52315 + *
52316 + * All interrupt registers are processed from LSB to MSB.
52317 + *
52318 + */
52319 +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
52320 +{
52321 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52322 +#ifdef VERBOSE
52323 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
52324 +#endif
52325 +       gintsts_data_t gintr_status;
52326 +       int32_t retval = 0;
52327 +
52328 +       /* Exit from ISR if core is hibernated */
52329 +       if (core_if->hibernation_suspend == 1) {
52330 +               return retval;
52331 +       }
52332 +#ifdef VERBOSE
52333 +       DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n",
52334 +                   __func__,
52335 +                   DWC_READ_REG32(&global_regs->gintsts),
52336 +                   DWC_READ_REG32(&global_regs->gintmsk));
52337 +#endif
52338 +
52339 +       if (dwc_otg_is_device_mode(core_if)) {
52340 +               DWC_SPINLOCK(pcd->lock);
52341 +#ifdef VERBOSE
52342 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",
52343 +                           __func__,
52344 +                           DWC_READ_REG32(&global_regs->gintsts),
52345 +                           DWC_READ_REG32(&global_regs->gintmsk));
52346 +#endif
52347 +
52348 +               gintr_status.d32 = dwc_otg_read_core_intr(core_if);
52349 +
52350 +               DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
52351 +                           __func__, gintr_status.d32);
52352 +
52353 +               if (gintr_status.b.sofintr) {
52354 +                       retval |= dwc_otg_pcd_handle_sof_intr(pcd);
52355 +               }
52356 +               if (gintr_status.b.rxstsqlvl) {
52357 +                       retval |=
52358 +                           dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
52359 +               }
52360 +               if (gintr_status.b.nptxfempty) {
52361 +                       retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
52362 +               }
52363 +               if (gintr_status.b.goutnakeff) {
52364 +                       retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
52365 +               }
52366 +               if (gintr_status.b.i2cintr) {
52367 +                       retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
52368 +               }
52369 +               if (gintr_status.b.erlysuspend) {
52370 +                       retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
52371 +               }
52372 +               if (gintr_status.b.usbreset) {
52373 +                       retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
52374 +               }
52375 +               if (gintr_status.b.enumdone) {
52376 +                       retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
52377 +               }
52378 +               if (gintr_status.b.isooutdrop) {
52379 +                       retval |=
52380 +                           dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
52381 +                           (pcd);
52382 +               }
52383 +               if (gintr_status.b.eopframe) {
52384 +                       retval |=
52385 +                           dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
52386 +               }
52387 +               if (gintr_status.b.inepint) {
52388 +                       if (!core_if->multiproc_int_enable) {
52389 +                               retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52390 +                       }
52391 +               }
52392 +               if (gintr_status.b.outepintr) {
52393 +                       if (!core_if->multiproc_int_enable) {
52394 +                               retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52395 +                       }
52396 +               }
52397 +               if (gintr_status.b.epmismatch) {
52398 +                       retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
52399 +               }
52400 +               if (gintr_status.b.fetsusp) {
52401 +                       retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
52402 +               }
52403 +               if (gintr_status.b.ginnakeff) {
52404 +                       retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
52405 +               }
52406 +               if (gintr_status.b.incomplisoin) {
52407 +                       retval |=
52408 +                           dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
52409 +               }
52410 +               if (gintr_status.b.incomplisoout) {
52411 +                       retval |=
52412 +                           dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
52413 +               }
52414 +
52415 +               /* In MPI mode Device Endpoints interrupts are asserted
52416 +                * without setting outepintr and inepint bits set, so these
52417 +                * Interrupt handlers are called without checking these bit-fields
52418 +                */
52419 +               if (core_if->multiproc_int_enable) {
52420 +                       retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52421 +                       retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52422 +               }
52423 +#ifdef VERBOSE
52424 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
52425 +                           DWC_READ_REG32(&global_regs->gintsts));
52426 +#endif
52427 +               DWC_SPINUNLOCK(pcd->lock);
52428 +       }
52429 +       return retval;
52430 +}
52431 +
52432 +#endif /* DWC_HOST_ONLY */
52433 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52434 new file mode 100644
52435 index 0000000..5d310df
52436 --- /dev/null
52437 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52438 @@ -0,0 +1,1358 @@
52439 + /* ==========================================================================
52440 +  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
52441 +  * $Revision: #21 $
52442 +  * $Date: 2012/08/10 $
52443 +  * $Change: 2047372 $
52444 +  *
52445 +  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
52446 +  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
52447 +  * otherwise expressly agreed to in writing between Synopsys and you.
52448 +  *
52449 +  * The Software IS NOT an item of Licensed Software or Licensed Product under
52450 +  * any End User Software License Agreement or Agreement for Licensed Product
52451 +  * with Synopsys or any supplement thereto. You are permitted to use and
52452 +  * redistribute this Software in source and binary forms, with or without
52453 +  * modification, provided that redistributions of source code must retain this
52454 +  * notice. You may not view, use, disclose, copy or distribute this file or
52455 +  * any information contained herein except pursuant to this license grant from
52456 +  * Synopsys. If you do not agree with this notice, including the disclaimer
52457 +  * below, then you are not authorized to use the Software.
52458 +  *
52459 +  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
52460 +  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52461 +  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52462 +  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
52463 +  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52464 +  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
52465 +  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52466 +  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52467 +  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52468 +  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52469 +  * DAMAGE.
52470 +  * ========================================================================== */
52471 +#ifndef DWC_HOST_ONLY
52472 +
52473 +/** @file
52474 + * This file implements the Peripheral Controller Driver.
52475 + *
52476 + * The Peripheral Controller Driver (PCD) is responsible for
52477 + * translating requests from the Function Driver into the appropriate
52478 + * actions on the DWC_otg controller. It isolates the Function Driver
52479 + * from the specifics of the controller by providing an API to the
52480 + * Function Driver.
52481 + *
52482 + * The Peripheral Controller Driver for Linux will implement the
52483 + * Gadget API, so that the existing Gadget drivers can be used.
52484 + * (Gadget Driver is the Linux terminology for a Function Driver.)
52485 + *
52486 + * The Linux Gadget API is defined in the header file
52487 + * <code><linux/usb_gadget.h></code>.  The USB EP operations API is
52488 + * defined in the structure <code>usb_ep_ops</code> and the USB
52489 + * Controller API is defined in the structure
52490 + * <code>usb_gadget_ops</code>.
52491 + *
52492 + */
52493 +
52494 +#include "dwc_otg_os_dep.h"
52495 +#include "dwc_otg_pcd_if.h"
52496 +#include "dwc_otg_pcd.h"
52497 +#include "dwc_otg_driver.h"
52498 +#include "dwc_otg_dbg.h"
52499 +
52500 +static struct gadget_wrapper {
52501 +       dwc_otg_pcd_t *pcd;
52502 +
52503 +       struct usb_gadget gadget;
52504 +       struct usb_gadget_driver *driver;
52505 +
52506 +       struct usb_ep ep0;
52507 +       struct usb_ep in_ep[16];
52508 +       struct usb_ep out_ep[16];
52509 +
52510 +} *gadget_wrapper;
52511 +
52512 +/* Display the contents of the buffer */
52513 +extern void dump_msg(const u8 * buf, unsigned int length);
52514 +/**
52515 + * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
52516 + * if the endpoint is not found
52517 + */
52518 +static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
52519 +{
52520 +       int i;
52521 +       if (pcd->ep0.priv == handle) {
52522 +               return &pcd->ep0;
52523 +       }
52524 +
52525 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
52526 +               if (pcd->in_ep[i].priv == handle)
52527 +                       return &pcd->in_ep[i];
52528 +               if (pcd->out_ep[i].priv == handle)
52529 +                       return &pcd->out_ep[i];
52530 +       }
52531 +
52532 +       return NULL;
52533 +}
52534 +
52535 +/* USB Endpoint Operations */
52536 +/*
52537 + * The following sections briefly describe the behavior of the Gadget
52538 + * API endpoint operations implemented in the DWC_otg driver
52539 + * software. Detailed descriptions of the generic behavior of each of
52540 + * these functions can be found in the Linux header file
52541 + * include/linux/usb_gadget.h.
52542 + *
52543 + * The Gadget API provides wrapper functions for each of the function
52544 + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
52545 + * function, which then calls the underlying PCD function. The
52546 + * following sections are named according to the wrapper
52547 + * functions. Within each section, the corresponding DWC_otg PCD
52548 + * function name is specified.
52549 + *
52550 + */
52551 +
52552 +/**
52553 + * This function is called by the Gadget Driver for each EP to be
52554 + * configured for the current configuration (SET_CONFIGURATION).
52555 + *
52556 + * This function initializes the dwc_otg_ep_t data structure, and then
52557 + * calls dwc_otg_ep_activate.
52558 + */
52559 +static int ep_enable(struct usb_ep *usb_ep,
52560 +                    const struct usb_endpoint_descriptor *ep_desc)
52561 +{
52562 +       int retval;
52563 +
52564 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
52565 +
52566 +       if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
52567 +               DWC_WARN("%s, bad ep or descriptor\n", __func__);
52568 +               return -EINVAL;
52569 +       }
52570 +       if (usb_ep == &gadget_wrapper->ep0) {
52571 +               DWC_WARN("%s, bad ep(0)\n", __func__);
52572 +               return -EINVAL;
52573 +       }
52574 +
52575 +       /* Check FIFO size? */
52576 +       if (!ep_desc->wMaxPacketSize) {
52577 +               DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
52578 +               return -ERANGE;
52579 +       }
52580 +
52581 +       if (!gadget_wrapper->driver ||
52582 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52583 +               DWC_WARN("%s, bogus device state\n", __func__);
52584 +               return -ESHUTDOWN;
52585 +       }
52586 +
52587 +       /* Delete after check - MAS */
52588 +#if 0
52589 +       nat = (uint32_t) ep_desc->wMaxPacketSize;
52590 +       printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
52591 +       nat = (nat >> 11) & 0x03;
52592 +       printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
52593 +#endif
52594 +       retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
52595 +                                      (const uint8_t *)ep_desc,
52596 +                                      (void *)usb_ep);
52597 +       if (retval) {
52598 +               DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
52599 +               return -EINVAL;
52600 +       }
52601 +
52602 +       usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
52603 +
52604 +       return 0;
52605 +}
52606 +
52607 +/**
52608 + * This function is called when an EP is disabled due to disconnect or
52609 + * change in configuration. Any pending requests will terminate with a
52610 + * status of -ESHUTDOWN.
52611 + *
52612 + * This function modifies the dwc_otg_ep_t data structure for this EP,
52613 + * and then calls dwc_otg_ep_deactivate.
52614 + */
52615 +static int ep_disable(struct usb_ep *usb_ep)
52616 +{
52617 +       int retval;
52618 +
52619 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
52620 +       if (!usb_ep) {
52621 +               DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
52622 +                           usb_ep ? usb_ep->name : NULL);
52623 +               return -EINVAL;
52624 +       }
52625 +
52626 +       retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
52627 +       if (retval) {
52628 +               retval = -EINVAL;
52629 +       }
52630 +
52631 +       return retval;
52632 +}
52633 +
52634 +/**
52635 + * This function allocates a request object to use with the specified
52636 + * endpoint.
52637 + *
52638 + * @param ep The endpoint to be used with with the request
52639 + * @param gfp_flags the GFP_* flags to use.
52640 + */
52641 +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
52642 +                                                    gfp_t gfp_flags)
52643 +{
52644 +       struct usb_request *usb_req;
52645 +
52646 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
52647 +       if (0 == ep) {
52648 +               DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
52649 +               return 0;
52650 +       }
52651 +       usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
52652 +       if (0 == usb_req) {
52653 +               DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
52654 +               return 0;
52655 +       }
52656 +       memset(usb_req, 0, sizeof(*usb_req));
52657 +       usb_req->dma = DWC_DMA_ADDR_INVALID;
52658 +
52659 +       return usb_req;
52660 +}
52661 +
52662 +/**
52663 + * This function frees a request object.
52664 + *
52665 + * @param ep The endpoint associated with the request
52666 + * @param req The request being freed
52667 + */
52668 +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
52669 +{
52670 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
52671 +
52672 +       if (0 == ep || 0 == req) {
52673 +               DWC_WARN("%s() %s\n", __func__,
52674 +                        "Invalid ep or req argument!\n");
52675 +               return;
52676 +       }
52677 +
52678 +       kfree(req);
52679 +}
52680 +
52681 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52682 +/**
52683 + * This function allocates an I/O buffer to be used for a transfer
52684 + * to/from the specified endpoint.
52685 + *
52686 + * @param usb_ep The endpoint to be used with with the request
52687 + * @param bytes The desired number of bytes for the buffer
52688 + * @param dma Pointer to the buffer's DMA address; must be valid
52689 + * @param gfp_flags the GFP_* flags to use.
52690 + * @return address of a new buffer or null is buffer could not be allocated.
52691 + */
52692 +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
52693 +                                     dma_addr_t * dma, gfp_t gfp_flags)
52694 +{
52695 +       void *buf;
52696 +       dwc_otg_pcd_t *pcd = 0;
52697 +
52698 +       pcd = gadget_wrapper->pcd;
52699 +
52700 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
52701 +                   dma, gfp_flags);
52702 +
52703 +       /* Check dword alignment */
52704 +       if ((bytes & 0x3UL) != 0) {
52705 +               DWC_WARN("%s() Buffer size is not a multiple of"
52706 +                        "DWORD size (%d)", __func__, bytes);
52707 +       }
52708 +
52709 +       buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
52710 +
52711 +       /* Check dword alignment */
52712 +       if (((int)buf & 0x3UL) != 0) {
52713 +               DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
52714 +                        __func__, buf);
52715 +       }
52716 +
52717 +       return buf;
52718 +}
52719 +
52720 +/**
52721 + * This function frees an I/O buffer that was allocated by alloc_buffer.
52722 + *
52723 + * @param usb_ep the endpoint associated with the buffer
52724 + * @param buf address of the buffer
52725 + * @param dma The buffer's DMA address
52726 + * @param bytes The number of bytes of the buffer
52727 + */
52728 +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
52729 +                                   dma_addr_t dma, unsigned bytes)
52730 +{
52731 +       dwc_otg_pcd_t *pcd = 0;
52732 +
52733 +       pcd = gadget_wrapper->pcd;
52734 +
52735 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
52736 +
52737 +       dma_free_coherent(NULL, bytes, buf, dma);
52738 +}
52739 +#endif
52740 +
52741 +/**
52742 + * This function is used to submit an I/O Request to an EP.
52743 + *
52744 + *     - When the request completes the request's completion callback
52745 + *       is called to return the request to the driver.
52746 + *     - An EP, except control EPs, may have multiple requests
52747 + *       pending.
52748 + *     - Once submitted the request cannot be examined or modified.
52749 + *     - Each request is turned into one or more packets.
52750 + *     - A BULK EP can queue any amount of data; the transfer is
52751 + *       packetized.
52752 + *     - Zero length Packets are specified with the request 'zero'
52753 + *       flag.
52754 + */
52755 +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
52756 +                   gfp_t gfp_flags)
52757 +{
52758 +       dwc_otg_pcd_t *pcd;
52759 +       struct dwc_otg_pcd_ep *ep = NULL;
52760 +       int retval = 0, is_isoc_ep = 0;
52761 +       dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
52762 +
52763 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
52764 +                   __func__, usb_ep, usb_req, gfp_flags);
52765 +
52766 +       if (!usb_req || !usb_req->complete || !usb_req->buf) {
52767 +               DWC_WARN("bad params\n");
52768 +               return -EINVAL;
52769 +       }
52770 +
52771 +       if (!usb_ep) {
52772 +               DWC_WARN("bad ep\n");
52773 +               return -EINVAL;
52774 +       }
52775 +
52776 +       pcd = gadget_wrapper->pcd;
52777 +       if (!gadget_wrapper->driver ||
52778 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52779 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52780 +                           gadget_wrapper->gadget.speed);
52781 +               DWC_WARN("bogus device state\n");
52782 +               return -ESHUTDOWN;
52783 +       }
52784 +
52785 +       DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
52786 +                   usb_ep->name, usb_req, usb_req->length, usb_req->buf);
52787 +
52788 +       usb_req->status = -EINPROGRESS;
52789 +       usb_req->actual = 0;
52790 +
52791 +       ep = ep_from_handle(pcd, usb_ep);
52792 +       if (ep == NULL)
52793 +               is_isoc_ep = 0;
52794 +       else
52795 +               is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
52796 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52797 +       dma_addr = usb_req->dma;
52798 +#else
52799 +       if (GET_CORE_IF(pcd)->dma_enable) {
52800 +                dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
52801 +                struct device *dev = NULL;
52802 +
52803 +                if (otg_dev != NULL)
52804 +                        dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
52805 +
52806 +               if (usb_req->length != 0 &&
52807 +                    usb_req->dma == DWC_DMA_ADDR_INVALID) {
52808 +                        dma_addr = dma_map_single(dev, usb_req->buf,
52809 +                                                  usb_req->length,
52810 +                                                  ep->dwc_ep.is_in ?
52811 +                                                        DMA_TO_DEVICE:
52812 +                                                        DMA_FROM_DEVICE);
52813 +               }
52814 +       }
52815 +#endif
52816 +
52817 +#ifdef DWC_UTE_PER_IO
52818 +       if (is_isoc_ep == 1) {
52819 +               retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52820 +                       usb_req->length, usb_req->zero, usb_req,
52821 +                       gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
52822 +               if (retval)
52823 +                       return -EINVAL;
52824 +
52825 +               return 0;
52826 +       }
52827 +#endif
52828 +       retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52829 +                                     usb_req->length, usb_req->zero, usb_req,
52830 +                                     gfp_flags == GFP_ATOMIC ? 1 : 0);
52831 +       if (retval) {
52832 +               return -EINVAL;
52833 +       }
52834 +
52835 +       return 0;
52836 +}
52837 +
52838 +/**
52839 + * This function cancels an I/O request from an EP.
52840 + */
52841 +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
52842 +{
52843 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
52844 +
52845 +       if (!usb_ep || !usb_req) {
52846 +               DWC_WARN("bad argument\n");
52847 +               return -EINVAL;
52848 +       }
52849 +       if (!gadget_wrapper->driver ||
52850 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52851 +               DWC_WARN("bogus device state\n");
52852 +               return -ESHUTDOWN;
52853 +       }
52854 +       if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
52855 +               return -EINVAL;
52856 +       }
52857 +
52858 +       return 0;
52859 +}
52860 +
52861 +/**
52862 + * usb_ep_set_halt stalls an endpoint.
52863 + *
52864 + * usb_ep_clear_halt clears an endpoint halt and resets its data
52865 + * toggle.
52866 + *
52867 + * Both of these functions are implemented with the same underlying
52868 + * function. The behavior depends on the value argument.
52869 + *
52870 + * @param[in] usb_ep the Endpoint to halt or clear halt.
52871 + * @param[in] value
52872 + *     - 0 means clear_halt.
52873 + *     - 1 means set_halt,
52874 + *     - 2 means clear stall lock flag.
52875 + *     - 3 means set  stall lock flag.
52876 + */
52877 +static int ep_halt(struct usb_ep *usb_ep, int value)
52878 +{
52879 +       int retval = 0;
52880 +
52881 +       DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
52882 +
52883 +       if (!usb_ep) {
52884 +               DWC_WARN("bad ep\n");
52885 +               return -EINVAL;
52886 +       }
52887 +
52888 +       retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
52889 +       if (retval == -DWC_E_AGAIN) {
52890 +               return -EAGAIN;
52891 +       } else if (retval) {
52892 +               retval = -EINVAL;
52893 +       }
52894 +
52895 +       return retval;
52896 +}
52897 +
52898 +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
52899 +#if 0
52900 +/**
52901 + * ep_wedge: sets the halt feature and ignores clear requests
52902 + *
52903 + * @usb_ep: the endpoint being wedged
52904 + *
52905 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
52906 + * requests. If the gadget driver clears the halt status, it will
52907 + * automatically unwedge the endpoint.
52908 + *
52909 + * Returns zero on success, else negative errno. *
52910 + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
52911 + */
52912 +static int ep_wedge(struct usb_ep *usb_ep)
52913 +{
52914 +       int retval = 0;
52915 +
52916 +       DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
52917 +
52918 +       if (!usb_ep) {
52919 +               DWC_WARN("bad ep\n");
52920 +               return -EINVAL;
52921 +       }
52922 +
52923 +       retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
52924 +       if (retval == -DWC_E_AGAIN) {
52925 +               retval = -EAGAIN;
52926 +       } else if (retval) {
52927 +               retval = -EINVAL;
52928 +       }
52929 +
52930 +       return retval;
52931 +}
52932 +#endif
52933 +
52934 +#ifdef DWC_EN_ISOC
52935 +/**
52936 + * This function is used to submit an ISOC Transfer Request to an EP.
52937 + *
52938 + *     - Every time a sync period completes the request's completion callback
52939 + *       is called to provide data to the gadget driver.
52940 + *     - Once submitted the request cannot be modified.
52941 + *     - Each request is turned into periodic data packets untill ISO
52942 + *       Transfer is stopped..
52943 + */
52944 +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
52945 +                       gfp_t gfp_flags)
52946 +{
52947 +       int retval = 0;
52948 +
52949 +       if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
52950 +               DWC_WARN("bad params\n");
52951 +               return -EINVAL;
52952 +       }
52953 +
52954 +       if (!usb_ep) {
52955 +               DWC_PRINTF("bad params\n");
52956 +               return -EINVAL;
52957 +       }
52958 +
52959 +       req->status = -EINPROGRESS;
52960 +
52961 +       retval =
52962 +           dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
52963 +                                    req->buf1, req->dma0, req->dma1,
52964 +                                    req->sync_frame, req->data_pattern_frame,
52965 +                                    req->data_per_frame,
52966 +                                    req->
52967 +                                    flags & USB_REQ_ISO_ASAP ? -1 :
52968 +                                    req->start_frame, req->buf_proc_intrvl,
52969 +                                    req, gfp_flags == GFP_ATOMIC ? 1 : 0);
52970 +
52971 +       if (retval) {
52972 +               return -EINVAL;
52973 +       }
52974 +
52975 +       return retval;
52976 +}
52977 +
52978 +/**
52979 + * This function stops ISO EP Periodic Data Transfer.
52980 + */
52981 +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
52982 +{
52983 +       int retval = 0;
52984 +       if (!usb_ep) {
52985 +               DWC_WARN("bad ep\n");
52986 +       }
52987 +
52988 +       if (!gadget_wrapper->driver ||
52989 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52990 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52991 +                           gadget_wrapper->gadget.speed);
52992 +               DWC_WARN("bogus device state\n");
52993 +       }
52994 +
52995 +       dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
52996 +       if (retval) {
52997 +               retval = -EINVAL;
52998 +       }
52999 +
53000 +       return retval;
53001 +}
53002 +
53003 +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
53004 +                                                int packets, gfp_t gfp_flags)
53005 +{
53006 +       struct usb_iso_request *pReq = NULL;
53007 +       uint32_t req_size;
53008 +
53009 +       req_size = sizeof(struct usb_iso_request);
53010 +       req_size +=
53011 +           (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
53012 +
53013 +       pReq = kmalloc(req_size, gfp_flags);
53014 +       if (!pReq) {
53015 +               DWC_WARN("Can't allocate Iso Request\n");
53016 +               return 0;
53017 +       }
53018 +       pReq->iso_packet_desc0 = (void *)(pReq + 1);
53019 +
53020 +       pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
53021 +
53022 +       return pReq;
53023 +}
53024 +
53025 +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
53026 +{
53027 +       kfree(req);
53028 +}
53029 +
53030 +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
53031 +       .ep_ops = {
53032 +                  .enable = ep_enable,
53033 +                  .disable = ep_disable,
53034 +
53035 +                  .alloc_request = dwc_otg_pcd_alloc_request,
53036 +                  .free_request = dwc_otg_pcd_free_request,
53037 +
53038 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
53039 +                  .alloc_buffer = dwc_otg_pcd_alloc_buffer,
53040 +                  .free_buffer = dwc_otg_pcd_free_buffer,
53041 +#endif
53042 +
53043 +                  .queue = ep_queue,
53044 +                  .dequeue = ep_dequeue,
53045 +
53046 +                  .set_halt = ep_halt,
53047 +                  .fifo_status = 0,
53048 +                  .fifo_flush = 0,
53049 +                  },
53050 +       .iso_ep_start = iso_ep_start,
53051 +       .iso_ep_stop = iso_ep_stop,
53052 +       .alloc_iso_request = alloc_iso_request,
53053 +       .free_iso_request = free_iso_request,
53054 +};
53055 +
53056 +#else
53057 +
53058 +       int (*enable) (struct usb_ep *ep,
53059 +               const struct usb_endpoint_descriptor *desc);
53060 +       int (*disable) (struct usb_ep *ep);
53061 +
53062 +       struct usb_request *(*alloc_request) (struct usb_ep *ep,
53063 +               gfp_t gfp_flags);
53064 +       void (*free_request) (struct usb_ep *ep, struct usb_request *req);
53065 +
53066 +       int (*queue) (struct usb_ep *ep, struct usb_request *req,
53067 +               gfp_t gfp_flags);
53068 +       int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
53069 +
53070 +       int (*set_halt) (struct usb_ep *ep, int value);
53071 +       int (*set_wedge) (struct usb_ep *ep);
53072 +
53073 +       int (*fifo_status) (struct usb_ep *ep);
53074 +       void (*fifo_flush) (struct usb_ep *ep);
53075 +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
53076 +       .enable = ep_enable,
53077 +       .disable = ep_disable,
53078 +
53079 +       .alloc_request = dwc_otg_pcd_alloc_request,
53080 +       .free_request = dwc_otg_pcd_free_request,
53081 +
53082 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
53083 +       .alloc_buffer = dwc_otg_pcd_alloc_buffer,
53084 +       .free_buffer = dwc_otg_pcd_free_buffer,
53085 +#else
53086 +       /* .set_wedge = ep_wedge, */
53087 +        .set_wedge = NULL, /* uses set_halt instead */
53088 +#endif
53089 +
53090 +       .queue = ep_queue,
53091 +       .dequeue = ep_dequeue,
53092 +
53093 +       .set_halt = ep_halt,
53094 +       .fifo_status = 0,
53095 +       .fifo_flush = 0,
53096 +
53097 +};
53098 +
53099 +#endif /* _EN_ISOC_ */
53100 +/*     Gadget Operations */
53101 +/**
53102 + * The following gadget operations will be implemented in the DWC_otg
53103 + * PCD. Functions in the API that are not described below are not
53104 + * implemented.
53105 + *
53106 + * The Gadget API provides wrapper functions for each of the function
53107 + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
53108 + * wrapper function, which then calls the underlying PCD function. The
53109 + * following sections are named according to the wrapper functions
53110 + * (except for ioctl, which doesn't have a wrapper function). Within
53111 + * each section, the corresponding DWC_otg PCD function name is
53112 + * specified.
53113 + *
53114 + */
53115 +
53116 +/**
53117 + *Gets the USB Frame number of the last SOF.
53118 + */
53119 +static int get_frame_number(struct usb_gadget *gadget)
53120 +{
53121 +       struct gadget_wrapper *d;
53122 +
53123 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53124 +
53125 +       if (gadget == 0) {
53126 +               return -ENODEV;
53127 +       }
53128 +
53129 +       d = container_of(gadget, struct gadget_wrapper, gadget);
53130 +       return dwc_otg_pcd_get_frame_number(d->pcd);
53131 +}
53132 +
53133 +#ifdef CONFIG_USB_DWC_OTG_LPM
53134 +static int test_lpm_enabled(struct usb_gadget *gadget)
53135 +{
53136 +       struct gadget_wrapper *d;
53137 +
53138 +       d = container_of(gadget, struct gadget_wrapper, gadget);
53139 +
53140 +       return dwc_otg_pcd_is_lpm_enabled(d->pcd);
53141 +}
53142 +#endif
53143 +
53144 +/**
53145 + * Initiates Session Request Protocol (SRP) to wakeup the host if no
53146 + * session is in progress. If a session is already in progress, but
53147 + * the device is suspended, remote wakeup signaling is started.
53148 + *
53149 + */
53150 +static int wakeup(struct usb_gadget *gadget)
53151 +{
53152 +       struct gadget_wrapper *d;
53153 +
53154 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53155 +
53156 +       if (gadget == 0) {
53157 +               return -ENODEV;
53158 +       } else {
53159 +               d = container_of(gadget, struct gadget_wrapper, gadget);
53160 +       }
53161 +       dwc_otg_pcd_wakeup(d->pcd);
53162 +       return 0;
53163 +}
53164 +
53165 +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
53166 +       .get_frame = get_frame_number,
53167 +       .wakeup = wakeup,
53168 +#ifdef CONFIG_USB_DWC_OTG_LPM
53169 +       .lpm_support = test_lpm_enabled,
53170 +#endif
53171 +       // current versions must always be self-powered
53172 +};
53173 +
53174 +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
53175 +{
53176 +       int retval = -DWC_E_NOT_SUPPORTED;
53177 +       if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
53178 +               retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
53179 +                                                      (struct usb_ctrlrequest
53180 +                                                       *)bytes);
53181 +       }
53182 +
53183 +       if (retval == -ENOTSUPP) {
53184 +               retval = -DWC_E_NOT_SUPPORTED;
53185 +       } else if (retval < 0) {
53186 +               retval = -DWC_E_INVALID;
53187 +       }
53188 +
53189 +       return retval;
53190 +}
53191 +
53192 +#ifdef DWC_EN_ISOC
53193 +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53194 +                         void *req_handle, int proc_buf_num)
53195 +{
53196 +       int i, packet_count;
53197 +       struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
53198 +       struct usb_iso_request *iso_req = req_handle;
53199 +
53200 +       if (proc_buf_num) {
53201 +               iso_packet = iso_req->iso_packet_desc1;
53202 +       } else {
53203 +               iso_packet = iso_req->iso_packet_desc0;
53204 +       }
53205 +       packet_count =
53206 +           dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
53207 +       for (i = 0; i < packet_count; ++i) {
53208 +               int status;
53209 +               int actual;
53210 +               int offset;
53211 +               dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
53212 +                                                 i, &status, &actual, &offset);
53213 +               switch (status) {
53214 +               case -DWC_E_NO_DATA:
53215 +                       status = -ENODATA;
53216 +                       break;
53217 +               default:
53218 +                       if (status) {
53219 +                               DWC_PRINTF("unknown status in isoc packet\n");
53220 +                       }
53221 +
53222 +               }
53223 +               iso_packet[i].status = status;
53224 +               iso_packet[i].offset = offset;
53225 +               iso_packet[i].actual_length = actual;
53226 +       }
53227 +
53228 +       iso_req->status = 0;
53229 +       iso_req->process_buffer(ep_handle, iso_req);
53230 +
53231 +       return 0;
53232 +}
53233 +#endif /* DWC_EN_ISOC */
53234 +
53235 +#ifdef DWC_UTE_PER_IO
53236 +/**
53237 + * Copy the contents of the extended request to the Linux usb_request's
53238 + * extended part and call the gadget's completion.
53239 + *
53240 + * @param pcd                  Pointer to the pcd structure
53241 + * @param ep_handle            Void pointer to the usb_ep structure
53242 + * @param req_handle   Void pointer to the usb_request structure
53243 + * @param status               Request status returned from the portable logic
53244 + * @param ereq_port            Void pointer to the extended request structure
53245 + *                                             created in the the portable part that contains the
53246 + *                                             results of the processed iso packets.
53247 + */
53248 +static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53249 +                          void *req_handle, int32_t status, void *ereq_port)
53250 +{
53251 +       struct dwc_ute_iso_req_ext *ereqorg = NULL;
53252 +       struct dwc_iso_xreq_port *ereqport = NULL;
53253 +       struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
53254 +       int i;
53255 +       struct usb_request *req;
53256 +       //struct dwc_ute_iso_packet_descriptor *
53257 +       //int status = 0;
53258 +
53259 +       req = (struct usb_request *)req_handle;
53260 +       ereqorg = &req->ext_req;
53261 +       ereqport = (struct dwc_iso_xreq_port *)ereq_port;
53262 +       desc_org = ereqorg->per_io_frame_descs;
53263 +
53264 +       if (req && req->complete) {
53265 +               /* Copy the request data from the portable logic to our request */
53266 +               for (i = 0; i < ereqport->pio_pkt_count; i++) {
53267 +                       desc_org[i].actual_length =
53268 +                           ereqport->per_io_frame_descs[i].actual_length;
53269 +                       desc_org[i].status =
53270 +                           ereqport->per_io_frame_descs[i].status;
53271 +               }
53272 +
53273 +               switch (status) {
53274 +               case -DWC_E_SHUTDOWN:
53275 +                       req->status = -ESHUTDOWN;
53276 +                       break;
53277 +               case -DWC_E_RESTART:
53278 +                       req->status = -ECONNRESET;
53279 +                       break;
53280 +               case -DWC_E_INVALID:
53281 +                       req->status = -EINVAL;
53282 +                       break;
53283 +               case -DWC_E_TIMEOUT:
53284 +                       req->status = -ETIMEDOUT;
53285 +                       break;
53286 +               default:
53287 +                       req->status = status;
53288 +               }
53289 +
53290 +               /* And call the gadget's completion */
53291 +               req->complete(ep_handle, req);
53292 +       }
53293 +
53294 +       return 0;
53295 +}
53296 +#endif /* DWC_UTE_PER_IO */
53297 +
53298 +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53299 +                    void *req_handle, int32_t status, uint32_t actual)
53300 +{
53301 +       struct usb_request *req = (struct usb_request *)req_handle;
53302 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53303 +       struct dwc_otg_pcd_ep *ep = NULL;
53304 +#endif
53305 +
53306 +       if (req && req->complete) {
53307 +               switch (status) {
53308 +               case -DWC_E_SHUTDOWN:
53309 +                       req->status = -ESHUTDOWN;
53310 +                       break;
53311 +               case -DWC_E_RESTART:
53312 +                       req->status = -ECONNRESET;
53313 +                       break;
53314 +               case -DWC_E_INVALID:
53315 +                       req->status = -EINVAL;
53316 +                       break;
53317 +               case -DWC_E_TIMEOUT:
53318 +                       req->status = -ETIMEDOUT;
53319 +                       break;
53320 +               default:
53321 +                       req->status = status;
53322 +
53323 +               }
53324 +
53325 +               req->actual = actual;
53326 +               DWC_SPINUNLOCK(pcd->lock);
53327 +               req->complete(ep_handle, req);
53328 +               DWC_SPINLOCK(pcd->lock);
53329 +       }
53330 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53331 +       ep = ep_from_handle(pcd, ep_handle);
53332 +       if (GET_CORE_IF(pcd)->dma_enable) {
53333 +                if (req->length != 0) {
53334 +                        dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
53335 +                        struct device *dev = NULL;
53336 +
53337 +                        if (otg_dev != NULL)
53338 +                                  dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
53339 +
53340 +                       dma_unmap_single(dev, req->dma, req->length,
53341 +                                         ep->dwc_ep.is_in ?
53342 +                                                DMA_TO_DEVICE: DMA_FROM_DEVICE);
53343 +                }
53344 +       }
53345 +#endif
53346 +
53347 +       return 0;
53348 +}
53349 +
53350 +static int _connect(dwc_otg_pcd_t * pcd, int speed)
53351 +{
53352 +       gadget_wrapper->gadget.speed = speed;
53353 +       return 0;
53354 +}
53355 +
53356 +static int _disconnect(dwc_otg_pcd_t * pcd)
53357 +{
53358 +       if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
53359 +               gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
53360 +       }
53361 +       return 0;
53362 +}
53363 +
53364 +static int _resume(dwc_otg_pcd_t * pcd)
53365 +{
53366 +       if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
53367 +               gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
53368 +       }
53369 +
53370 +       return 0;
53371 +}
53372 +
53373 +static int _suspend(dwc_otg_pcd_t * pcd)
53374 +{
53375 +       if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
53376 +               gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
53377 +       }
53378 +       return 0;
53379 +}
53380 +
53381 +/**
53382 + * This function updates the otg values in the gadget structure.
53383 + */
53384 +static int _hnp_changed(dwc_otg_pcd_t * pcd)
53385 +{
53386 +
53387 +       if (!gadget_wrapper->gadget.is_otg)
53388 +               return 0;
53389 +
53390 +       gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
53391 +       gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
53392 +       gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
53393 +       return 0;
53394 +}
53395 +
53396 +static int _reset(dwc_otg_pcd_t * pcd)
53397 +{
53398 +       return 0;
53399 +}
53400 +
53401 +#ifdef DWC_UTE_CFI
53402 +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
53403 +{
53404 +       int retval = -DWC_E_INVALID;
53405 +       if (gadget_wrapper->driver->cfi_feature_setup) {
53406 +               retval =
53407 +                   gadget_wrapper->driver->
53408 +                   cfi_feature_setup(&gadget_wrapper->gadget,
53409 +                                     (struct cfi_usb_ctrlrequest *)cfi_req);
53410 +       }
53411 +
53412 +       return retval;
53413 +}
53414 +#endif
53415 +
53416 +static const struct dwc_otg_pcd_function_ops fops = {
53417 +       .complete = _complete,
53418 +#ifdef DWC_EN_ISOC
53419 +       .isoc_complete = _isoc_complete,
53420 +#endif
53421 +       .setup = _setup,
53422 +       .disconnect = _disconnect,
53423 +       .connect = _connect,
53424 +       .resume = _resume,
53425 +       .suspend = _suspend,
53426 +       .hnp_changed = _hnp_changed,
53427 +       .reset = _reset,
53428 +#ifdef DWC_UTE_CFI
53429 +       .cfi_setup = _cfi_setup,
53430 +#endif
53431 +#ifdef DWC_UTE_PER_IO
53432 +       .xisoc_complete = _xisoc_complete,
53433 +#endif
53434 +};
53435 +
53436 +/**
53437 + * This function is the top level PCD interrupt handler.
53438 + */
53439 +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
53440 +{
53441 +       dwc_otg_pcd_t *pcd = dev;
53442 +       int32_t retval = IRQ_NONE;
53443 +
53444 +       retval = dwc_otg_pcd_handle_intr(pcd);
53445 +       if (retval != 0) {
53446 +               S3C2410X_CLEAR_EINTPEND();
53447 +       }
53448 +       return IRQ_RETVAL(retval);
53449 +}
53450 +
53451 +/**
53452 + * This function initialized the usb_ep structures to there default
53453 + * state.
53454 + *
53455 + * @param d Pointer on gadget_wrapper.
53456 + */
53457 +void gadget_add_eps(struct gadget_wrapper *d)
53458 +{
53459 +       static const char *names[] = {
53460 +
53461 +               "ep0",
53462 +               "ep1in",
53463 +               "ep2in",
53464 +               "ep3in",
53465 +               "ep4in",
53466 +               "ep5in",
53467 +               "ep6in",
53468 +               "ep7in",
53469 +               "ep8in",
53470 +               "ep9in",
53471 +               "ep10in",
53472 +               "ep11in",
53473 +               "ep12in",
53474 +               "ep13in",
53475 +               "ep14in",
53476 +               "ep15in",
53477 +               "ep1out",
53478 +               "ep2out",
53479 +               "ep3out",
53480 +               "ep4out",
53481 +               "ep5out",
53482 +               "ep6out",
53483 +               "ep7out",
53484 +               "ep8out",
53485 +               "ep9out",
53486 +               "ep10out",
53487 +               "ep11out",
53488 +               "ep12out",
53489 +               "ep13out",
53490 +               "ep14out",
53491 +               "ep15out"
53492 +       };
53493 +
53494 +       int i;
53495 +       struct usb_ep *ep;
53496 +       int8_t dev_endpoints;
53497 +
53498 +       DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
53499 +
53500 +       INIT_LIST_HEAD(&d->gadget.ep_list);
53501 +       d->gadget.ep0 = &d->ep0;
53502 +       d->gadget.speed = USB_SPEED_UNKNOWN;
53503 +
53504 +       INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
53505 +
53506 +       /**
53507 +        * Initialize the EP0 structure.
53508 +        */
53509 +       ep = &d->ep0;
53510 +
53511 +       /* Init the usb_ep structure. */
53512 +       ep->name = names[0];
53513 +       ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53514 +
53515 +       /**
53516 +        * @todo NGS: What should the max packet size be set to
53517 +        * here?  Before EP type is set?
53518 +        */
53519 +       ep->maxpacket = MAX_PACKET_SIZE;
53520 +       dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
53521 +
53522 +       list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53523 +
53524 +       /**
53525 +        * Initialize the EP structures.
53526 +        */
53527 +       dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
53528 +
53529 +       for (i = 0; i < dev_endpoints; i++) {
53530 +               ep = &d->in_ep[i];
53531 +
53532 +               /* Init the usb_ep structure. */
53533 +               ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
53534 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53535 +
53536 +               /**
53537 +                * @todo NGS: What should the max packet size be set to
53538 +                * here?  Before EP type is set?
53539 +                */
53540 +               ep->maxpacket = MAX_PACKET_SIZE;
53541 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53542 +       }
53543 +
53544 +       dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
53545 +
53546 +       for (i = 0; i < dev_endpoints; i++) {
53547 +               ep = &d->out_ep[i];
53548 +
53549 +               /* Init the usb_ep structure. */
53550 +               ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
53551 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53552 +
53553 +               /**
53554 +                * @todo NGS: What should the max packet size be set to
53555 +                * here?  Before EP type is set?
53556 +                */
53557 +               ep->maxpacket = MAX_PACKET_SIZE;
53558 +
53559 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53560 +       }
53561 +
53562 +       /* remove ep0 from the list.  There is a ep0 pointer. */
53563 +       list_del_init(&d->ep0.ep_list);
53564 +
53565 +       d->ep0.maxpacket = MAX_EP0_SIZE;
53566 +}
53567 +
53568 +/**
53569 + * This function releases the Gadget device.
53570 + * required by device_unregister().
53571 + *
53572 + * @todo Should this do something?     Should it free the PCD?
53573 + */
53574 +static void dwc_otg_pcd_gadget_release(struct device *dev)
53575 +{
53576 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
53577 +}
53578 +
53579 +static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)
53580 +{
53581 +       static char pcd_name[] = "dwc_otg_pcd";
53582 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53583 +       struct gadget_wrapper *d;
53584 +       int retval;
53585 +
53586 +       d = DWC_ALLOC(sizeof(*d));
53587 +       if (d == NULL) {
53588 +               return NULL;
53589 +       }
53590 +
53591 +       memset(d, 0, sizeof(*d));
53592 +
53593 +       d->gadget.name = pcd_name;
53594 +       d->pcd = otg_dev->pcd;
53595 +
53596 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
53597 +       strcpy(d->gadget.dev.bus_id, "gadget");
53598 +#else
53599 +       dev_set_name(&d->gadget.dev, "%s", "gadget");
53600 +#endif
53601 +
53602 +       d->gadget.dev.parent = &_dev->dev;
53603 +       d->gadget.dev.release = dwc_otg_pcd_gadget_release;
53604 +       d->gadget.ops = &dwc_otg_pcd_ops;
53605 +       d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;
53606 +       d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
53607 +
53608 +       d->driver = 0;
53609 +       /* Register the gadget device */
53610 +       retval = device_register(&d->gadget.dev);
53611 +       if (retval != 0) {
53612 +               DWC_ERROR("device_register failed\n");
53613 +               DWC_FREE(d);
53614 +               return NULL;
53615 +       }
53616 +
53617 +       return d;
53618 +}
53619 +
53620 +static void free_wrapper(struct gadget_wrapper *d)
53621 +{
53622 +       if (d->driver) {
53623 +               /* should have been done already by driver model core */
53624 +               DWC_WARN("driver '%s' is still registered\n",
53625 +                        d->driver->driver.name);
53626 +               usb_gadget_unregister_driver(d->driver);
53627 +       }
53628 +
53629 +       device_unregister(&d->gadget.dev);
53630 +       DWC_FREE(d);
53631 +}
53632 +
53633 +/**
53634 + * This function initialized the PCD portion of the driver.
53635 + *
53636 + */
53637 +int pcd_init(dwc_bus_dev_t *_dev)
53638 +{
53639 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53640 +       int retval = 0;
53641 +
53642 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
53643 +
53644 +       otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
53645 +
53646 +       if (!otg_dev->pcd) {
53647 +               DWC_ERROR("dwc_otg_pcd_init failed\n");
53648 +               return -ENOMEM;
53649 +       }
53650 +
53651 +       otg_dev->pcd->otg_dev = otg_dev;
53652 +       gadget_wrapper = alloc_wrapper(_dev);
53653 +
53654 +       /*
53655 +        * Initialize EP structures
53656 +        */
53657 +       gadget_add_eps(gadget_wrapper);
53658 +       /*
53659 +        * Setup interupt handler
53660 +        */
53661 +#ifdef PLATFORM_INTERFACE
53662 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53663 +                    platform_get_irq(_dev, 0));
53664 +       retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
53665 +                            IRQF_SHARED, gadget_wrapper->gadget.name,
53666 +                            otg_dev->pcd);
53667 +       if (retval != 0) {
53668 +               DWC_ERROR("request of irq%d failed\n",
53669 +                          platform_get_irq(_dev, 0));
53670 +               free_wrapper(gadget_wrapper);
53671 +               return -EBUSY;
53672 +       }
53673 +#else
53674 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53675 +                    _dev->irq);
53676 +       retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
53677 +                            IRQF_SHARED | IRQF_DISABLED,
53678 +                            gadget_wrapper->gadget.name, otg_dev->pcd);
53679 +       if (retval != 0) {
53680 +               DWC_ERROR("request of irq%d failed\n", _dev->irq);
53681 +               free_wrapper(gadget_wrapper);
53682 +               return -EBUSY;
53683 +       }
53684 +#endif
53685 +
53686 +       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
53687 +
53688 +       return retval;
53689 +}
53690 +
53691 +/**
53692 + * Cleanup the PCD.
53693 + */
53694 +void pcd_remove(dwc_bus_dev_t *_dev)
53695 +{
53696 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53697 +       dwc_otg_pcd_t *pcd = otg_dev->pcd;
53698 +
53699 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
53700 +
53701 +       /*
53702 +        * Free the IRQ
53703 +        */
53704 +#ifdef PLATFORM_INTERFACE
53705 +       free_irq(platform_get_irq(_dev, 0), pcd);
53706 +#else
53707 +       free_irq(_dev->irq, pcd);
53708 +#endif
53709 +       dwc_otg_pcd_remove(otg_dev->pcd);
53710 +       free_wrapper(gadget_wrapper);
53711 +       otg_dev->pcd = 0;
53712 +}
53713 +
53714 +/**
53715 + * This function registers a gadget driver with the PCD.
53716 + *
53717 + * When a driver is successfully registered, it will receive control
53718 + * requests including set_configuration(), which enables non-control
53719 + * requests.  then usb traffic follows until a disconnect is reported.
53720 + * then a host may connect again, or the driver might get unbound.
53721 + *
53722 + * @param driver The driver being registered
53723 + * @param bind The bind function of gadget driver
53724 + */
53725 +
53726 +int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
53727 +{
53728 +       int retval;
53729 +
53730 +       DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
53731 +                   driver->driver.name);
53732 +
53733 +       if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
53734 +           !driver->bind ||
53735 +           !driver->unbind || !driver->disconnect || !driver->setup) {
53736 +               DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
53737 +               return -EINVAL;
53738 +       }
53739 +       if (gadget_wrapper == 0) {
53740 +               DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
53741 +               return -ENODEV;
53742 +       }
53743 +       if (gadget_wrapper->driver != 0) {
53744 +               DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
53745 +               return -EBUSY;
53746 +       }
53747 +
53748 +       /* hook up the driver */
53749 +       gadget_wrapper->driver = driver;
53750 +       gadget_wrapper->gadget.dev.driver = &driver->driver;
53751 +
53752 +       DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
53753 +       retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);
53754 +       if (retval) {
53755 +               DWC_ERROR("bind to driver %s --> error %d\n",
53756 +                         driver->driver.name, retval);
53757 +               gadget_wrapper->driver = 0;
53758 +               gadget_wrapper->gadget.dev.driver = 0;
53759 +               return retval;
53760 +       }
53761 +       DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
53762 +                   driver->driver.name);
53763 +       return 0;
53764 +}
53765 +EXPORT_SYMBOL(usb_gadget_probe_driver);
53766 +
53767 +/**
53768 + * This function unregisters a gadget driver
53769 + *
53770 + * @param driver The driver being unregistered
53771 + */
53772 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
53773 +{
53774 +       //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
53775 +
53776 +       if (gadget_wrapper == 0) {
53777 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
53778 +                           -ENODEV);
53779 +               return -ENODEV;
53780 +       }
53781 +       if (driver == 0 || driver != gadget_wrapper->driver) {
53782 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
53783 +                           -EINVAL);
53784 +               return -EINVAL;
53785 +       }
53786 +
53787 +       driver->unbind(&gadget_wrapper->gadget);
53788 +       gadget_wrapper->driver = 0;
53789 +
53790 +       DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
53791 +       return 0;
53792 +}
53793 +
53794 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
53795 +
53796 +#endif /* DWC_HOST_ONLY */
53797 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53798 new file mode 100644
53799 index 0000000..8e0e7b5
53800 --- /dev/null
53801 +++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53802 @@ -0,0 +1,2550 @@
53803 +/* ==========================================================================
53804 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
53805 + * $Revision: #98 $
53806 + * $Date: 2012/08/10 $
53807 + * $Change: 2047372 $
53808 + *
53809 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
53810 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
53811 + * otherwise expressly agreed to in writing between Synopsys and you.
53812 + *
53813 + * The Software IS NOT an item of Licensed Software or Licensed Product under
53814 + * any End User Software License Agreement or Agreement for Licensed Product
53815 + * with Synopsys or any supplement thereto. You are permitted to use and
53816 + * redistribute this Software in source and binary forms, with or without
53817 + * modification, provided that redistributions of source code must retain this
53818 + * notice. You may not view, use, disclose, copy or distribute this file or
53819 + * any information contained herein except pursuant to this license grant from
53820 + * Synopsys. If you do not agree with this notice, including the disclaimer
53821 + * below, then you are not authorized to use the Software.
53822 + *
53823 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
53824 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53825 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53826 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
53827 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53828 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53829 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
53830 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53831 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53832 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53833 + * DAMAGE.
53834 + * ========================================================================== */
53835 +
53836 +#ifndef __DWC_OTG_REGS_H__
53837 +#define __DWC_OTG_REGS_H__
53838 +
53839 +#include "dwc_otg_core_if.h"
53840 +
53841 +/**
53842 + * @file
53843 + *
53844 + * This file contains the data structures for accessing the DWC_otg core registers.
53845 + *
53846 + * The application interfaces with the HS OTG core by reading from and
53847 + * writing to the Control and Status Register (CSR) space through the
53848 + * AHB Slave interface. These registers are 32 bits wide, and the
53849 + * addresses are 32-bit-block aligned.
53850 + * CSRs are classified as follows:
53851 + * - Core Global Registers
53852 + * - Device Mode Registers
53853 + * - Device Global Registers
53854 + * - Device Endpoint Specific Registers
53855 + * - Host Mode Registers
53856 + * - Host Global Registers
53857 + * - Host Port CSRs
53858 + * - Host Channel Specific Registers
53859 + *
53860 + * Only the Core Global registers can be accessed in both Device and
53861 + * Host modes. When the HS OTG core is operating in one mode, either
53862 + * Device or Host, the application must not access registers from the
53863 + * other mode. When the core switches from one mode to another, the
53864 + * registers in the new mode of operation must be reprogrammed as they
53865 + * would be after a power-on reset.
53866 + */
53867 +
53868 +/****************************************************************************/
53869 +/** DWC_otg Core registers .
53870 + * The dwc_otg_core_global_regs structure defines the size
53871 + * and relative field offsets for the Core Global registers.
53872 + */
53873 +typedef struct dwc_otg_core_global_regs {
53874 +       /** OTG Control and Status Register.  <i>Offset: 000h</i> */
53875 +       volatile uint32_t gotgctl;
53876 +       /** OTG Interrupt Register.      <i>Offset: 004h</i> */
53877 +       volatile uint32_t gotgint;
53878 +       /**Core AHB Configuration Register.      <i>Offset: 008h</i> */
53879 +       volatile uint32_t gahbcfg;
53880 +
53881 +#define DWC_GLBINTRMASK                0x0001
53882 +#define DWC_DMAENABLE          0x0020
53883 +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
53884 +#define DWC_NPTXEMPTYLVL_HALFEMPTY     0x0000
53885 +#define DWC_PTXEMPTYLVL_EMPTY  0x0100
53886 +#define DWC_PTXEMPTYLVL_HALFEMPTY      0x0000
53887 +
53888 +       /**Core USB Configuration Register.      <i>Offset: 00Ch</i> */
53889 +       volatile uint32_t gusbcfg;
53890 +       /**Core Reset Register.  <i>Offset: 010h</i> */
53891 +       volatile uint32_t grstctl;
53892 +       /**Core Interrupt Register.      <i>Offset: 014h</i> */
53893 +       volatile uint32_t gintsts;
53894 +       /**Core Interrupt Mask Register.  <i>Offset: 018h</i> */
53895 +       volatile uint32_t gintmsk;
53896 +       /**Receive Status Queue Read Register (Read Only).      <i>Offset: 01Ch</i> */
53897 +       volatile uint32_t grxstsr;
53898 +       /**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/
53899 +       volatile uint32_t grxstsp;
53900 +       /**Receive FIFO Size Register.  <i>Offset: 024h</i> */
53901 +       volatile uint32_t grxfsiz;
53902 +       /**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */
53903 +       volatile uint32_t gnptxfsiz;
53904 +       /**Non Periodic Transmit FIFO/Queue Status Register (Read
53905 +        * Only). <i>Offset: 02Ch</i> */
53906 +       volatile uint32_t gnptxsts;
53907 +       /**I2C Access Register.  <i>Offset: 030h</i> */
53908 +       volatile uint32_t gi2cctl;
53909 +       /**PHY Vendor Control Register.  <i>Offset: 034h</i> */
53910 +       volatile uint32_t gpvndctl;
53911 +       /**General Purpose Input/Output Register.  <i>Offset: 038h</i> */
53912 +       volatile uint32_t ggpio;
53913 +       /**User ID Register.  <i>Offset: 03Ch</i> */
53914 +       volatile uint32_t guid;
53915 +       /**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */
53916 +       volatile uint32_t gsnpsid;
53917 +       /**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */
53918 +       volatile uint32_t ghwcfg1;
53919 +       /**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */
53920 +       volatile uint32_t ghwcfg2;
53921 +#define DWC_SLAVE_ONLY_ARCH 0
53922 +#define DWC_EXT_DMA_ARCH 1
53923 +#define DWC_INT_DMA_ARCH 2
53924 +
53925 +#define DWC_MODE_HNP_SRP_CAPABLE       0
53926 +#define DWC_MODE_SRP_ONLY_CAPABLE      1
53927 +#define DWC_MODE_NO_HNP_SRP_CAPABLE            2
53928 +#define DWC_MODE_SRP_CAPABLE_DEVICE            3
53929 +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
53930 +#define DWC_MODE_SRP_CAPABLE_HOST      5
53931 +#define DWC_MODE_NO_SRP_CAPABLE_HOST   6
53932 +
53933 +       /**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */
53934 +       volatile uint32_t ghwcfg3;
53935 +       /**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/
53936 +       volatile uint32_t ghwcfg4;
53937 +       /** Core LPM Configuration register <i>Offset: 054h</i>*/
53938 +       volatile uint32_t glpmcfg;
53939 +       /** Global PowerDn Register <i>Offset: 058h</i> */
53940 +       volatile uint32_t gpwrdn;
53941 +       /** Global DFIFO SW Config Register  <i>Offset: 05Ch</i> */
53942 +       volatile uint32_t gdfifocfg;
53943 +       /** ADP Control Register  <i>Offset: 060h</i> */
53944 +       volatile uint32_t adpctl;
53945 +       /** Reserved  <i>Offset: 064h-0FFh</i> */
53946 +       volatile uint32_t reserved39[39];
53947 +       /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
53948 +       volatile uint32_t hptxfsiz;
53949 +       /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
53950 +               otherwise Device Transmit FIFO#n Register.
53951 +        * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
53952 +       volatile uint32_t dtxfsiz[15];
53953 +} dwc_otg_core_global_regs_t;
53954 +
53955 +/**
53956 + * This union represents the bit fields of the Core OTG Control
53957 + * and Status Register (GOTGCTL).  Set the bits using the bit
53958 + * fields then write the <i>d32</i> value to the register.
53959 + */
53960 +typedef union gotgctl_data {
53961 +       /** raw register data */
53962 +       uint32_t d32;
53963 +       /** register bits */
53964 +       struct {
53965 +               unsigned sesreqscs:1;
53966 +               unsigned sesreq:1;
53967 +               unsigned vbvalidoven:1;
53968 +               unsigned vbvalidovval:1;
53969 +               unsigned avalidoven:1;
53970 +               unsigned avalidovval:1;
53971 +               unsigned bvalidoven:1;
53972 +               unsigned bvalidovval:1;
53973 +               unsigned hstnegscs:1;
53974 +               unsigned hnpreq:1;
53975 +               unsigned hstsethnpen:1;
53976 +               unsigned devhnpen:1;
53977 +               unsigned reserved12_15:4;
53978 +               unsigned conidsts:1;
53979 +               unsigned dbnctime:1;
53980 +               unsigned asesvld:1;
53981 +               unsigned bsesvld:1;
53982 +               unsigned otgver:1;
53983 +               unsigned reserved1:1;
53984 +               unsigned multvalidbc:5;
53985 +               unsigned chirpen:1;
53986 +               unsigned reserved28_31:4;
53987 +       } b;
53988 +} gotgctl_data_t;
53989 +
53990 +/**
53991 + * This union represents the bit fields of the Core OTG Interrupt Register
53992 + * (GOTGINT).  Set/clear the bits using the bit fields then write the <i>d32</i>
53993 + * value to the register.
53994 + */
53995 +typedef union gotgint_data {
53996 +       /** raw register data */
53997 +       uint32_t d32;
53998 +       /** register bits */
53999 +       struct {
54000 +               /** Current Mode */
54001 +               unsigned reserved0_1:2;
54002 +
54003 +               /** Session End Detected */
54004 +               unsigned sesenddet:1;
54005 +
54006 +               unsigned reserved3_7:5;
54007 +
54008 +               /** Session Request Success Status Change */
54009 +               unsigned sesreqsucstschng:1;
54010 +               /** Host Negotiation Success Status Change */
54011 +               unsigned hstnegsucstschng:1;
54012 +
54013 +               unsigned reserved10_16:7;
54014 +
54015 +               /** Host Negotiation Detected */
54016 +               unsigned hstnegdet:1;
54017 +               /** A-Device Timeout Change */
54018 +               unsigned adevtoutchng:1;
54019 +               /** Debounce Done */
54020 +               unsigned debdone:1;
54021 +               /** Multi-Valued input changed */
54022 +               unsigned mvic:1;
54023 +
54024 +               unsigned reserved31_21:11;
54025 +
54026 +       } b;
54027 +} gotgint_data_t;
54028 +
54029 +/**
54030 + * This union represents the bit fields of the Core AHB Configuration
54031 + * Register (GAHBCFG). Set/clear the bits using the bit fields then
54032 + * write the <i>d32</i> value to the register.
54033 + */
54034 +typedef union gahbcfg_data {
54035 +       /** raw register data */
54036 +       uint32_t d32;
54037 +       /** register bits */
54038 +       struct {
54039 +               unsigned glblintrmsk:1;
54040 +#define DWC_GAHBCFG_GLBINT_ENABLE              1
54041 +
54042 +               unsigned hburstlen:4;
54043 +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE       0
54044 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR         1
54045 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4                3
54046 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8                5
54047 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16       7
54048 +
54049 +               unsigned dmaenable:1;
54050 +#define DWC_GAHBCFG_DMAENABLE                  1
54051 +               unsigned reserved:1;
54052 +               unsigned nptxfemplvl_txfemplvl:1;
54053 +               unsigned ptxfemplvl:1;
54054 +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY          1
54055 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY      0
54056 +               unsigned reserved9_20:12;
54057 +               unsigned remmemsupp:1;
54058 +               unsigned notialldmawrit:1;
54059 +               unsigned ahbsingle:1;
54060 +               unsigned reserved24_31:8;
54061 +       } b;
54062 +} gahbcfg_data_t;
54063 +
54064 +/**
54065 + * This union represents the bit fields of the Core USB Configuration
54066 + * Register (GUSBCFG). Set the bits using the bit fields then write
54067 + * the <i>d32</i> value to the register.
54068 + */
54069 +typedef union gusbcfg_data {
54070 +       /** raw register data */
54071 +       uint32_t d32;
54072 +       /** register bits */
54073 +       struct {
54074 +               unsigned toutcal:3;
54075 +               unsigned phyif:1;
54076 +               unsigned ulpi_utmi_sel:1;
54077 +               unsigned fsintf:1;
54078 +               unsigned physel:1;
54079 +               unsigned ddrsel:1;
54080 +               unsigned srpcap:1;
54081 +               unsigned hnpcap:1;
54082 +               unsigned usbtrdtim:4;
54083 +               unsigned reserved1:1;
54084 +               unsigned phylpwrclksel:1;
54085 +               unsigned otgutmifssel:1;
54086 +               unsigned ulpi_fsls:1;
54087 +               unsigned ulpi_auto_res:1;
54088 +               unsigned ulpi_clk_sus_m:1;
54089 +               unsigned ulpi_ext_vbus_drv:1;
54090 +               unsigned ulpi_int_vbus_indicator:1;
54091 +               unsigned term_sel_dl_pulse:1;
54092 +               unsigned indicator_complement:1;
54093 +               unsigned indicator_pass_through:1;
54094 +               unsigned ulpi_int_prot_dis:1;
54095 +               unsigned ic_usb_cap:1;
54096 +               unsigned ic_traffic_pull_remove:1;
54097 +               unsigned tx_end_delay:1;
54098 +               unsigned force_host_mode:1;
54099 +               unsigned force_dev_mode:1;
54100 +               unsigned reserved31:1;
54101 +       } b;
54102 +} gusbcfg_data_t;
54103 +
54104 +/**
54105 + * This union represents the bit fields of the Core Reset Register
54106 + * (GRSTCTL).  Set/clear the bits using the bit fields then write the
54107 + * <i>d32</i> value to the register.
54108 + */
54109 +typedef union grstctl_data {
54110 +       /** raw register data */
54111 +       uint32_t d32;
54112 +       /** register bits */
54113 +       struct {
54114 +               /** Core Soft Reset (CSftRst) (Device and Host)
54115 +                *
54116 +                * The application can flush the control logic in the
54117 +                * entire core using this bit. This bit resets the
54118 +                * pipelines in the AHB Clock domain as well as the
54119 +                * PHY Clock domain.
54120 +                *
54121 +                * The state machines are reset to an IDLE state, the
54122 +                * control bits in the CSRs are cleared, all the
54123 +                * transmit FIFOs and the receive FIFO are flushed.
54124 +                *
54125 +                * The status mask bits that control the generation of
54126 +                * the interrupt, are cleared, to clear the
54127 +                * interrupt. The interrupt status bits are not
54128 +                * cleared, so the application can get the status of
54129 +                * any events that occurred in the core after it has
54130 +                * set this bit.
54131 +                *
54132 +                * Any transactions on the AHB are terminated as soon
54133 +                * as possible following the protocol. Any
54134 +                * transactions on the USB are terminated immediately.
54135 +                *
54136 +                * The configuration settings in the CSRs are
54137 +                * unchanged, so the software doesn't have to
54138 +                * reprogram these registers (Device
54139 +                * Configuration/Host Configuration/Core System
54140 +                * Configuration/Core PHY Configuration).
54141 +                *
54142 +                * The application can write to this bit, any time it
54143 +                * wants to reset the core. This is a self clearing
54144 +                * bit and the core clears this bit after all the
54145 +                * necessary logic is reset in the core, which may
54146 +                * take several clocks, depending on the current state
54147 +                * of the core.
54148 +                */
54149 +               unsigned csftrst:1;
54150 +               /** Hclk Soft Reset
54151 +                *
54152 +                * The application uses this bit to reset the control logic in
54153 +                * the AHB clock domain. Only AHB clock domain pipelines are
54154 +                * reset.
54155 +                */
54156 +               unsigned hsftrst:1;
54157 +               /** Host Frame Counter Reset (Host Only)<br>
54158 +                *
54159 +                * The application can reset the (micro)frame number
54160 +                * counter inside the core, using this bit. When the
54161 +                * (micro)frame counter is reset, the subsequent SOF
54162 +                * sent out by the core, will have a (micro)frame
54163 +                * number of 0.
54164 +                */
54165 +               unsigned hstfrm:1;
54166 +               /** In Token Sequence Learning Queue Flush
54167 +                * (INTknQFlsh) (Device Only)
54168 +                */
54169 +               unsigned intknqflsh:1;
54170 +               /** RxFIFO Flush (RxFFlsh) (Device and Host)
54171 +                *
54172 +                * The application can flush the entire Receive FIFO
54173 +                * using this bit. The application must first
54174 +                * ensure that the core is not in the middle of a
54175 +                * transaction. The application should write into
54176 +                * this bit, only after making sure that neither the
54177 +                * DMA engine is reading from the RxFIFO nor the MAC
54178 +                * is writing the data in to the FIFO. The
54179 +                * application should wait until the bit is cleared
54180 +                * before performing any other operations. This bit
54181 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54182 +                * to clear.
54183 +                */
54184 +               unsigned rxfflsh:1;
54185 +               /** TxFIFO Flush (TxFFlsh) (Device and Host).
54186 +                *
54187 +                * This bit is used to selectively flush a single or
54188 +                * all transmit FIFOs. The application must first
54189 +                * ensure that the core is not in the middle of a
54190 +                * transaction. The application should write into
54191 +                * this bit, only after making sure that neither the
54192 +                * DMA engine is writing into the TxFIFO nor the MAC
54193 +                * is reading the data out of the FIFO. The
54194 +                * application should wait until the core clears this
54195 +                * bit, before performing any operations. This bit
54196 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54197 +                * to clear.
54198 +                */
54199 +               unsigned txfflsh:1;
54200 +
54201 +               /** TxFIFO Number (TxFNum) (Device and Host).
54202 +                *
54203 +                * This is the FIFO number which needs to be flushed,
54204 +                * using the TxFIFO Flush bit. This field should not
54205 +                * be changed until the TxFIFO Flush bit is cleared by
54206 +                * the core.
54207 +                *       - 0x0 : Non Periodic TxFIFO Flush
54208 +                *       - 0x1 : Periodic TxFIFO #1 Flush in device mode
54209 +                *         or Periodic TxFIFO in host mode
54210 +                *       - 0x2 : Periodic TxFIFO #2 Flush in device mode.
54211 +                *       - ...
54212 +                *       - 0xF : Periodic TxFIFO #15 Flush in device mode
54213 +                *       - 0x10: Flush all the Transmit NonPeriodic and
54214 +                *         Transmit Periodic FIFOs in the core
54215 +                */
54216 +               unsigned txfnum:5;
54217 +               /** Reserved */
54218 +               unsigned reserved11_29:19;
54219 +               /** DMA Request Signal.  Indicated DMA request is in
54220 +                * probress. Used for debug purpose. */
54221 +               unsigned dmareq:1;
54222 +               /** AHB Master Idle.  Indicates the AHB Master State
54223 +                * Machine is in IDLE condition. */
54224 +               unsigned ahbidle:1;
54225 +       } b;
54226 +} grstctl_t;
54227 +
54228 +/**
54229 + * This union represents the bit fields of the Core Interrupt Mask
54230 + * Register (GINTMSK). Set/clear the bits using the bit fields then
54231 + * write the <i>d32</i> value to the register.
54232 + */
54233 +typedef union gintmsk_data {
54234 +       /** raw register data */
54235 +       uint32_t d32;
54236 +       /** register bits */
54237 +       struct {
54238 +               unsigned reserved0:1;
54239 +               unsigned modemismatch:1;
54240 +               unsigned otgintr:1;
54241 +               unsigned sofintr:1;
54242 +               unsigned rxstsqlvl:1;
54243 +               unsigned nptxfempty:1;
54244 +               unsigned ginnakeff:1;
54245 +               unsigned goutnakeff:1;
54246 +               unsigned ulpickint:1;
54247 +               unsigned i2cintr:1;
54248 +               unsigned erlysuspend:1;
54249 +               unsigned usbsuspend:1;
54250 +               unsigned usbreset:1;
54251 +               unsigned enumdone:1;
54252 +               unsigned isooutdrop:1;
54253 +               unsigned eopframe:1;
54254 +               unsigned restoredone:1;
54255 +               unsigned epmismatch:1;
54256 +               unsigned inepintr:1;
54257 +               unsigned outepintr:1;
54258 +               unsigned incomplisoin:1;
54259 +               unsigned incomplisoout:1;
54260 +               unsigned fetsusp:1;
54261 +               unsigned resetdet:1;
54262 +               unsigned portintr:1;
54263 +               unsigned hcintr:1;
54264 +               unsigned ptxfempty:1;
54265 +               unsigned lpmtranrcvd:1;
54266 +               unsigned conidstschng:1;
54267 +               unsigned disconnect:1;
54268 +               unsigned sessreqintr:1;
54269 +               unsigned wkupintr:1;
54270 +       } b;
54271 +} gintmsk_data_t;
54272 +/**
54273 + * This union represents the bit fields of the Core Interrupt Register
54274 + * (GINTSTS).  Set/clear the bits using the bit fields then write the
54275 + * <i>d32</i> value to the register.
54276 + */
54277 +typedef union gintsts_data {
54278 +       /** raw register data */
54279 +       uint32_t d32;
54280 +#define DWC_SOF_INTR_MASK 0x0008
54281 +       /** register bits */
54282 +       struct {
54283 +#define DWC_HOST_MODE 1
54284 +               unsigned curmode:1;
54285 +               unsigned modemismatch:1;
54286 +               unsigned otgintr:1;
54287 +               unsigned sofintr:1;
54288 +               unsigned rxstsqlvl:1;
54289 +               unsigned nptxfempty:1;
54290 +               unsigned ginnakeff:1;
54291 +               unsigned goutnakeff:1;
54292 +               unsigned ulpickint:1;
54293 +               unsigned i2cintr:1;
54294 +               unsigned erlysuspend:1;
54295 +               unsigned usbsuspend:1;
54296 +               unsigned usbreset:1;
54297 +               unsigned enumdone:1;
54298 +               unsigned isooutdrop:1;
54299 +               unsigned eopframe:1;
54300 +               unsigned restoredone:1;
54301 +               unsigned epmismatch:1;
54302 +               unsigned inepint:1;
54303 +               unsigned outepintr:1;
54304 +               unsigned incomplisoin:1;
54305 +               unsigned incomplisoout:1;
54306 +               unsigned fetsusp:1;
54307 +               unsigned resetdet:1;
54308 +               unsigned portintr:1;
54309 +               unsigned hcintr:1;
54310 +               unsigned ptxfempty:1;
54311 +               unsigned lpmtranrcvd:1;
54312 +               unsigned conidstschng:1;
54313 +               unsigned disconnect:1;
54314 +               unsigned sessreqintr:1;
54315 +               unsigned wkupintr:1;
54316 +       } b;
54317 +} gintsts_data_t;
54318 +
54319 +/**
54320 + * This union represents the bit fields in the Device Receive Status Read and
54321 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54322 + * element then read out the bits using the <i>b</i>it elements.
54323 + */
54324 +typedef union device_grxsts_data {
54325 +       /** raw register data */
54326 +       uint32_t d32;
54327 +       /** register bits */
54328 +       struct {
54329 +               unsigned epnum:4;
54330 +               unsigned bcnt:11;
54331 +               unsigned dpid:2;
54332 +
54333 +#define DWC_STS_DATA_UPDT              0x2     // OUT Data Packet
54334 +#define DWC_STS_XFER_COMP              0x3     // OUT Data Transfer Complete
54335 +
54336 +#define DWC_DSTS_GOUT_NAK              0x1     // Global OUT NAK
54337 +#define DWC_DSTS_SETUP_COMP            0x4     // Setup Phase Complete
54338 +#define DWC_DSTS_SETUP_UPDT 0x6        // SETUP Packet
54339 +               unsigned pktsts:4;
54340 +               unsigned fn:4;
54341 +               unsigned reserved25_31:7;
54342 +       } b;
54343 +} device_grxsts_data_t;
54344 +
54345 +/**
54346 + * This union represents the bit fields in the Host Receive Status Read and
54347 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54348 + * element then read out the bits using the <i>b</i>it elements.
54349 + */
54350 +typedef union host_grxsts_data {
54351 +       /** raw register data */
54352 +       uint32_t d32;
54353 +       /** register bits */
54354 +       struct {
54355 +               unsigned chnum:4;
54356 +               unsigned bcnt:11;
54357 +               unsigned dpid:2;
54358 +
54359 +               unsigned pktsts:4;
54360 +#define DWC_GRXSTS_PKTSTS_IN                     0x2
54361 +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP   0x3
54362 +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
54363 +#define DWC_GRXSTS_PKTSTS_CH_HALTED              0x7
54364 +
54365 +               unsigned reserved21_31:11;
54366 +       } b;
54367 +} host_grxsts_data_t;
54368 +
54369 +/**
54370 + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
54371 + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element
54372 + * then read out the bits using the <i>b</i>it elements.
54373 + */
54374 +typedef union fifosize_data {
54375 +       /** raw register data */
54376 +       uint32_t d32;
54377 +       /** register bits */
54378 +       struct {
54379 +               unsigned startaddr:16;
54380 +               unsigned depth:16;
54381 +       } b;
54382 +} fifosize_data_t;
54383 +
54384 +/**
54385 + * This union represents the bit fields in the Non-Periodic Transmit
54386 + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
54387 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54388 + * elements.
54389 + */
54390 +typedef union gnptxsts_data {
54391 +       /** raw register data */
54392 +       uint32_t d32;
54393 +       /** register bits */
54394 +       struct {
54395 +               unsigned nptxfspcavail:16;
54396 +               unsigned nptxqspcavail:8;
54397 +               /** Top of the Non-Periodic Transmit Request Queue
54398 +                *      - bit 24 - Terminate (Last entry for the selected
54399 +                *        channel/EP)
54400 +                *      - bits 26:25 - Token Type
54401 +                *        - 2'b00 - IN/OUT
54402 +                *        - 2'b01 - Zero Length OUT
54403 +                *        - 2'b10 - PING/Complete Split
54404 +                *        - 2'b11 - Channel Halt
54405 +                *      - bits 30:27 - Channel/EP Number
54406 +                */
54407 +               unsigned nptxqtop_terminate:1;
54408 +               unsigned nptxqtop_token:2;
54409 +               unsigned nptxqtop_chnep:4;
54410 +               unsigned reserved:1;
54411 +       } b;
54412 +} gnptxsts_data_t;
54413 +
54414 +/**
54415 + * This union represents the bit fields in the Transmit
54416 + * FIFO Status Register (DTXFSTS). Read the register into the
54417 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54418 + * elements.
54419 + */
54420 +typedef union dtxfsts_data {
54421 +       /** raw register data */
54422 +       uint32_t d32;
54423 +       /** register bits */
54424 +       struct {
54425 +               unsigned txfspcavail:16;
54426 +               unsigned reserved:16;
54427 +       } b;
54428 +} dtxfsts_data_t;
54429 +
54430 +/**
54431 + * This union represents the bit fields in the I2C Control Register
54432 + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
54433 + * bits using the <i>b</i>it elements.
54434 + */
54435 +typedef union gi2cctl_data {
54436 +       /** raw register data */
54437 +       uint32_t d32;
54438 +       /** register bits */
54439 +       struct {
54440 +               unsigned rwdata:8;
54441 +               unsigned regaddr:8;
54442 +               unsigned addr:7;
54443 +               unsigned i2cen:1;
54444 +               unsigned ack:1;
54445 +               unsigned i2csuspctl:1;
54446 +               unsigned i2cdevaddr:2;
54447 +               unsigned i2cdatse0:1;
54448 +               unsigned reserved:1;
54449 +               unsigned rw:1;
54450 +               unsigned bsydne:1;
54451 +       } b;
54452 +} gi2cctl_data_t;
54453 +
54454 +/**
54455 + * This union represents the bit fields in the PHY Vendor Control Register
54456 + * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the
54457 + * bits using the <i>b</i>it elements.
54458 + */
54459 +typedef union gpvndctl_data {
54460 +       /** raw register data */
54461 +       uint32_t d32;
54462 +       /** register bits */
54463 +       struct {
54464 +               unsigned regdata:8;
54465 +               unsigned vctrl:8;
54466 +               unsigned regaddr16_21:6;
54467 +               unsigned regwr:1;
54468 +               unsigned reserved23_24:2;
54469 +               unsigned newregreq:1;
54470 +               unsigned vstsbsy:1;
54471 +               unsigned vstsdone:1;
54472 +               unsigned reserved28_30:3;
54473 +               unsigned disulpidrvr:1;
54474 +       } b;
54475 +} gpvndctl_data_t;
54476 +
54477 +/**
54478 + * This union represents the bit fields in the General Purpose
54479 + * Input/Output Register (GGPIO).
54480 + * Read the register into the <i>d32</i> element then read out the
54481 + * bits using the <i>b</i>it elements.
54482 + */
54483 +typedef union ggpio_data {
54484 +       /** raw register data */
54485 +       uint32_t d32;
54486 +       /** register bits */
54487 +       struct {
54488 +               unsigned gpi:16;
54489 +               unsigned gpo:16;
54490 +       } b;
54491 +} ggpio_data_t;
54492 +
54493 +/**
54494 + * This union represents the bit fields in the User ID Register
54495 + * (GUID). Read the register into the <i>d32</i> element then read out the
54496 + * bits using the <i>b</i>it elements.
54497 + */
54498 +typedef union guid_data {
54499 +       /** raw register data */
54500 +       uint32_t d32;
54501 +       /** register bits */
54502 +       struct {
54503 +               unsigned rwdata:32;
54504 +       } b;
54505 +} guid_data_t;
54506 +
54507 +/**
54508 + * This union represents the bit fields in the Synopsys ID Register
54509 + * (GSNPSID). Read the register into the <i>d32</i> element then read out the
54510 + * bits using the <i>b</i>it elements.
54511 + */
54512 +typedef union gsnpsid_data {
54513 +       /** raw register data */
54514 +       uint32_t d32;
54515 +       /** register bits */
54516 +       struct {
54517 +               unsigned rwdata:32;
54518 +       } b;
54519 +} gsnpsid_data_t;
54520 +
54521 +/**
54522 + * This union represents the bit fields in the User HW Config1
54523 + * Register.  Read the register into the <i>d32</i> element then read
54524 + * out the bits using the <i>b</i>it elements.
54525 + */
54526 +typedef union hwcfg1_data {
54527 +       /** raw register data */
54528 +       uint32_t d32;
54529 +       /** register bits */
54530 +       struct {
54531 +               unsigned ep_dir0:2;
54532 +               unsigned ep_dir1:2;
54533 +               unsigned ep_dir2:2;
54534 +               unsigned ep_dir3:2;
54535 +               unsigned ep_dir4:2;
54536 +               unsigned ep_dir5:2;
54537 +               unsigned ep_dir6:2;
54538 +               unsigned ep_dir7:2;
54539 +               unsigned ep_dir8:2;
54540 +               unsigned ep_dir9:2;
54541 +               unsigned ep_dir10:2;
54542 +               unsigned ep_dir11:2;
54543 +               unsigned ep_dir12:2;
54544 +               unsigned ep_dir13:2;
54545 +               unsigned ep_dir14:2;
54546 +               unsigned ep_dir15:2;
54547 +       } b;
54548 +} hwcfg1_data_t;
54549 +
54550 +/**
54551 + * This union represents the bit fields in the User HW Config2
54552 + * Register.  Read the register into the <i>d32</i> element then read
54553 + * out the bits using the <i>b</i>it elements.
54554 + */
54555 +typedef union hwcfg2_data {
54556 +       /** raw register data */
54557 +       uint32_t d32;
54558 +       /** register bits */
54559 +       struct {
54560 +               /* GHWCFG2 */
54561 +               unsigned op_mode:3;
54562 +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
54563 +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
54564 +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
54565 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
54566 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
54567 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
54568 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
54569 +
54570 +               unsigned architecture:2;
54571 +               unsigned point2point:1;
54572 +               unsigned hs_phy_type:2;
54573 +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
54574 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
54575 +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
54576 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
54577 +
54578 +               unsigned fs_phy_type:2;
54579 +               unsigned num_dev_ep:4;
54580 +               unsigned num_host_chan:4;
54581 +               unsigned perio_ep_supported:1;
54582 +               unsigned dynamic_fifo:1;
54583 +               unsigned multi_proc_int:1;
54584 +               unsigned reserved21:1;
54585 +               unsigned nonperio_tx_q_depth:2;
54586 +               unsigned host_perio_tx_q_depth:2;
54587 +               unsigned dev_token_q_depth:5;
54588 +               unsigned otg_enable_ic_usb:1;
54589 +       } b;
54590 +} hwcfg2_data_t;
54591 +
54592 +/**
54593 + * This union represents the bit fields in the User HW Config3
54594 + * Register.  Read the register into the <i>d32</i> element then read
54595 + * out the bits using the <i>b</i>it elements.
54596 + */
54597 +typedef union hwcfg3_data {
54598 +       /** raw register data */
54599 +       uint32_t d32;
54600 +       /** register bits */
54601 +       struct {
54602 +               /* GHWCFG3 */
54603 +               unsigned xfer_size_cntr_width:4;
54604 +               unsigned packet_size_cntr_width:3;
54605 +               unsigned otg_func:1;
54606 +               unsigned i2c:1;
54607 +               unsigned vendor_ctrl_if:1;
54608 +               unsigned optional_features:1;
54609 +               unsigned synch_reset_type:1;
54610 +               unsigned adp_supp:1;
54611 +               unsigned otg_enable_hsic:1;
54612 +               unsigned bc_support:1;
54613 +               unsigned otg_lpm_en:1;
54614 +               unsigned dfifo_depth:16;
54615 +       } b;
54616 +} hwcfg3_data_t;
54617 +
54618 +/**
54619 + * This union represents the bit fields in the User HW Config4
54620 + * Register.  Read the register into the <i>d32</i> element then read
54621 + * out the bits using the <i>b</i>it elements.
54622 + */
54623 +typedef union hwcfg4_data {
54624 +       /** raw register data */
54625 +       uint32_t d32;
54626 +       /** register bits */
54627 +       struct {
54628 +               unsigned num_dev_perio_in_ep:4;
54629 +               unsigned power_optimiz:1;
54630 +               unsigned min_ahb_freq:1;
54631 +               unsigned hiber:1;
54632 +               unsigned xhiber:1;
54633 +               unsigned reserved:6;
54634 +               unsigned utmi_phy_data_width:2;
54635 +               unsigned num_dev_mode_ctrl_ep:4;
54636 +               unsigned iddig_filt_en:1;
54637 +               unsigned vbus_valid_filt_en:1;
54638 +               unsigned a_valid_filt_en:1;
54639 +               unsigned b_valid_filt_en:1;
54640 +               unsigned session_end_filt_en:1;
54641 +               unsigned ded_fifo_en:1;
54642 +               unsigned num_in_eps:4;
54643 +               unsigned desc_dma:1;
54644 +               unsigned desc_dma_dyn:1;
54645 +       } b;
54646 +} hwcfg4_data_t;
54647 +
54648 +/**
54649 + * This union represents the bit fields of the Core LPM Configuration
54650 + * Register (GLPMCFG). Set the bits using bit fields then write
54651 + * the <i>d32</i> value to the register.
54652 + */
54653 +typedef union glpmctl_data {
54654 +       /** raw register data */
54655 +       uint32_t d32;
54656 +       /** register bits */
54657 +       struct {
54658 +               /** LPM-Capable (LPMCap) (Device and Host)
54659 +                * The application uses this bit to control
54660 +                * the DWC_otg core LPM capabilities.
54661 +                */
54662 +               unsigned lpm_cap_en:1;
54663 +               /** LPM response programmed by application (AppL1Res) (Device)
54664 +                * Handshake response to LPM token pre-programmed
54665 +                * by device application software.
54666 +                */
54667 +               unsigned appl_resp:1;
54668 +               /** Host Initiated Resume Duration (HIRD) (Device and Host)
54669 +                * In Host mode this field indicates the value of HIRD
54670 +                * to be sent in an LPM transaction.
54671 +                * In Device mode this field is updated with the
54672 +                * Received LPM Token HIRD bmAttribute
54673 +                * when an ACK/NYET/STALL response is sent
54674 +                * to an LPM transaction.
54675 +                */
54676 +               unsigned hird:4;
54677 +               /** RemoteWakeEnable (bRemoteWake) (Device and Host)
54678 +                * In Host mode this bit indicates the value of remote
54679 +                * wake up to be sent in wIndex field of LPM transaction.
54680 +                * In Device mode this field is updated with the
54681 +                * Received LPM Token bRemoteWake bmAttribute
54682 +                * when an ACK/NYET/STALL response is sent
54683 +                * to an LPM transaction.
54684 +                */
54685 +               unsigned rem_wkup_en:1;
54686 +               /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
54687 +                * The application uses this bit to control
54688 +                * the utmi_sleep_n assertion to the PHY when in L1 state.
54689 +                */
54690 +               unsigned en_utmi_sleep:1;
54691 +               /** HIRD Threshold (HIRD_Thres) (Device and Host)
54692 +                */
54693 +               unsigned hird_thres:5;
54694 +               /** LPM Response (CoreL1Res) (Device and Host)
54695 +                * In Host mode this bit contains handsake response to
54696 +                * LPM transaction.
54697 +                * In Device mode the response of the core to
54698 +                * LPM transaction received is reflected in these two bits.
54699 +                       - 0x0 : ERROR (No handshake response)
54700 +                       - 0x1 : STALL
54701 +                       - 0x2 : NYET
54702 +                       - 0x3 : ACK
54703 +                */
54704 +               unsigned lpm_resp:2;
54705 +               /** Port Sleep Status (SlpSts) (Device and Host)
54706 +                * This bit is set as long as a Sleep condition
54707 +                * is present on the USB bus.
54708 +                */
54709 +               unsigned prt_sleep_sts:1;
54710 +               /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
54711 +                * Indicates that the application or host
54712 +                * can start resume from Sleep state.
54713 +                */
54714 +               unsigned sleep_state_resumeok:1;
54715 +               /** LPM channel Index (LPM_Chnl_Indx) (Host)
54716 +                * The channel number on which the LPM transaction
54717 +                * has to be applied while sending
54718 +                * an LPM transaction to the local device.
54719 +                */
54720 +               unsigned lpm_chan_index:4;
54721 +               /** LPM Retry Count (LPM_Retry_Cnt) (Host)
54722 +                * Number host retries that would be performed
54723 +                * if the device response was not valid response.
54724 +                */
54725 +               unsigned retry_count:3;
54726 +               /** Send LPM Transaction (SndLPM) (Host)
54727 +                * When set by application software,
54728 +                * an LPM transaction containing two tokens
54729 +                * is sent.
54730 +                */
54731 +               unsigned send_lpm:1;
54732 +               /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
54733 +                * Number of LPM Host Retries still remaining
54734 +                * to be transmitted for the current LPM sequence
54735 +                */
54736 +               unsigned retry_count_sts:3;
54737 +               unsigned reserved28_29:2;
54738 +               /** In host mode once this bit is set, the host
54739 +                * configures to drive the HSIC Idle state on the bus.
54740 +                * It then waits for the  device to initiate the Connect sequence.
54741 +                * In device mode once this bit is set, the device waits for
54742 +                * the HSIC Idle line state on the bus. Upon receving the Idle
54743 +                * line state, it initiates the HSIC Connect sequence.
54744 +                */
54745 +               unsigned hsic_connect:1;
54746 +               /** This bit overrides and functionally inverts
54747 +                * the if_select_hsic input port signal.
54748 +                */
54749 +               unsigned inv_sel_hsic:1;
54750 +       } b;
54751 +} glpmcfg_data_t;
54752 +
54753 +/**
54754 + * This union represents the bit fields of the Core ADP Timer, Control and
54755 + * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write
54756 + * the <i>d32</i> value to the register.
54757 + */
54758 +typedef union adpctl_data {
54759 +       /** raw register data */
54760 +       uint32_t d32;
54761 +       /** register bits */
54762 +       struct {
54763 +               /** Probe Discharge (PRB_DSCHG)
54764 +                *  These bits set the times for TADP_DSCHG.
54765 +                *  These bits are defined as follows:
54766 +                *  2'b00 - 4 msec
54767 +                *  2'b01 - 8 msec
54768 +                *  2'b10 - 16 msec
54769 +                *  2'b11 - 32 msec
54770 +                */
54771 +               unsigned prb_dschg:2;
54772 +               /** Probe Delta (PRB_DELTA)
54773 +                *  These bits set the resolution for RTIM   value.
54774 +                *  The bits are defined in units of 32 kHz clock cycles as follows:
54775 +                *  2'b00  -  1 cycles
54776 +                *  2'b01  -  2 cycles
54777 +                *  2'b10 -  3 cycles
54778 +                *  2'b11 - 4 cycles
54779 +                *  For example if this value is chosen to 2'b01, it means that RTIM
54780 +                *  increments for every 3(three) 32Khz clock cycles.
54781 +                */
54782 +               unsigned prb_delta:2;
54783 +               /** Probe Period (PRB_PER)
54784 +                *  These bits sets the TADP_PRD as shown in Figure 4 as follows:
54785 +                *  2'b00  -  0.625 to 0.925 sec (typical 0.775 sec)
54786 +                *  2'b01  -  1.25 to 1.85 sec (typical 1.55 sec)
54787 +                *  2'b10  -  1.9 to 2.6 sec (typical 2.275 sec)
54788 +                *  2'b11  -  Reserved
54789 +                */
54790 +               unsigned prb_per:2;
54791 +               /** These bits capture the latest time it took for VBUS to ramp from
54792 +                *  VADP_SINK to VADP_PRB.
54793 +                *  0x000  -  1 cycles
54794 +                *  0x001  -  2 cycles
54795 +                *  0x002  -  3 cycles
54796 +                *  etc
54797 +                *  0x7FF  -  2048 cycles
54798 +                *  A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.
54799 +               */
54800 +               unsigned rtim:11;
54801 +               /** Enable Probe (EnaPrb)
54802 +                *  When programmed to 1'b1, the core performs a probe operation.
54803 +                *  This bit is valid only if OTG_Ver = 1'b1.
54804 +                */
54805 +               unsigned enaprb:1;
54806 +               /** Enable Sense (EnaSns)
54807 +                *  When programmed to 1'b1, the core performs a Sense operation.
54808 +                *  This bit is valid only if OTG_Ver = 1'b1.
54809 +                */
54810 +               unsigned enasns:1;
54811 +               /** ADP Reset (ADPRes)
54812 +                *  When set, ADP controller is reset.
54813 +                *  This bit is valid only if OTG_Ver = 1'b1.
54814 +                */
54815 +               unsigned adpres:1;
54816 +               /** ADP Enable (ADPEn)
54817 +                *  When set, the core performs either ADP probing or sensing
54818 +                *  based on EnaPrb or EnaSns.
54819 +                *  This bit is valid only if OTG_Ver = 1'b1.
54820 +                */
54821 +               unsigned adpen:1;
54822 +               /** ADP Probe Interrupt (ADP_PRB_INT)
54823 +                *  When this bit is set, it means that the VBUS
54824 +                *  voltage is greater than VADP_PRB or VADP_PRB is reached.
54825 +                *  This bit is valid only if OTG_Ver = 1'b1.
54826 +                */
54827 +               unsigned adp_prb_int:1;
54828 +               /**
54829 +                *  ADP Sense Interrupt (ADP_SNS_INT)
54830 +                *  When this bit is set, it means that the VBUS voltage is greater than
54831 +                *  VADP_SNS value or VADP_SNS is reached.
54832 +                *  This bit is valid only if OTG_Ver = 1'b1.
54833 +                */
54834 +               unsigned adp_sns_int:1;
54835 +               /** ADP Tomeout Interrupt (ADP_TMOUT_INT)
54836 +                *  This bit is relevant only for an ADP probe.
54837 +                *  When this bit is set, it means that the ramp time has
54838 +                *  completed ie ADPCTL.RTIM has reached its terminal value
54839 +                *  of 0x7FF.  This is a debug feature that allows software
54840 +                *  to read the ramp time after each cycle.
54841 +                *  This bit is valid only if OTG_Ver = 1'b1.
54842 +                */
54843 +               unsigned adp_tmout_int:1;
54844 +               /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)
54845 +                *  When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.
54846 +                *  This bit is valid only if OTG_Ver = 1'b1.
54847 +                */
54848 +               unsigned adp_prb_int_msk:1;
54849 +               /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)
54850 +                *  When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.
54851 +                *  This bit is valid only if OTG_Ver = 1'b1.
54852 +                */
54853 +               unsigned adp_sns_int_msk:1;
54854 +               /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)
54855 +                *  When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.
54856 +                *  This bit is valid only if OTG_Ver = 1'b1.
54857 +                */
54858 +               unsigned adp_tmout_int_msk:1;
54859 +               /** Access Request
54860 +                * 2'b00 - Read/Write Valid (updated by the core)
54861 +                * 2'b01 - Read
54862 +                * 2'b00 - Write
54863 +                * 2'b00 - Reserved
54864 +                */
54865 +               unsigned ar:2;
54866 +                /** Reserved */
54867 +               unsigned reserved29_31:3;
54868 +       } b;
54869 +} adpctl_data_t;
54870 +
54871 +////////////////////////////////////////////
54872 +// Device Registers
54873 +/**
54874 + * Device Global Registers. <i>Offsets 800h-BFFh</i>
54875 + *
54876 + * The following structures define the size and relative field offsets
54877 + * for the Device Mode Registers.
54878 + *
54879 + * <i>These registers are visible only in Device mode and must not be
54880 + * accessed in Host mode, as the results are unknown.</i>
54881 + */
54882 +typedef struct dwc_otg_dev_global_regs {
54883 +       /** Device Configuration Register. <i>Offset 800h</i> */
54884 +       volatile uint32_t dcfg;
54885 +       /** Device Control Register. <i>Offset: 804h</i> */
54886 +       volatile uint32_t dctl;
54887 +       /** Device Status Register (Read Only). <i>Offset: 808h</i> */
54888 +       volatile uint32_t dsts;
54889 +       /** Reserved. <i>Offset: 80Ch</i> */
54890 +       uint32_t unused;
54891 +       /** Device IN Endpoint Common Interrupt Mask
54892 +        * Register. <i>Offset: 810h</i> */
54893 +       volatile uint32_t diepmsk;
54894 +       /** Device OUT Endpoint Common Interrupt Mask
54895 +        * Register. <i>Offset: 814h</i> */
54896 +       volatile uint32_t doepmsk;
54897 +       /** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */
54898 +       volatile uint32_t daint;
54899 +       /** Device All Endpoints Interrupt Mask Register.  <i>Offset:
54900 +        * 81Ch</i> */
54901 +       volatile uint32_t daintmsk;
54902 +       /** Device IN Token Queue Read Register-1 (Read Only).
54903 +        * <i>Offset: 820h</i> */
54904 +       volatile uint32_t dtknqr1;
54905 +       /** Device IN Token Queue Read Register-2 (Read Only).
54906 +        * <i>Offset: 824h</i> */
54907 +       volatile uint32_t dtknqr2;
54908 +       /** Device VBUS  discharge Register.  <i>Offset: 828h</i> */
54909 +       volatile uint32_t dvbusdis;
54910 +       /** Device VBUS Pulse Register.  <i>Offset: 82Ch</i> */
54911 +       volatile uint32_t dvbuspulse;
54912 +       /** Device IN Token Queue Read Register-3 (Read Only). /
54913 +        *      Device Thresholding control register (Read/Write)
54914 +        * <i>Offset: 830h</i> */
54915 +       volatile uint32_t dtknqr3_dthrctl;
54916 +       /** Device IN Token Queue Read Register-4 (Read Only). /
54917 +        *      Device IN EPs empty Inr. Mask Register (Read/Write)
54918 +        * <i>Offset: 834h</i> */
54919 +       volatile uint32_t dtknqr4_fifoemptymsk;
54920 +       /** Device Each Endpoint Interrupt Register (Read Only). /
54921 +        * <i>Offset: 838h</i> */
54922 +       volatile uint32_t deachint;
54923 +       /** Device Each Endpoint Interrupt mask Register (Read/Write). /
54924 +        * <i>Offset: 83Ch</i> */
54925 +       volatile uint32_t deachintmsk;
54926 +       /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
54927 +        * <i>Offset: 840h</i> */
54928 +       volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
54929 +       /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
54930 +        * <i>Offset: 880h</i> */
54931 +       volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
54932 +} dwc_otg_device_global_regs_t;
54933 +
54934 +/**
54935 + * This union represents the bit fields in the Device Configuration
54936 + * Register.  Read the register into the <i>d32</i> member then
54937 + * set/clear the bits using the <i>b</i>it elements.  Write the
54938 + * <i>d32</i> member to the dcfg register.
54939 + */
54940 +typedef union dcfg_data {
54941 +       /** raw register data */
54942 +       uint32_t d32;
54943 +       /** register bits */
54944 +       struct {
54945 +               /** Device Speed */
54946 +               unsigned devspd:2;
54947 +               /** Non Zero Length Status OUT Handshake */
54948 +               unsigned nzstsouthshk:1;
54949 +#define DWC_DCFG_SEND_STALL 1
54950 +
54951 +               unsigned ena32khzs:1;
54952 +               /** Device Addresses */
54953 +               unsigned devaddr:7;
54954 +               /** Periodic Frame Interval */
54955 +               unsigned perfrint:2;
54956 +#define DWC_DCFG_FRAME_INTERVAL_80 0
54957 +#define DWC_DCFG_FRAME_INTERVAL_85 1
54958 +#define DWC_DCFG_FRAME_INTERVAL_90 2
54959 +#define DWC_DCFG_FRAME_INTERVAL_95 3
54960 +
54961 +               /** Enable Device OUT NAK for bulk in DDMA mode */
54962 +               unsigned endevoutnak:1;
54963 +
54964 +               unsigned reserved14_17:4;
54965 +               /** In Endpoint Mis-match count */
54966 +               unsigned epmscnt:5;
54967 +               /** Enable Descriptor DMA in Device mode */
54968 +               unsigned descdma:1;
54969 +               unsigned perschintvl:2;
54970 +               unsigned resvalid:6;
54971 +       } b;
54972 +} dcfg_data_t;
54973 +
54974 +/**
54975 + * This union represents the bit fields in the Device Control
54976 + * Register.  Read the register into the <i>d32</i> member then
54977 + * set/clear the bits using the <i>b</i>it elements.
54978 + */
54979 +typedef union dctl_data {
54980 +       /** raw register data */
54981 +       uint32_t d32;
54982 +       /** register bits */
54983 +       struct {
54984 +               /** Remote Wakeup */
54985 +               unsigned rmtwkupsig:1;
54986 +               /** Soft Disconnect */
54987 +               unsigned sftdiscon:1;
54988 +               /** Global Non-Periodic IN NAK Status */
54989 +               unsigned gnpinnaksts:1;
54990 +               /** Global OUT NAK Status */
54991 +               unsigned goutnaksts:1;
54992 +               /** Test Control */
54993 +               unsigned tstctl:3;
54994 +               /** Set Global Non-Periodic IN NAK */
54995 +               unsigned sgnpinnak:1;
54996 +               /** Clear Global Non-Periodic IN NAK */
54997 +               unsigned cgnpinnak:1;
54998 +               /** Set Global OUT NAK */
54999 +               unsigned sgoutnak:1;
55000 +               /** Clear Global OUT NAK */
55001 +               unsigned cgoutnak:1;
55002 +               /** Power-On Programming Done */
55003 +               unsigned pwronprgdone:1;
55004 +               /** Reserved */
55005 +               unsigned reserved:1;
55006 +               /** Global Multi Count */
55007 +               unsigned gmc:2;
55008 +               /** Ignore Frame Number for ISOC EPs */
55009 +               unsigned ifrmnum:1;
55010 +               /** NAK on Babble */
55011 +               unsigned nakonbble:1;
55012 +               /** Enable Continue on BNA */
55013 +               unsigned encontonbna:1;
55014 +
55015 +               unsigned reserved18_31:14;
55016 +       } b;
55017 +} dctl_data_t;
55018 +
55019 +/**
55020 + * This union represents the bit fields in the Device Status
55021 + * Register.  Read the register into the <i>d32</i> member then
55022 + * set/clear the bits using the <i>b</i>it elements.
55023 + */
55024 +typedef union dsts_data {
55025 +       /** raw register data */
55026 +       uint32_t d32;
55027 +       /** register bits */
55028 +       struct {
55029 +               /** Suspend Status */
55030 +               unsigned suspsts:1;
55031 +               /** Enumerated Speed */
55032 +               unsigned enumspd:2;
55033 +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
55034 +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
55035 +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ              2
55036 +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ             3
55037 +               /** Erratic Error */
55038 +               unsigned errticerr:1;
55039 +               unsigned reserved4_7:4;
55040 +               /** Frame or Microframe Number of the received SOF */
55041 +               unsigned soffn:14;
55042 +               unsigned reserved22_31:10;
55043 +       } b;
55044 +} dsts_data_t;
55045 +
55046 +/**
55047 + * This union represents the bit fields in the Device IN EP Interrupt
55048 + * Register and the Device IN EP Common Mask Register.
55049 + *
55050 + * - Read the register into the <i>d32</i> member then set/clear the
55051 + *      bits using the <i>b</i>it elements.
55052 + */
55053 +typedef union diepint_data {
55054 +       /** raw register data */
55055 +       uint32_t d32;
55056 +       /** register bits */
55057 +       struct {
55058 +               /** Transfer complete mask */
55059 +               unsigned xfercompl:1;
55060 +               /** Endpoint disable mask */
55061 +               unsigned epdisabled:1;
55062 +               /** AHB Error mask */
55063 +               unsigned ahberr:1;
55064 +               /** TimeOUT Handshake mask (non-ISOC EPs) */
55065 +               unsigned timeout:1;
55066 +               /** IN Token received with TxF Empty mask */
55067 +               unsigned intktxfemp:1;
55068 +               /** IN Token Received with EP mismatch mask */
55069 +               unsigned intknepmis:1;
55070 +               /** IN Endpoint NAK Effective mask */
55071 +               unsigned inepnakeff:1;
55072 +               /** Reserved */
55073 +               unsigned emptyintr:1;
55074 +
55075 +               unsigned txfifoundrn:1;
55076 +
55077 +               /** BNA Interrupt mask */
55078 +               unsigned bna:1;
55079 +
55080 +               unsigned reserved10_12:3;
55081 +               /** BNA Interrupt mask */
55082 +               unsigned nak:1;
55083 +
55084 +               unsigned reserved14_31:18;
55085 +       } b;
55086 +} diepint_data_t;
55087 +
55088 +/**
55089 + * This union represents the bit fields in the Device IN EP
55090 + * Common/Dedicated Interrupt Mask Register.
55091 + */
55092 +typedef union diepint_data diepmsk_data_t;
55093 +
55094 +/**
55095 + * This union represents the bit fields in the Device OUT EP Interrupt
55096 + * Registerand Device OUT EP Common Interrupt Mask Register.
55097 + *
55098 + * - Read the register into the <i>d32</i> member then set/clear the
55099 + *      bits using the <i>b</i>it elements.
55100 + */
55101 +typedef union doepint_data {
55102 +       /** raw register data */
55103 +       uint32_t d32;
55104 +       /** register bits */
55105 +       struct {
55106 +               /** Transfer complete */
55107 +               unsigned xfercompl:1;
55108 +               /** Endpoint disable  */
55109 +               unsigned epdisabled:1;
55110 +               /** AHB Error */
55111 +               unsigned ahberr:1;
55112 +               /** Setup Phase Done (contorl EPs) */
55113 +               unsigned setup:1;
55114 +               /** OUT Token Received when Endpoint Disabled */
55115 +               unsigned outtknepdis:1;
55116 +
55117 +               unsigned stsphsercvd:1;
55118 +               /** Back-to-Back SETUP Packets Received */
55119 +               unsigned back2backsetup:1;
55120 +
55121 +               unsigned reserved7:1;
55122 +               /** OUT packet Error */
55123 +               unsigned outpkterr:1;
55124 +               /** BNA Interrupt */
55125 +               unsigned bna:1;
55126 +
55127 +               unsigned reserved10:1;
55128 +               /** Packet Drop Status */
55129 +               unsigned pktdrpsts:1;
55130 +               /** Babble Interrupt */
55131 +               unsigned babble:1;
55132 +               /** NAK Interrupt */
55133 +               unsigned nak:1;
55134 +               /** NYET Interrupt */
55135 +               unsigned nyet:1;
55136 +               /** Bit indicating setup packet received */
55137 +               unsigned sr:1;
55138 +
55139 +               unsigned reserved16_31:16;
55140 +       } b;
55141 +} doepint_data_t;
55142 +
55143 +/**
55144 + * This union represents the bit fields in the Device OUT EP
55145 + * Common/Dedicated Interrupt Mask Register.
55146 + */
55147 +typedef union doepint_data doepmsk_data_t;
55148 +
55149 +/**
55150 + * This union represents the bit fields in the Device All EP Interrupt
55151 + * and Mask Registers.
55152 + * - Read the register into the <i>d32</i> member then set/clear the
55153 + *      bits using the <i>b</i>it elements.
55154 + */
55155 +typedef union daint_data {
55156 +       /** raw register data */
55157 +       uint32_t d32;
55158 +       /** register bits */
55159 +       struct {
55160 +               /** IN Endpoint bits */
55161 +               unsigned in:16;
55162 +               /** OUT Endpoint bits */
55163 +               unsigned out:16;
55164 +       } ep;
55165 +       struct {
55166 +               /** IN Endpoint bits */
55167 +               unsigned inep0:1;
55168 +               unsigned inep1:1;
55169 +               unsigned inep2:1;
55170 +               unsigned inep3:1;
55171 +               unsigned inep4:1;
55172 +               unsigned inep5:1;
55173 +               unsigned inep6:1;
55174 +               unsigned inep7:1;
55175 +               unsigned inep8:1;
55176 +               unsigned inep9:1;
55177 +               unsigned inep10:1;
55178 +               unsigned inep11:1;
55179 +               unsigned inep12:1;
55180 +               unsigned inep13:1;
55181 +               unsigned inep14:1;
55182 +               unsigned inep15:1;
55183 +               /** OUT Endpoint bits */
55184 +               unsigned outep0:1;
55185 +               unsigned outep1:1;
55186 +               unsigned outep2:1;
55187 +               unsigned outep3:1;
55188 +               unsigned outep4:1;
55189 +               unsigned outep5:1;
55190 +               unsigned outep6:1;
55191 +               unsigned outep7:1;
55192 +               unsigned outep8:1;
55193 +               unsigned outep9:1;
55194 +               unsigned outep10:1;
55195 +               unsigned outep11:1;
55196 +               unsigned outep12:1;
55197 +               unsigned outep13:1;
55198 +               unsigned outep14:1;
55199 +               unsigned outep15:1;
55200 +       } b;
55201 +} daint_data_t;
55202 +
55203 +/**
55204 + * This union represents the bit fields in the Device IN Token Queue
55205 + * Read Registers.
55206 + * - Read the register into the <i>d32</i> member.
55207 + * - READ-ONLY Register
55208 + */
55209 +typedef union dtknq1_data {
55210 +       /** raw register data */
55211 +       uint32_t d32;
55212 +       /** register bits */
55213 +       struct {
55214 +               /** In Token Queue Write Pointer */
55215 +               unsigned intknwptr:5;
55216 +               /** Reserved */
55217 +               unsigned reserved05_06:2;
55218 +               /** write pointer has wrapped. */
55219 +               unsigned wrap_bit:1;
55220 +               /** EP Numbers of IN Tokens 0 ... 4 */
55221 +               unsigned epnums0_5:24;
55222 +       } b;
55223 +} dtknq1_data_t;
55224 +
55225 +/**
55226 + * This union represents Threshold control Register
55227 + * - Read and write the register into the <i>d32</i> member.
55228 + * - READ-WRITABLE Register
55229 + */
55230 +typedef union dthrctl_data {
55231 +       /** raw register data */
55232 +       uint32_t d32;
55233 +       /** register bits */
55234 +       struct {
55235 +               /** non ISO Tx Thr. Enable */
55236 +               unsigned non_iso_thr_en:1;
55237 +               /** ISO Tx Thr. Enable */
55238 +               unsigned iso_thr_en:1;
55239 +               /** Tx Thr. Length */
55240 +               unsigned tx_thr_len:9;
55241 +               /** AHB Threshold ratio */
55242 +               unsigned ahb_thr_ratio:2;
55243 +               /** Reserved */
55244 +               unsigned reserved13_15:3;
55245 +               /** Rx Thr. Enable */
55246 +               unsigned rx_thr_en:1;
55247 +               /** Rx Thr. Length */
55248 +               unsigned rx_thr_len:9;
55249 +               unsigned reserved26:1;
55250 +               /** Arbiter Parking Enable*/
55251 +               unsigned arbprken:1;
55252 +               /** Reserved */
55253 +               unsigned reserved28_31:4;
55254 +       } b;
55255 +} dthrctl_data_t;
55256 +
55257 +/**
55258 + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
55259 + * 900h-AFCh</i>
55260 + *
55261 + * There will be one set of endpoint registers per logical endpoint
55262 + * implemented.
55263 + *
55264 + * <i>These registers are visible only in Device mode and must not be
55265 + * accessed in Host mode, as the results are unknown.</i>
55266 + */
55267 +typedef struct dwc_otg_dev_in_ep_regs {
55268 +       /** Device IN Endpoint Control Register. <i>Offset:900h +
55269 +        * (ep_num * 20h) + 00h</i> */
55270 +       volatile uint32_t diepctl;
55271 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
55272 +       uint32_t reserved04;
55273 +       /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
55274 +        * (ep_num * 20h) + 08h</i> */
55275 +       volatile uint32_t diepint;
55276 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
55277 +       uint32_t reserved0C;
55278 +       /** Device IN Endpoint Transfer Size
55279 +        * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
55280 +       volatile uint32_t dieptsiz;
55281 +       /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
55282 +        * (ep_num * 20h) + 14h</i> */
55283 +       volatile uint32_t diepdma;
55284 +       /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
55285 +        * (ep_num * 20h) + 18h</i> */
55286 +       volatile uint32_t dtxfsts;
55287 +       /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
55288 +        * (ep_num * 20h) + 1Ch</i> */
55289 +       volatile uint32_t diepdmab;
55290 +} dwc_otg_dev_in_ep_regs_t;
55291 +
55292 +/**
55293 + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
55294 + * B00h-CFCh</i>
55295 + *
55296 + * There will be one set of endpoint registers per logical endpoint
55297 + * implemented.
55298 + *
55299 + * <i>These registers are visible only in Device mode and must not be
55300 + * accessed in Host mode, as the results are unknown.</i>
55301 + */
55302 +typedef struct dwc_otg_dev_out_ep_regs {
55303 +       /** Device OUT Endpoint Control Register. <i>Offset:B00h +
55304 +        * (ep_num * 20h) + 00h</i> */
55305 +       volatile uint32_t doepctl;
55306 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
55307 +       uint32_t reserved04;
55308 +       /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
55309 +        * (ep_num * 20h) + 08h</i> */
55310 +       volatile uint32_t doepint;
55311 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
55312 +       uint32_t reserved0C;
55313 +       /** Device OUT Endpoint Transfer Size Register. <i>Offset:
55314 +        * B00h + (ep_num * 20h) + 10h</i> */
55315 +       volatile uint32_t doeptsiz;
55316 +       /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
55317 +        * + (ep_num * 20h) + 14h</i> */
55318 +       volatile uint32_t doepdma;
55319 +       /** Reserved. <i>Offset:B00h +   * (ep_num * 20h) + 18h</i> */
55320 +       uint32_t unused;
55321 +       /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
55322 +        * + (ep_num * 20h) + 1Ch</i> */
55323 +       uint32_t doepdmab;
55324 +} dwc_otg_dev_out_ep_regs_t;
55325 +
55326 +/**
55327 + * This union represents the bit fields in the Device EP Control
55328 + * Register.  Read the register into the <i>d32</i> member then
55329 + * set/clear the bits using the <i>b</i>it elements.
55330 + */
55331 +typedef union depctl_data {
55332 +       /** raw register data */
55333 +       uint32_t d32;
55334 +       /** register bits */
55335 +       struct {
55336 +               /** Maximum Packet Size
55337 +                * IN/OUT EPn
55338 +                * IN/OUT EP0 - 2 bits
55339 +                *       2'b00: 64 Bytes
55340 +                *       2'b01: 32
55341 +                *       2'b10: 16
55342 +                *       2'b11: 8 */
55343 +               unsigned mps:11;
55344 +#define DWC_DEP0CTL_MPS_64      0
55345 +#define DWC_DEP0CTL_MPS_32      1
55346 +#define DWC_DEP0CTL_MPS_16      2
55347 +#define DWC_DEP0CTL_MPS_8       3
55348 +
55349 +               /** Next Endpoint
55350 +                * IN EPn/IN EP0
55351 +                * OUT EPn/OUT EP0 - reserved */
55352 +               unsigned nextep:4;
55353 +
55354 +               /** USB Active Endpoint */
55355 +               unsigned usbactep:1;
55356 +
55357 +               /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
55358 +                * This field contains the PID of the packet going to
55359 +                * be received or transmitted on this endpoint. The
55360 +                * application should program the PID of the first
55361 +                * packet going to be received or transmitted on this
55362 +                * endpoint , after the endpoint is
55363 +                * activated. Application use the SetD1PID and
55364 +                * SetD0PID fields of this register to program either
55365 +                * D0 or D1 PID.
55366 +                *
55367 +                * The encoding for this field is
55368 +                *       - 0: D0
55369 +                *       - 1: D1
55370 +                */
55371 +               unsigned dpid:1;
55372 +
55373 +               /** NAK Status */
55374 +               unsigned naksts:1;
55375 +
55376 +               /** Endpoint Type
55377 +                *      2'b00: Control
55378 +                *      2'b01: Isochronous
55379 +                *      2'b10: Bulk
55380 +                *      2'b11: Interrupt */
55381 +               unsigned eptype:2;
55382 +
55383 +               /** Snoop Mode
55384 +                * OUT EPn/OUT EP0
55385 +                * IN EPn/IN EP0 - reserved */
55386 +               unsigned snp:1;
55387 +
55388 +               /** Stall Handshake */
55389 +               unsigned stall:1;
55390 +
55391 +               /** Tx Fifo Number
55392 +                * IN EPn/IN EP0
55393 +                * OUT EPn/OUT EP0 - reserved */
55394 +               unsigned txfnum:4;
55395 +
55396 +               /** Clear NAK */
55397 +               unsigned cnak:1;
55398 +               /** Set NAK */
55399 +               unsigned snak:1;
55400 +               /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
55401 +                * Writing to this field sets the Endpoint DPID (DPID)
55402 +                * field in this register to DATA0. Set Even
55403 +                * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
55404 +                * Writing to this field sets the Even/Odd
55405 +                * (micro)frame (EO_FrNum) field to even (micro)
55406 +                * frame.
55407 +                */
55408 +               unsigned setd0pid:1;
55409 +               /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
55410 +                * Writing to this field sets the Endpoint DPID (DPID)
55411 +                * field in this register to DATA1 Set Odd
55412 +                * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
55413 +                * Writing to this field sets the Even/Odd
55414 +                * (micro)frame (EO_FrNum) field to odd (micro) frame.
55415 +                */
55416 +               unsigned setd1pid:1;
55417 +
55418 +               /** Endpoint Disable */
55419 +               unsigned epdis:1;
55420 +               /** Endpoint Enable */
55421 +               unsigned epena:1;
55422 +       } b;
55423 +} depctl_data_t;
55424 +
55425 +/**
55426 + * This union represents the bit fields in the Device EP Transfer
55427 + * Size Register.  Read the register into the <i>d32</i> member then
55428 + * set/clear the bits using the <i>b</i>it elements.
55429 + */
55430 +typedef union deptsiz_data {
55431 +               /** raw register data */
55432 +       uint32_t d32;
55433 +               /** register bits */
55434 +       struct {
55435 +               /** Transfer size */
55436 +               unsigned xfersize:19;
55437 +/** Max packet count for EP (pow(2,10)-1) */
55438 +#define MAX_PKT_CNT 1023
55439 +               /** Packet Count */
55440 +               unsigned pktcnt:10;
55441 +               /** Multi Count - Periodic IN endpoints */
55442 +               unsigned mc:2;
55443 +               unsigned reserved:1;
55444 +       } b;
55445 +} deptsiz_data_t;
55446 +
55447 +/**
55448 + * This union represents the bit fields in the Device EP 0 Transfer
55449 + * Size Register.  Read the register into the <i>d32</i> member then
55450 + * set/clear the bits using the <i>b</i>it elements.
55451 + */
55452 +typedef union deptsiz0_data {
55453 +               /** raw register data */
55454 +       uint32_t d32;
55455 +               /** register bits */
55456 +       struct {
55457 +               /** Transfer size */
55458 +               unsigned xfersize:7;
55459 +                               /** Reserved */
55460 +               unsigned reserved7_18:12;
55461 +               /** Packet Count */
55462 +               unsigned pktcnt:2;
55463 +                               /** Reserved */
55464 +               unsigned reserved21_28:8;
55465 +                               /**Setup Packet Count (DOEPTSIZ0 Only) */
55466 +               unsigned supcnt:2;
55467 +               unsigned reserved31;
55468 +       } b;
55469 +} deptsiz0_data_t;
55470 +
55471 +/////////////////////////////////////////////////
55472 +// DMA Descriptor Specific Structures
55473 +//
55474 +
55475 +/** Buffer status definitions */
55476 +
55477 +#define BS_HOST_READY  0x0
55478 +#define BS_DMA_BUSY            0x1
55479 +#define BS_DMA_DONE            0x2
55480 +#define BS_HOST_BUSY   0x3
55481 +
55482 +/** Receive/Transmit status definitions */
55483 +
55484 +#define RTS_SUCCESS            0x0
55485 +#define RTS_BUFFLUSH   0x1
55486 +#define RTS_RESERVED   0x2
55487 +#define RTS_BUFERR             0x3
55488 +
55489 +/**
55490 + * This union represents the bit fields in the DMA Descriptor
55491 + * status quadlet. Read the quadlet into the <i>d32</i> member then
55492 + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
55493 + * <i>b_iso_in</i> elements.
55494 + */
55495 +typedef union dev_dma_desc_sts {
55496 +               /** raw register data */
55497 +       uint32_t d32;
55498 +               /** quadlet bits */
55499 +       struct {
55500 +               /** Received number of bytes */
55501 +               unsigned bytes:16;
55502 +               /** NAK bit - only for OUT EPs */
55503 +               unsigned nak:1;
55504 +               unsigned reserved17_22:6;
55505 +               /** Multiple Transfer - only for OUT EPs */
55506 +               unsigned mtrf:1;
55507 +               /** Setup Packet received - only for OUT EPs */
55508 +               unsigned sr:1;
55509 +               /** Interrupt On Complete */
55510 +               unsigned ioc:1;
55511 +               /** Short Packet */
55512 +               unsigned sp:1;
55513 +               /** Last */
55514 +               unsigned l:1;
55515 +               /** Receive Status */
55516 +               unsigned sts:2;
55517 +               /** Buffer Status */
55518 +               unsigned bs:2;
55519 +       } b;
55520 +
55521 +//#ifdef DWC_EN_ISOC
55522 +               /** iso out quadlet bits */
55523 +       struct {
55524 +               /** Received number of bytes */
55525 +               unsigned rxbytes:11;
55526 +
55527 +               unsigned reserved11:1;
55528 +               /** Frame Number */
55529 +               unsigned framenum:11;
55530 +               /** Received ISO Data PID */
55531 +               unsigned pid:2;
55532 +               /** Interrupt On Complete */
55533 +               unsigned ioc:1;
55534 +               /** Short Packet */
55535 +               unsigned sp:1;
55536 +               /** Last */
55537 +               unsigned l:1;
55538 +               /** Receive Status */
55539 +               unsigned rxsts:2;
55540 +               /** Buffer Status */
55541 +               unsigned bs:2;
55542 +       } b_iso_out;
55543 +
55544 +               /** iso in quadlet bits */
55545 +       struct {
55546 +               /** Transmited number of bytes */
55547 +               unsigned txbytes:12;
55548 +               /** Frame Number */
55549 +               unsigned framenum:11;
55550 +               /** Transmited ISO Data PID */
55551 +               unsigned pid:2;
55552 +               /** Interrupt On Complete */
55553 +               unsigned ioc:1;
55554 +               /** Short Packet */
55555 +               unsigned sp:1;
55556 +               /** Last */
55557 +               unsigned l:1;
55558 +               /** Transmit Status */
55559 +               unsigned txsts:2;
55560 +               /** Buffer Status */
55561 +               unsigned bs:2;
55562 +       } b_iso_in;
55563 +//#endif                                /* DWC_EN_ISOC */
55564 +} dev_dma_desc_sts_t;
55565 +
55566 +/**
55567 + * DMA Descriptor structure
55568 + *
55569 + * DMA Descriptor structure contains two quadlets:
55570 + * Status quadlet and Data buffer pointer.
55571 + */
55572 +typedef struct dwc_otg_dev_dma_desc {
55573 +       /** DMA Descriptor status quadlet */
55574 +       dev_dma_desc_sts_t status;
55575 +       /** DMA Descriptor data buffer pointer */
55576 +       uint32_t buf;
55577 +} dwc_otg_dev_dma_desc_t;
55578 +
55579 +/**
55580 + * The dwc_otg_dev_if structure contains information needed to manage
55581 + * the DWC_otg controller acting in device mode. It represents the
55582 + * programming view of the device-specific aspects of the controller.
55583 + */
55584 +typedef struct dwc_otg_dev_if {
55585 +       /** Pointer to device Global registers.
55586 +        * Device Global Registers starting at offset 800h
55587 +        */
55588 +       dwc_otg_device_global_regs_t *dev_global_regs;
55589 +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
55590 +
55591 +       /**
55592 +        * Device Logical IN Endpoint-Specific Registers 900h-AFCh
55593 +        */
55594 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
55595 +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
55596 +#define DWC_EP_REG_OFFSET 0x20
55597 +
55598 +       /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
55599 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
55600 +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
55601 +
55602 +       /* Device configuration information */
55603 +       uint8_t speed;                           /**< Device Speed      0: Unknown, 1: LS, 2:FS, 3: HS */
55604 +       uint8_t num_in_eps;              /**< Number # of Tx EP range: 0-15 exept ep0 */
55605 +       uint8_t num_out_eps;             /**< Number # of Rx EP range: 0-15 exept ep 0*/
55606 +
55607 +       /** Size of periodic FIFOs (Bytes) */
55608 +       uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
55609 +
55610 +       /** Size of Tx FIFOs (Bytes) */
55611 +       uint16_t tx_fifo_size[MAX_TX_FIFOS];
55612 +
55613 +       /** Thresholding enable flags and length varaiables **/
55614 +       uint16_t rx_thr_en;
55615 +       uint16_t iso_tx_thr_en;
55616 +       uint16_t non_iso_tx_thr_en;
55617 +
55618 +       uint16_t rx_thr_length;
55619 +       uint16_t tx_thr_length;
55620 +
55621 +       /**
55622 +        * Pointers to the DMA Descriptors for EP0 Control
55623 +        * transfers (virtual and physical)
55624 +        */
55625 +
55626 +       /** 2 descriptors for SETUP packets */
55627 +       dwc_dma_t dma_setup_desc_addr[2];
55628 +       dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
55629 +
55630 +       /** Pointer to Descriptor with latest SETUP packet */
55631 +       dwc_otg_dev_dma_desc_t *psetup;
55632 +
55633 +       /** Index of current SETUP handler descriptor */
55634 +       uint32_t setup_desc_index;
55635 +
55636 +       /** Descriptor for Data In or Status In phases */
55637 +       dwc_dma_t dma_in_desc_addr;
55638 +       dwc_otg_dev_dma_desc_t *in_desc_addr;
55639 +
55640 +       /** Descriptor for Data Out or Status Out phases */
55641 +       dwc_dma_t dma_out_desc_addr;
55642 +       dwc_otg_dev_dma_desc_t *out_desc_addr;
55643 +
55644 +       /** Setup Packet Detected - if set clear NAK when queueing */
55645 +       uint32_t spd;
55646 +       /** Isoc ep pointer on which incomplete happens */
55647 +       void *isoc_ep;
55648 +
55649 +} dwc_otg_dev_if_t;
55650 +
55651 +/////////////////////////////////////////////////
55652 +// Host Mode Register Structures
55653 +//
55654 +/**
55655 + * The Host Global Registers structure defines the size and relative
55656 + * field offsets for the Host Mode Global Registers.  Host Global
55657 + * Registers offsets 400h-7FFh.
55658 +*/
55659 +typedef struct dwc_otg_host_global_regs {
55660 +       /** Host Configuration Register.   <i>Offset: 400h</i> */
55661 +       volatile uint32_t hcfg;
55662 +       /** Host Frame Interval Register.       <i>Offset: 404h</i> */
55663 +       volatile uint32_t hfir;
55664 +       /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
55665 +       volatile uint32_t hfnum;
55666 +       /** Reserved.   <i>Offset: 40Ch</i> */
55667 +       uint32_t reserved40C;
55668 +       /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
55669 +       volatile uint32_t hptxsts;
55670 +       /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
55671 +       volatile uint32_t haint;
55672 +       /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
55673 +       volatile uint32_t haintmsk;
55674 +       /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
55675 +       volatile uint32_t hflbaddr;
55676 +} dwc_otg_host_global_regs_t;
55677 +
55678 +/**
55679 + * This union represents the bit fields in the Host Configuration Register.
55680 + * Read the register into the <i>d32</i> member then set/clear the bits using
55681 + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
55682 + */
55683 +typedef union hcfg_data {
55684 +       /** raw register data */
55685 +       uint32_t d32;
55686 +
55687 +       /** register bits */
55688 +       struct {
55689 +               /** FS/LS Phy Clock Select */
55690 +               unsigned fslspclksel:2;
55691 +#define DWC_HCFG_30_60_MHZ 0
55692 +#define DWC_HCFG_48_MHZ           1
55693 +#define DWC_HCFG_6_MHZ    2
55694 +
55695 +               /** FS/LS Only Support */
55696 +               unsigned fslssupp:1;
55697 +               unsigned reserved3_6:4;
55698 +               /** Enable 32-KHz Suspend Mode */
55699 +               unsigned ena32khzs:1;
55700 +               /** Resume Validation Periiod */
55701 +               unsigned resvalid:8;
55702 +               unsigned reserved16_22:7;
55703 +               /** Enable Scatter/gather DMA in Host mode */
55704 +               unsigned descdma:1;
55705 +               /** Frame List Entries */
55706 +               unsigned frlisten:2;
55707 +               /** Enable Periodic Scheduling */
55708 +               unsigned perschedena:1;
55709 +               unsigned reserved27_30:4;
55710 +               unsigned modechtimen:1;
55711 +       } b;
55712 +} hcfg_data_t;
55713 +
55714 +/**
55715 + * This union represents the bit fields in the Host Frame Remaing/Number
55716 + * Register.
55717 + */
55718 +typedef union hfir_data {
55719 +       /** raw register data */
55720 +       uint32_t d32;
55721 +
55722 +       /** register bits */
55723 +       struct {
55724 +               unsigned frint:16;
55725 +               unsigned hfirrldctrl:1;
55726 +               unsigned reserved:15;
55727 +       } b;
55728 +} hfir_data_t;
55729 +
55730 +/**
55731 + * This union represents the bit fields in the Host Frame Remaing/Number
55732 + * Register.
55733 + */
55734 +typedef union hfnum_data {
55735 +       /** raw register data */
55736 +       uint32_t d32;
55737 +
55738 +       /** register bits */
55739 +       struct {
55740 +               unsigned frnum:16;
55741 +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
55742 +               unsigned frrem:16;
55743 +       } b;
55744 +} hfnum_data_t;
55745 +
55746 +typedef union hptxsts_data {
55747 +       /** raw register data */
55748 +       uint32_t d32;
55749 +
55750 +       /** register bits */
55751 +       struct {
55752 +               unsigned ptxfspcavail:16;
55753 +               unsigned ptxqspcavail:8;
55754 +               /** Top of the Periodic Transmit Request Queue
55755 +                *      - bit 24 - Terminate (last entry for the selected channel)
55756 +                *      - bits 26:25 - Token Type
55757 +                *        - 2'b00 - Zero length
55758 +                *        - 2'b01 - Ping
55759 +                *        - 2'b10 - Disable
55760 +                *      - bits 30:27 - Channel Number
55761 +                *      - bit 31 - Odd/even microframe
55762 +                */
55763 +               unsigned ptxqtop_terminate:1;
55764 +               unsigned ptxqtop_token:2;
55765 +               unsigned ptxqtop_chnum:4;
55766 +               unsigned ptxqtop_odd:1;
55767 +       } b;
55768 +} hptxsts_data_t;
55769 +
55770 +/**
55771 + * This union represents the bit fields in the Host Port Control and Status
55772 + * Register. Read the register into the <i>d32</i> member then set/clear the
55773 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55774 + * hprt0 register.
55775 + */
55776 +typedef union hprt0_data {
55777 +       /** raw register data */
55778 +       uint32_t d32;
55779 +       /** register bits */
55780 +       struct {
55781 +               unsigned prtconnsts:1;
55782 +               unsigned prtconndet:1;
55783 +               unsigned prtena:1;
55784 +               unsigned prtenchng:1;
55785 +               unsigned prtovrcurract:1;
55786 +               unsigned prtovrcurrchng:1;
55787 +               unsigned prtres:1;
55788 +               unsigned prtsusp:1;
55789 +               unsigned prtrst:1;
55790 +               unsigned reserved9:1;
55791 +               unsigned prtlnsts:2;
55792 +               unsigned prtpwr:1;
55793 +               unsigned prttstctl:4;
55794 +               unsigned prtspd:2;
55795 +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
55796 +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
55797 +#define DWC_HPRT0_PRTSPD_LOW_SPEED     2
55798 +               unsigned reserved19_31:13;
55799 +       } b;
55800 +} hprt0_data_t;
55801 +
55802 +/**
55803 + * This union represents the bit fields in the Host All Interrupt
55804 + * Register.
55805 + */
55806 +typedef union haint_data {
55807 +       /** raw register data */
55808 +       uint32_t d32;
55809 +       /** register bits */
55810 +       struct {
55811 +               unsigned ch0:1;
55812 +               unsigned ch1:1;
55813 +               unsigned ch2:1;
55814 +               unsigned ch3:1;
55815 +               unsigned ch4:1;
55816 +               unsigned ch5:1;
55817 +               unsigned ch6:1;
55818 +               unsigned ch7:1;
55819 +               unsigned ch8:1;
55820 +               unsigned ch9:1;
55821 +               unsigned ch10:1;
55822 +               unsigned ch11:1;
55823 +               unsigned ch12:1;
55824 +               unsigned ch13:1;
55825 +               unsigned ch14:1;
55826 +               unsigned ch15:1;
55827 +               unsigned reserved:16;
55828 +       } b;
55829 +
55830 +       struct {
55831 +               unsigned chint:16;
55832 +               unsigned reserved:16;
55833 +       } b2;
55834 +} haint_data_t;
55835 +
55836 +/**
55837 + * This union represents the bit fields in the Host All Interrupt
55838 + * Register.
55839 + */
55840 +typedef union haintmsk_data {
55841 +       /** raw register data */
55842 +       uint32_t d32;
55843 +       /** register bits */
55844 +       struct {
55845 +               unsigned ch0:1;
55846 +               unsigned ch1:1;
55847 +               unsigned ch2:1;
55848 +               unsigned ch3:1;
55849 +               unsigned ch4:1;
55850 +               unsigned ch5:1;
55851 +               unsigned ch6:1;
55852 +               unsigned ch7:1;
55853 +               unsigned ch8:1;
55854 +               unsigned ch9:1;
55855 +               unsigned ch10:1;
55856 +               unsigned ch11:1;
55857 +               unsigned ch12:1;
55858 +               unsigned ch13:1;
55859 +               unsigned ch14:1;
55860 +               unsigned ch15:1;
55861 +               unsigned reserved:16;
55862 +       } b;
55863 +
55864 +       struct {
55865 +               unsigned chint:16;
55866 +               unsigned reserved:16;
55867 +       } b2;
55868 +} haintmsk_data_t;
55869 +
55870 +/**
55871 + * Host Channel Specific Registers. <i>500h-5FCh</i>
55872 + */
55873 +typedef struct dwc_otg_hc_regs {
55874 +       /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
55875 +       volatile uint32_t hcchar;
55876 +       /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
55877 +       volatile uint32_t hcsplt;
55878 +       /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
55879 +       volatile uint32_t hcint;
55880 +       /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
55881 +       volatile uint32_t hcintmsk;
55882 +       /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
55883 +       volatile uint32_t hctsiz;
55884 +       /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
55885 +       volatile uint32_t hcdma;
55886 +       volatile uint32_t reserved;
55887 +       /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
55888 +       volatile uint32_t hcdmab;
55889 +} dwc_otg_hc_regs_t;
55890 +
55891 +/**
55892 + * This union represents the bit fields in the Host Channel Characteristics
55893 + * Register. Read the register into the <i>d32</i> member then set/clear the
55894 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55895 + * hcchar register.
55896 + */
55897 +typedef union hcchar_data {
55898 +       /** raw register data */
55899 +       uint32_t d32;
55900 +
55901 +       /** register bits */
55902 +       struct {
55903 +               /** Maximum packet size in bytes */
55904 +               unsigned mps:11;
55905 +
55906 +               /** Endpoint number */
55907 +               unsigned epnum:4;
55908 +
55909 +               /** 0: OUT, 1: IN */
55910 +               unsigned epdir:1;
55911 +
55912 +               unsigned reserved:1;
55913 +
55914 +               /** 0: Full/high speed device, 1: Low speed device */
55915 +               unsigned lspddev:1;
55916 +
55917 +               /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
55918 +               unsigned eptype:2;
55919 +
55920 +               /** Packets per frame for periodic transfers. 0 is reserved. */
55921 +               unsigned multicnt:2;
55922 +
55923 +               /** Device address */
55924 +               unsigned devaddr:7;
55925 +
55926 +               /**
55927 +                * Frame to transmit periodic transaction.
55928 +                * 0: even, 1: odd
55929 +                */
55930 +               unsigned oddfrm:1;
55931 +
55932 +               /** Channel disable */
55933 +               unsigned chdis:1;
55934 +
55935 +               /** Channel enable */
55936 +               unsigned chen:1;
55937 +       } b;
55938 +} hcchar_data_t;
55939 +
55940 +typedef union hcsplt_data {
55941 +       /** raw register data */
55942 +       uint32_t d32;
55943 +
55944 +       /** register bits */
55945 +       struct {
55946 +               /** Port Address */
55947 +               unsigned prtaddr:7;
55948 +
55949 +               /** Hub Address */
55950 +               unsigned hubaddr:7;
55951 +
55952 +               /** Transaction Position */
55953 +               unsigned xactpos:2;
55954 +#define DWC_HCSPLIT_XACTPOS_MID 0
55955 +#define DWC_HCSPLIT_XACTPOS_END 1
55956 +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
55957 +#define DWC_HCSPLIT_XACTPOS_ALL 3
55958 +
55959 +               /** Do Complete Split */
55960 +               unsigned compsplt:1;
55961 +
55962 +               /** Reserved */
55963 +               unsigned reserved:14;
55964 +
55965 +               /** Split Enble */
55966 +               unsigned spltena:1;
55967 +       } b;
55968 +} hcsplt_data_t;
55969 +
55970 +/**
55971 + * This union represents the bit fields in the Host All Interrupt
55972 + * Register.
55973 + */
55974 +typedef union hcint_data {
55975 +       /** raw register data */
55976 +       uint32_t d32;
55977 +       /** register bits */
55978 +       struct {
55979 +               /** Transfer Complete */
55980 +               unsigned xfercomp:1;
55981 +               /** Channel Halted */
55982 +               unsigned chhltd:1;
55983 +               /** AHB Error */
55984 +               unsigned ahberr:1;
55985 +               /** STALL Response Received */
55986 +               unsigned stall:1;
55987 +               /** NAK Response Received */
55988 +               unsigned nak:1;
55989 +               /** ACK Response Received */
55990 +               unsigned ack:1;
55991 +               /** NYET Response Received */
55992 +               unsigned nyet:1;
55993 +               /** Transaction Err */
55994 +               unsigned xacterr:1;
55995 +               /** Babble Error */
55996 +               unsigned bblerr:1;
55997 +               /** Frame Overrun */
55998 +               unsigned frmovrun:1;
55999 +               /** Data Toggle Error */
56000 +               unsigned datatglerr:1;
56001 +               /** Buffer Not Available (only for DDMA mode) */
56002 +               unsigned bna:1;
56003 +               /** Exessive transaction error (only for DDMA mode) */
56004 +               unsigned xcs_xact:1;
56005 +               /** Frame List Rollover interrupt */
56006 +               unsigned frm_list_roll:1;
56007 +               /** Reserved */
56008 +               unsigned reserved14_31:18;
56009 +       } b;
56010 +} hcint_data_t;
56011 +
56012 +/**
56013 + * This union represents the bit fields in the Host Channel Interrupt Mask
56014 + * Register. Read the register into the <i>d32</i> member then set/clear the
56015 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56016 + * hcintmsk register.
56017 + */
56018 +typedef union hcintmsk_data {
56019 +       /** raw register data */
56020 +       uint32_t d32;
56021 +
56022 +       /** register bits */
56023 +       struct {
56024 +               unsigned xfercompl:1;
56025 +               unsigned chhltd:1;
56026 +               unsigned ahberr:1;
56027 +               unsigned stall:1;
56028 +               unsigned nak:1;
56029 +               unsigned ack:1;
56030 +               unsigned nyet:1;
56031 +               unsigned xacterr:1;
56032 +               unsigned bblerr:1;
56033 +               unsigned frmovrun:1;
56034 +               unsigned datatglerr:1;
56035 +               unsigned bna:1;
56036 +               unsigned xcs_xact:1;
56037 +               unsigned frm_list_roll:1;
56038 +               unsigned reserved14_31:18;
56039 +       } b;
56040 +} hcintmsk_data_t;
56041 +
56042 +/**
56043 + * This union represents the bit fields in the Host Channel Transfer Size
56044 + * Register. Read the register into the <i>d32</i> member then set/clear the
56045 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
56046 + * hcchar register.
56047 + */
56048 +
56049 +typedef union hctsiz_data {
56050 +       /** raw register data */
56051 +       uint32_t d32;
56052 +
56053 +       /** register bits */
56054 +       struct {
56055 +               /** Total transfer size in bytes */
56056 +               unsigned xfersize:19;
56057 +
56058 +               /** Data packets to transfer */
56059 +               unsigned pktcnt:10;
56060 +
56061 +               /**
56062 +                * Packet ID for next data packet
56063 +                * 0: DATA0
56064 +                * 1: DATA2
56065 +                * 2: DATA1
56066 +                * 3: MDATA (non-Control), SETUP (Control)
56067 +                */
56068 +               unsigned pid:2;
56069 +#define DWC_HCTSIZ_DATA0 0
56070 +#define DWC_HCTSIZ_DATA1 2
56071 +#define DWC_HCTSIZ_DATA2 1
56072 +#define DWC_HCTSIZ_MDATA 3
56073 +#define DWC_HCTSIZ_SETUP 3
56074 +
56075 +               /** Do PING protocol when 1 */
56076 +               unsigned dopng:1;
56077 +       } b;
56078 +
56079 +       /** register bits */
56080 +       struct {
56081 +               /** Scheduling information */
56082 +               unsigned schinfo:8;
56083 +
56084 +               /** Number of transfer descriptors.
56085 +                * Max value:
56086 +                * 64 in general,
56087 +                * 256 only for HS isochronous endpoint.
56088 +                */
56089 +               unsigned ntd:8;
56090 +
56091 +               /** Data packets to transfer */
56092 +               unsigned reserved16_28:13;
56093 +
56094 +               /**
56095 +                * Packet ID for next data packet
56096 +                * 0: DATA0
56097 +                * 1: DATA2
56098 +                * 2: DATA1
56099 +                * 3: MDATA (non-Control)
56100 +                */
56101 +               unsigned pid:2;
56102 +
56103 +               /** Do PING protocol when 1 */
56104 +               unsigned dopng:1;
56105 +       } b_ddma;
56106 +} hctsiz_data_t;
56107 +
56108 +/**
56109 + * This union represents the bit fields in the Host DMA Address
56110 + * Register used in Descriptor DMA mode.
56111 + */
56112 +typedef union hcdma_data {
56113 +       /** raw register data */
56114 +       uint32_t d32;
56115 +       /** register bits */
56116 +       struct {
56117 +               unsigned reserved0_2:3;
56118 +               /** Current Transfer Descriptor. Not used for ISOC */
56119 +               unsigned ctd:8;
56120 +               /** Start Address of Descriptor List */
56121 +               unsigned dma_addr:21;
56122 +       } b;
56123 +} hcdma_data_t;
56124 +
56125 +/**
56126 + * This union represents the bit fields in the DMA Descriptor
56127 + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
56128 + * set/clear the bits using the <i>b</i>it elements.
56129 + */
56130 +typedef union host_dma_desc_sts {
56131 +       /** raw register data */
56132 +       uint32_t d32;
56133 +       /** quadlet bits */
56134 +
56135 +       /* for non-isochronous  */
56136 +       struct {
56137 +               /** Number of bytes */
56138 +               unsigned n_bytes:17;
56139 +               /** QTD offset to jump when Short Packet received - only for IN EPs */
56140 +               unsigned qtd_offset:6;
56141 +               /**
56142 +                * Set to request the core to jump to alternate QTD if
56143 +                * Short Packet received - only for IN EPs
56144 +                */
56145 +               unsigned a_qtd:1;
56146 +                /**
56147 +                 * Setup Packet bit. When set indicates that buffer contains
56148 +                 * setup packet.
56149 +                 */
56150 +               unsigned sup:1;
56151 +               /** Interrupt On Complete */
56152 +               unsigned ioc:1;
56153 +               /** End of List */
56154 +               unsigned eol:1;
56155 +               unsigned reserved27:1;
56156 +               /** Rx/Tx Status */
56157 +               unsigned sts:2;
56158 +#define DMA_DESC_STS_PKTERR    1
56159 +               unsigned reserved30:1;
56160 +               /** Active Bit */
56161 +               unsigned a:1;
56162 +       } b;
56163 +       /* for isochronous */
56164 +       struct {
56165 +               /** Number of bytes */
56166 +               unsigned n_bytes:12;
56167 +               unsigned reserved12_24:13;
56168 +               /** Interrupt On Complete */
56169 +               unsigned ioc:1;
56170 +               unsigned reserved26_27:2;
56171 +               /** Rx/Tx Status */
56172 +               unsigned sts:2;
56173 +               unsigned reserved30:1;
56174 +               /** Active Bit */
56175 +               unsigned a:1;
56176 +       } b_isoc;
56177 +} host_dma_desc_sts_t;
56178 +
56179 +#define        MAX_DMA_DESC_SIZE               131071
56180 +#define MAX_DMA_DESC_NUM_GENERIC       64
56181 +#define MAX_DMA_DESC_NUM_HS_ISOC       256
56182 +#define MAX_FRLIST_EN_NUM              64
56183 +/**
56184 + * Host-mode DMA Descriptor structure
56185 + *
56186 + * DMA Descriptor structure contains two quadlets:
56187 + * Status quadlet and Data buffer pointer.
56188 + */
56189 +typedef struct dwc_otg_host_dma_desc {
56190 +       /** DMA Descriptor status quadlet */
56191 +       host_dma_desc_sts_t status;
56192 +       /** DMA Descriptor data buffer pointer */
56193 +       uint32_t buf;
56194 +} dwc_otg_host_dma_desc_t;
56195 +
56196 +/** OTG Host Interface Structure.
56197 + *
56198 + * The OTG Host Interface Structure structure contains information
56199 + * needed to manage the DWC_otg controller acting in host mode. It
56200 + * represents the programming view of the host-specific aspects of the
56201 + * controller.
56202 + */
56203 +typedef struct dwc_otg_host_if {
56204 +       /** Host Global Registers starting at offset 400h.*/
56205 +       dwc_otg_host_global_regs_t *host_global_regs;
56206 +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
56207 +
56208 +       /** Host Port 0 Control and Status Register */
56209 +       volatile uint32_t *hprt0;
56210 +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
56211 +
56212 +       /** Host Channel Specific Registers at offsets 500h-5FCh. */
56213 +       dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
56214 +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
56215 +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
56216 +
56217 +       /* Host configuration information */
56218 +       /** Number of Host Channels (range: 1-16) */
56219 +       uint8_t num_host_channels;
56220 +       /** Periodic EPs supported (0: no, 1: yes) */
56221 +       uint8_t perio_eps_supported;
56222 +       /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
56223 +       uint16_t perio_tx_fifo_size;
56224 +
56225 +} dwc_otg_host_if_t;
56226 +
56227 +/**
56228 + * This union represents the bit fields in the Power and Clock Gating Control
56229 + * Register. Read the register into the <i>d32</i> member then set/clear the
56230 + * bits using the <i>b</i>it elements.
56231 + */
56232 +typedef union pcgcctl_data {
56233 +       /** raw register data */
56234 +       uint32_t d32;
56235 +
56236 +       /** register bits */
56237 +       struct {
56238 +               /** Stop Pclk */
56239 +               unsigned stoppclk:1;
56240 +               /** Gate Hclk */
56241 +               unsigned gatehclk:1;
56242 +               /** Power Clamp */
56243 +               unsigned pwrclmp:1;
56244 +               /** Reset Power Down Modules */
56245 +               unsigned rstpdwnmodule:1;
56246 +               /** Reserved */
56247 +               unsigned reserved:1;
56248 +               /** Enable Sleep Clock Gating (Enbl_L1Gating) */
56249 +               unsigned enbl_sleep_gating:1;
56250 +               /** PHY In Sleep (PhySleep) */
56251 +               unsigned phy_in_sleep:1;
56252 +               /** Deep Sleep*/
56253 +               unsigned deep_sleep:1;
56254 +               unsigned resetaftsusp:1;
56255 +               unsigned restoremode:1;
56256 +               unsigned enbl_extnd_hiber:1;
56257 +               unsigned extnd_hiber_pwrclmp:1;
56258 +               unsigned extnd_hiber_switch:1;
56259 +               unsigned ess_reg_restored:1;
56260 +               unsigned prt_clk_sel:2;
56261 +               unsigned port_power:1;
56262 +               unsigned max_xcvrselect:2;
56263 +               unsigned max_termsel:1;
56264 +               unsigned mac_dev_addr:7;
56265 +               unsigned p2hd_dev_enum_spd:2;
56266 +               unsigned p2hd_prt_spd:2;
56267 +               unsigned if_dev_mode:1;
56268 +       } b;
56269 +} pcgcctl_data_t;
56270 +
56271 +/**
56272 + * This union represents the bit fields in the Global Data FIFO Software
56273 + * Configuration Register. Read the register into the <i>d32</i> member then
56274 + * set/clear the bits using the <i>b</i>it elements.
56275 + */
56276 +typedef union gdfifocfg_data {
56277 +       /* raw register data */
56278 +       uint32_t d32;
56279 +       /** register bits */
56280 +       struct {
56281 +               /** OTG Data FIFO depth */
56282 +               unsigned gdfifocfg:16;
56283 +               /** Start address of EP info controller */
56284 +               unsigned epinfobase:16;
56285 +       } b;
56286 +} gdfifocfg_data_t;
56287 +
56288 +/**
56289 + * This union represents the bit fields in the Global Power Down Register
56290 + * Register. Read the register into the <i>d32</i> member then set/clear the
56291 + * bits using the <i>b</i>it elements.
56292 + */
56293 +typedef union gpwrdn_data {
56294 +       /* raw register data */
56295 +       uint32_t d32;
56296 +
56297 +       /** register bits */
56298 +       struct {
56299 +               /** PMU Interrupt Select */
56300 +               unsigned pmuintsel:1;
56301 +               /** PMU Active */
56302 +               unsigned pmuactv:1;
56303 +               /** Restore */
56304 +               unsigned restore:1;
56305 +               /** Power Down Clamp */
56306 +               unsigned pwrdnclmp:1;
56307 +               /** Power Down Reset */
56308 +               unsigned pwrdnrstn:1;
56309 +               /** Power Down Switch */
56310 +               unsigned pwrdnswtch:1;
56311 +               /** Disable VBUS */
56312 +               unsigned dis_vbus:1;
56313 +               /** Line State Change */
56314 +               unsigned lnstschng:1;
56315 +               /** Line state change mask */
56316 +               unsigned lnstchng_msk:1;
56317 +               /** Reset Detected */
56318 +               unsigned rst_det:1;
56319 +               /** Reset Detect mask */
56320 +               unsigned rst_det_msk:1;
56321 +               /** Disconnect Detected */
56322 +               unsigned disconn_det:1;
56323 +               /** Disconnect Detect mask */
56324 +               unsigned disconn_det_msk:1;
56325 +               /** Connect Detected*/
56326 +               unsigned connect_det:1;
56327 +               /** Connect Detected Mask*/
56328 +               unsigned connect_det_msk:1;
56329 +               /** SRP Detected */
56330 +               unsigned srp_det:1;
56331 +               /** SRP Detect mask */
56332 +               unsigned srp_det_msk:1;
56333 +               /** Status Change Interrupt */
56334 +               unsigned sts_chngint:1;
56335 +               /** Status Change Interrupt Mask */
56336 +               unsigned sts_chngint_msk:1;
56337 +               /** Line State */
56338 +               unsigned linestate:2;
56339 +               /** Indicates current mode(status of IDDIG signal) */
56340 +               unsigned idsts:1;
56341 +               /** B Session Valid signal status*/
56342 +               unsigned bsessvld:1;
56343 +               /** ADP Event Detected */
56344 +               unsigned adp_int:1;
56345 +               /** Multi Valued ID pin */
56346 +               unsigned mult_val_id_bc:5;
56347 +               /** Reserved 24_31 */
56348 +               unsigned reserved29_31:3;
56349 +       } b;
56350 +} gpwrdn_data_t;
56351 +
56352 +#endif
56353 diff --git a/drivers/usb/host/dwc_otg/test/Makefile b/drivers/usb/host/dwc_otg/test/Makefile
56354 new file mode 100644
56355 index 0000000..fc45375
56356 --- /dev/null
56357 +++ b/drivers/usb/host/dwc_otg/test/Makefile
56358 @@ -0,0 +1,16 @@
56359 +
56360 +PERL=/usr/bin/perl
56361 +PL_TESTS=test_sysfs.pl test_mod_param.pl
56362 +
56363 +.PHONY : test
56364 +test : perl_tests
56365 +
56366 +perl_tests :
56367 +       @echo
56368 +       @echo Running perl tests
56369 +       @for test in $(PL_TESTS); do \
56370 +         if $(PERL) ./$$test ; then \
56371 +           echo "=======> $$test, PASSED" ; \
56372 +         else echo "=======> $$test, FAILED" ; \
56373 +         fi \
56374 +       done
56375 diff --git a/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56376 new file mode 100644
56377 index 0000000..85e55fd
56378 --- /dev/null
56379 +++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56380 @@ -0,0 +1,337 @@
56381 +package dwc_otg_test;
56382 +
56383 +use strict;
56384 +use Exporter ();
56385 +
56386 +use vars qw(@ISA @EXPORT
56387 +$sysfsdir $paramdir $errors $params
56388 +);
56389 +
56390 +@ISA = qw(Exporter);
56391 +
56392 +#
56393 +# Globals
56394 +#
56395 +$sysfsdir = "/sys/devices/lm0";
56396 +$paramdir = "/sys/module/dwc_otg";
56397 +$errors = 0;
56398 +
56399 +$params = [
56400 +          {
56401 +           NAME => "otg_cap",
56402 +           DEFAULT => 0,
56403 +           ENUM => [],
56404 +           LOW => 0,
56405 +           HIGH => 2
56406 +          },
56407 +          {
56408 +           NAME => "dma_enable",
56409 +           DEFAULT => 0,
56410 +           ENUM => [],
56411 +           LOW => 0,
56412 +           HIGH => 1
56413 +          },
56414 +          {
56415 +           NAME => "dma_burst_size",
56416 +           DEFAULT => 32,
56417 +           ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
56418 +           LOW => 1,
56419 +           HIGH => 256
56420 +          },
56421 +          {
56422 +           NAME => "host_speed",
56423 +           DEFAULT => 0,
56424 +           ENUM => [],
56425 +           LOW => 0,
56426 +           HIGH => 1
56427 +          },
56428 +          {
56429 +           NAME => "host_support_fs_ls_low_power",
56430 +           DEFAULT => 0,
56431 +           ENUM => [],
56432 +           LOW => 0,
56433 +           HIGH => 1
56434 +          },
56435 +          {
56436 +           NAME => "host_ls_low_power_phy_clk",
56437 +           DEFAULT => 0,
56438 +           ENUM => [],
56439 +           LOW => 0,
56440 +           HIGH => 1
56441 +          },
56442 +          {
56443 +           NAME => "dev_speed",
56444 +           DEFAULT => 0,
56445 +           ENUM => [],
56446 +           LOW => 0,
56447 +           HIGH => 1
56448 +          },
56449 +          {
56450 +           NAME => "enable_dynamic_fifo",
56451 +           DEFAULT => 1,
56452 +           ENUM => [],
56453 +           LOW => 0,
56454 +           HIGH => 1
56455 +          },
56456 +          {
56457 +           NAME => "data_fifo_size",
56458 +           DEFAULT => 8192,
56459 +           ENUM => [],
56460 +           LOW => 32,
56461 +           HIGH => 32768
56462 +          },
56463 +          {
56464 +           NAME => "dev_rx_fifo_size",
56465 +           DEFAULT => 1064,
56466 +           ENUM => [],
56467 +           LOW => 16,
56468 +           HIGH => 32768
56469 +          },
56470 +          {
56471 +           NAME => "dev_nperio_tx_fifo_size",
56472 +           DEFAULT => 1024,
56473 +           ENUM => [],
56474 +           LOW => 16,
56475 +           HIGH => 32768
56476 +          },
56477 +          {
56478 +           NAME => "dev_perio_tx_fifo_size_1",
56479 +           DEFAULT => 256,
56480 +           ENUM => [],
56481 +           LOW => 4,
56482 +           HIGH => 768
56483 +          },
56484 +          {
56485 +           NAME => "dev_perio_tx_fifo_size_2",
56486 +           DEFAULT => 256,
56487 +           ENUM => [],
56488 +           LOW => 4,
56489 +           HIGH => 768
56490 +          },
56491 +          {
56492 +           NAME => "dev_perio_tx_fifo_size_3",
56493 +           DEFAULT => 256,
56494 +           ENUM => [],
56495 +           LOW => 4,
56496 +           HIGH => 768
56497 +          },
56498 +          {
56499 +           NAME => "dev_perio_tx_fifo_size_4",
56500 +           DEFAULT => 256,
56501 +           ENUM => [],
56502 +           LOW => 4,
56503 +           HIGH => 768
56504 +          },
56505 +          {
56506 +           NAME => "dev_perio_tx_fifo_size_5",
56507 +           DEFAULT => 256,
56508 +           ENUM => [],
56509 +           LOW => 4,
56510 +           HIGH => 768
56511 +          },
56512 +          {
56513 +           NAME => "dev_perio_tx_fifo_size_6",
56514 +           DEFAULT => 256,
56515 +           ENUM => [],
56516 +           LOW => 4,
56517 +           HIGH => 768
56518 +          },
56519 +          {
56520 +           NAME => "dev_perio_tx_fifo_size_7",
56521 +           DEFAULT => 256,
56522 +           ENUM => [],
56523 +           LOW => 4,
56524 +           HIGH => 768
56525 +          },
56526 +          {
56527 +           NAME => "dev_perio_tx_fifo_size_8",
56528 +           DEFAULT => 256,
56529 +           ENUM => [],
56530 +           LOW => 4,
56531 +           HIGH => 768
56532 +          },
56533 +          {
56534 +           NAME => "dev_perio_tx_fifo_size_9",
56535 +           DEFAULT => 256,
56536 +           ENUM => [],
56537 +           LOW => 4,
56538 +           HIGH => 768
56539 +          },
56540 +          {
56541 +           NAME => "dev_perio_tx_fifo_size_10",
56542 +           DEFAULT => 256,
56543 +           ENUM => [],
56544 +           LOW => 4,
56545 +           HIGH => 768
56546 +          },
56547 +          {
56548 +           NAME => "dev_perio_tx_fifo_size_11",
56549 +           DEFAULT => 256,
56550 +           ENUM => [],
56551 +           LOW => 4,
56552 +           HIGH => 768
56553 +          },
56554 +          {
56555 +           NAME => "dev_perio_tx_fifo_size_12",
56556 +           DEFAULT => 256,
56557 +           ENUM => [],
56558 +           LOW => 4,
56559 +           HIGH => 768
56560 +          },
56561 +          {
56562 +           NAME => "dev_perio_tx_fifo_size_13",
56563 +           DEFAULT => 256,
56564 +           ENUM => [],
56565 +           LOW => 4,
56566 +           HIGH => 768
56567 +          },
56568 +          {
56569 +           NAME => "dev_perio_tx_fifo_size_14",
56570 +           DEFAULT => 256,
56571 +           ENUM => [],
56572 +           LOW => 4,
56573 +           HIGH => 768
56574 +          },
56575 +          {
56576 +           NAME => "dev_perio_tx_fifo_size_15",
56577 +           DEFAULT => 256,
56578 +           ENUM => [],
56579 +           LOW => 4,
56580 +           HIGH => 768
56581 +          },
56582 +          {
56583 +           NAME => "host_rx_fifo_size",
56584 +           DEFAULT => 1024,
56585 +           ENUM => [],
56586 +           LOW => 16,
56587 +           HIGH => 32768
56588 +          },
56589 +          {
56590 +           NAME => "host_nperio_tx_fifo_size",
56591 +           DEFAULT => 1024,
56592 +           ENUM => [],
56593 +           LOW => 16,
56594 +           HIGH => 32768
56595 +          },
56596 +          {
56597 +           NAME => "host_perio_tx_fifo_size",
56598 +           DEFAULT => 1024,
56599 +           ENUM => [],
56600 +           LOW => 16,
56601 +           HIGH => 32768
56602 +          },
56603 +          {
56604 +           NAME => "max_transfer_size",
56605 +           DEFAULT => 65535,
56606 +           ENUM => [],
56607 +           LOW => 2047,
56608 +           HIGH => 65535
56609 +          },
56610 +          {
56611 +           NAME => "max_packet_count",
56612 +           DEFAULT => 511,
56613 +           ENUM => [],
56614 +           LOW => 15,
56615 +           HIGH => 511
56616 +          },
56617 +          {
56618 +           NAME => "host_channels",
56619 +           DEFAULT => 12,
56620 +           ENUM => [],
56621 +           LOW => 1,
56622 +           HIGH => 16
56623 +          },
56624 +          {
56625 +           NAME => "dev_endpoints",
56626 +           DEFAULT => 6,
56627 +           ENUM => [],
56628 +           LOW => 1,
56629 +           HIGH => 15
56630 +          },
56631 +          {
56632 +           NAME => "phy_type",
56633 +           DEFAULT => 1,
56634 +           ENUM => [],
56635 +           LOW => 0,
56636 +           HIGH => 2
56637 +          },
56638 +          {
56639 +           NAME => "phy_utmi_width",
56640 +           DEFAULT => 16,
56641 +           ENUM => [8, 16],
56642 +           LOW => 8,
56643 +           HIGH => 16
56644 +          },
56645 +          {
56646 +           NAME => "phy_ulpi_ddr",
56647 +           DEFAULT => 0,
56648 +           ENUM => [],
56649 +           LOW => 0,
56650 +           HIGH => 1
56651 +          },
56652 +         ];
56653 +
56654 +
56655 +#
56656 +#
56657 +sub check_arch {
56658 +  $_ = `uname -m`;
56659 +  chomp;
56660 +  unless (m/armv4tl/) {
56661 +    warn "# \n# Can't execute on $_.  Run on integrator platform.\n# \n";
56662 +    return 0;
56663 +  }
56664 +  return 1;
56665 +}
56666 +
56667 +#
56668 +#
56669 +sub load_module {
56670 +  my $params = shift;
56671 +  print "\nRemoving Module\n";
56672 +  system "rmmod dwc_otg";
56673 +  print "Loading Module\n";
56674 +  if ($params ne "") {
56675 +    print "Module Parameters: $params\n";
56676 +  }
56677 +  if (system("modprobe dwc_otg $params")) {
56678 +    warn "Unable to load module\n";
56679 +    return 0;
56680 +  }
56681 +  return 1;
56682 +}
56683 +
56684 +#
56685 +#
56686 +sub test_status {
56687 +  my $arg = shift;
56688 +
56689 +  print "\n";
56690 +
56691 +  if (defined $arg) {
56692 +    warn "WARNING: $arg\n";
56693 +  }
56694 +
56695 +  if ($errors > 0) {
56696 +    warn "TEST FAILED with $errors errors\n";
56697 +    return 0;
56698 +  } else {
56699 +    print "TEST PASSED\n";
56700 +    return 0 if (defined $arg);
56701 +  }
56702 +  return 1;
56703 +}
56704 +
56705 +#
56706 +#
56707 +@EXPORT = qw(
56708 +$sysfsdir
56709 +$paramdir
56710 +$params
56711 +$errors
56712 +check_arch
56713 +load_module
56714 +test_status
56715 +);
56716 +
56717 +1;
56718 diff --git a/drivers/usb/host/dwc_otg/test/test_mod_param.pl b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56719 new file mode 100644
56720 index 0000000..dc3820d
56721 --- /dev/null
56722 +++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56723 @@ -0,0 +1,133 @@
56724 +#!/usr/bin/perl -w
56725 +#
56726 +# Run this program on the integrator.
56727 +#
56728 +# - Tests module parameter default values.
56729 +# - Tests setting of valid module parameter values via modprobe.
56730 +# - Tests invalid module parameter values.
56731 +# -----------------------------------------------------------------------------
56732 +use strict;
56733 +use dwc_otg_test;
56734 +
56735 +check_arch() or die;
56736 +
56737 +#
56738 +#
56739 +sub test {
56740 +  my ($param,$expected) = @_;
56741 +  my $value = get($param);
56742 +
56743 +  if ($value == $expected) {
56744 +    print "$param = $value, okay\n";
56745 +  }
56746 +
56747 +  else {
56748 +    warn "ERROR: value of $param != $expected, $value\n";
56749 +    $errors ++;
56750 +  }
56751 +}
56752 +
56753 +#
56754 +#
56755 +sub get {
56756 +  my $param = shift;
56757 +  my $tmp = `cat $paramdir/$param`;
56758 +  chomp $tmp;
56759 +  return $tmp;
56760 +}
56761 +
56762 +#
56763 +#
56764 +sub test_main {
56765 +
56766 +  print "\nTesting Module Parameters\n";
56767 +
56768 +  load_module("") or die;
56769 +
56770 +  # Test initial values
56771 +  print "\nTesting Default Values\n";
56772 +  foreach (@{$params}) {
56773 +    test ($_->{NAME}, $_->{DEFAULT});
56774 +  }
56775 +
56776 +  # Test low value
56777 +  print "\nTesting Low Value\n";
56778 +  my $cmd_params = "";
56779 +  foreach (@{$params}) {
56780 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
56781 +  }
56782 +  load_module($cmd_params) or die;
56783 +
56784 +  foreach (@{$params}) {
56785 +    test ($_->{NAME}, $_->{LOW});
56786 +  }
56787 +
56788 +  # Test high value
56789 +  print "\nTesting High Value\n";
56790 +  $cmd_params = "";
56791 +  foreach (@{$params}) {
56792 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
56793 +  }
56794 +  load_module($cmd_params) or die;
56795 +
56796 +  foreach (@{$params}) {
56797 +    test ($_->{NAME}, $_->{HIGH});
56798 +  }
56799 +
56800 +  # Test Enum
56801 +  print "\nTesting Enumerated\n";
56802 +  foreach (@{$params}) {
56803 +    if (defined $_->{ENUM}) {
56804 +      my $value;
56805 +      foreach $value (@{$_->{ENUM}}) {
56806 +       $cmd_params = "$_->{NAME}=$value";
56807 +       load_module($cmd_params) or die;
56808 +       test ($_->{NAME}, $value);
56809 +      }
56810 +    }
56811 +  }
56812 +
56813 +  # Test Invalid Values
56814 +  print "\nTesting Invalid Values\n";
56815 +  $cmd_params = "";
56816 +  foreach (@{$params}) {
56817 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
56818 +  }
56819 +  load_module($cmd_params) or die;
56820 +
56821 +  foreach (@{$params}) {
56822 +    test ($_->{NAME}, $_->{DEFAULT});
56823 +  }
56824 +
56825 +  $cmd_params = "";
56826 +  foreach (@{$params}) {
56827 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
56828 +  }
56829 +  load_module($cmd_params) or die;
56830 +
56831 +  foreach (@{$params}) {
56832 +    test ($_->{NAME}, $_->{DEFAULT});
56833 +  }
56834 +
56835 +  print "\nTesting Enumerated\n";
56836 +  foreach (@{$params}) {
56837 +    if (defined $_->{ENUM}) {
56838 +      my $value;
56839 +      foreach $value (@{$_->{ENUM}}) {
56840 +       $value = $value + 1;
56841 +       $cmd_params = "$_->{NAME}=$value";
56842 +       load_module($cmd_params) or die;
56843 +       test ($_->{NAME}, $_->{DEFAULT});
56844 +       $value = $value - 2;
56845 +       $cmd_params = "$_->{NAME}=$value";
56846 +       load_module($cmd_params) or die;
56847 +       test ($_->{NAME}, $_->{DEFAULT});
56848 +      }
56849 +    }
56850 +  }
56851 +
56852 +  test_status() or die;
56853 +}
56854 +
56855 +test_main();
56856 +0;
56857 diff --git a/drivers/usb/host/dwc_otg/test/test_sysfs.pl b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
56858 new file mode 100644
56859 index 0000000..cdc9963
56860 --- /dev/null
56861 +++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
56862 @@ -0,0 +1,193 @@
56863 +#!/usr/bin/perl -w
56864 +#
56865 +# Run this program on the integrator
56866 +# - Tests select sysfs attributes.
56867 +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
56868 +# -----------------------------------------------------------------------------
56869 +use strict;
56870 +use dwc_otg_test;
56871 +
56872 +check_arch() or die;
56873 +
56874 +#
56875 +#
56876 +sub test {
56877 +  my ($attr,$expected) = @_;
56878 +  my $string = get($attr);
56879 +
56880 +  if ($string eq $expected) {
56881 +    printf("$attr = $string, okay\n");
56882 +  }
56883 +  else {
56884 +    warn "ERROR: value of $attr != $expected, $string\n";
56885 +    $errors ++;
56886 +  }
56887 +}
56888 +
56889 +#
56890 +#
56891 +sub set {
56892 +  my ($reg, $value) = @_;
56893 +  system "echo $value > $sysfsdir/$reg";
56894 +}
56895 +
56896 +#
56897 +#
56898 +sub get {
56899 +  my $attr = shift;
56900 +  my $string = `cat $sysfsdir/$attr`;
56901 +  chomp $string;
56902 +  if ($string =~ m/\s\=\s/) {
56903 +    my $tmp;
56904 +    ($tmp, $string) = split /\s=\s/, $string;
56905 +  }
56906 +  return $string;
56907 +}
56908 +
56909 +#
56910 +#
56911 +sub test_main {
56912 +  print("\nTesting Sysfs Attributes\n");
56913 +
56914 +  load_module("") or die;
56915 +
56916 +  # Test initial values of regoffset/regvalue/guid/gsnpsid
56917 +  print("\nTesting Default Values\n");
56918 +
56919 +  test("regoffset", "0xffffffff");
56920 +  test("regvalue", "invalid offset");
56921 +  test("guid", "0x12345678");  # this will fail if it has been changed
56922 +  test("gsnpsid", "0x4f54200a");
56923 +
56924 +  # Test operation of regoffset/regvalue
56925 +  print("\nTesting regoffset\n");
56926 +  set('regoffset', '5a5a5a5a');
56927 +  test("regoffset", "0xffffffff");
56928 +
56929 +  set('regoffset', '0');
56930 +  test("regoffset", "0x00000000");
56931 +
56932 +  set('regoffset', '40000');
56933 +  test("regoffset", "0x00000000");
56934 +
56935 +  set('regoffset', '3ffff');
56936 +  test("regoffset", "0x0003ffff");
56937 +
56938 +  set('regoffset', '1');
56939 +  test("regoffset", "0x00000001");
56940 +
56941 +  print("\nTesting regvalue\n");
56942 +  set('regoffset', '3c');
56943 +  test("regvalue", "0x12345678");
56944 +  set('regvalue', '5a5a5a5a');
56945 +  test("regvalue", "0x5a5a5a5a");
56946 +  set('regvalue','a5a5a5a5');
56947 +  test("regvalue", "0xa5a5a5a5");
56948 +  set('guid','12345678');
56949 +
56950 +  # Test HNP Capable
56951 +  print("\nTesting HNP Capable bit\n");
56952 +  set('hnpcapable', '1');
56953 +  test("hnpcapable", "0x1");
56954 +  set('hnpcapable','0');
56955 +  test("hnpcapable", "0x0");
56956 +
56957 +  set('regoffset','0c');
56958 +
56959 +  my $old = get('gusbcfg');
56960 +  print("setting hnpcapable\n");
56961 +  set('hnpcapable', '1');
56962 +  test("hnpcapable", "0x1");
56963 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
56964 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
56965 +
56966 +  $old = get('gusbcfg');
56967 +  print("clearing hnpcapable\n");
56968 +  set('hnpcapable', '0');
56969 +  test("hnpcapable", "0x0");
56970 +  test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56971 +  test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56972 +
56973 +  # Test SRP Capable
56974 +  print("\nTesting SRP Capable bit\n");
56975 +  set('srpcapable', '1');
56976 +  test("srpcapable", "0x1");
56977 +  set('srpcapable','0');
56978 +  test("srpcapable", "0x0");
56979 +
56980 +  set('regoffset','0c');
56981 +
56982 +  $old = get('gusbcfg');
56983 +  print("setting srpcapable\n");
56984 +  set('srpcapable', '1');
56985 +  test("srpcapable", "0x1");
56986 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
56987 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
56988 +
56989 +  $old = get('gusbcfg');
56990 +  print("clearing srpcapable\n");
56991 +  set('srpcapable', '0');
56992 +  test("srpcapable", "0x0");
56993 +  test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
56994 +  test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
56995 +
56996 +  # Test GGPIO
56997 +  print("\nTesting GGPIO\n");
56998 +  set('ggpio','5a5a5a5a');
56999 +  test('ggpio','0x5a5a0000');
57000 +  set('ggpio','a5a5a5a5');
57001 +  test('ggpio','0xa5a50000');
57002 +  set('ggpio','11110000');
57003 +  test('ggpio','0x11110000');
57004 +  set('ggpio','00001111');
57005 +  test('ggpio','0x00000000');
57006 +
57007 +  # Test DEVSPEED
57008 +  print("\nTesting DEVSPEED\n");
57009 +  set('regoffset','800');
57010 +  $old = get('regvalue');
57011 +  set('devspeed','0');
57012 +  test('devspeed','0x0');
57013 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
57014 +  set('devspeed','1');
57015 +  test('devspeed','0x1');
57016 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
57017 +  set('devspeed','2');
57018 +  test('devspeed','0x2');
57019 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
57020 +  set('devspeed','3');
57021 +  test('devspeed','0x3');
57022 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
57023 +  set('devspeed','4');
57024 +  test('devspeed','0x0');
57025 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
57026 +  set('devspeed','5');
57027 +  test('devspeed','0x1');
57028 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
57029 +
57030 +
57031 +  #  mode      Returns the current mode:0 for device mode1 for host mode       Read
57032 +  #  hnp       Initiate the Host Negotiation Protocol.  Read returns the status.       Read/Write
57033 +  #  srp       Initiate the Session Request Protocol.  Read returns the status.        Read/Write
57034 +  #  buspower  Get or Set the Power State of the bus (0 - Off or 1 - On)       Read/Write
57035 +  #  bussuspend        Suspend the USB bus.    Read/Write
57036 +  #  busconnected      Get the connection status of the bus    Read
57037 +
57038 +  #  gotgctl   Get or set the Core Control Status Register.    Read/Write
57039 +  ##  gusbcfg  Get or set the Core USB Configuration Register  Read/Write
57040 +  #  grxfsiz   Get or set the Receive FIFO Size Register       Read/Write
57041 +  #  gnptxfsiz Get or set the non-periodic Transmit Size Register      Read/Write
57042 +  #  gpvndctl  Get or set the PHY Vendor Control Register      Read/Write
57043 +  ##  ggpio    Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
57044 +  ##  guid     Get or set the value of the User ID Register    Read/Write
57045 +  ##  gsnpsid  Get the value of the Synopsys ID Regester       Read
57046 +  ##  devspeed Get or set the device speed setting in the DCFG register        Read/Write
57047 +  #  enumspeed Gets the device enumeration Speed.      Read
57048 +  #  hptxfsiz  Get the value of the Host Periodic Transmit FIFO        Read
57049 +  #  hprt0     Get or Set the value in the Host Port Control and Status Register       Read/Write
57050 +
57051 +  test_status("TEST NYI") or die;
57052 +}
57053 +
57054 +test_main();
57055 +0;
57056 -- 
57057 1.8.3.2
57058