ralink: fix when tx done is 0 also need to clean interrupt status
[openwrt.git] / target / linux / brcm2708 / patches-3.14 / 0003-Add-dwc_otg-driver.patch
1 From 8065edf883d2adeea72ab1d64d50931501959a83 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 03/54] Add dwc_otg driver
5
6 Signed-off-by: popcornmix <popcornmix@gmail.com>
7 ---
8  drivers/usb/Makefile                               |    1 +
9  drivers/usb/core/generic.c                         |    1 +
10  drivers/usb/core/message.c                         |   79 +
11  drivers/usb/core/otg_whitelist.h                   |  160 +-
12  drivers/usb/gadget/file_storage.c                  | 3676 ++++++++++
13  drivers/usb/host/Kconfig                           |   13 +
14  drivers/usb/host/Makefile                          |    2 +
15  drivers/usb/host/dwc_common_port/Makefile          |   58 +
16  drivers/usb/host/dwc_common_port/Makefile.fbsd     |   17 +
17  drivers/usb/host/dwc_common_port/Makefile.linux    |   49 +
18  drivers/usb/host/dwc_common_port/changes.txt       |  174 +
19  drivers/usb/host/dwc_common_port/doc/doxygen.cfg   |  270 +
20  drivers/usb/host/dwc_common_port/dwc_cc.c          |  532 ++
21  drivers/usb/host/dwc_common_port/dwc_cc.h          |  224 +
22  drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++
23  .../usb/host/dwc_common_port/dwc_common_linux.c    | 1421 ++++
24  drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++
25  drivers/usb/host/dwc_common_port/dwc_crypto.c      |  308 +
26  drivers/usb/host/dwc_common_port/dwc_crypto.h      |  111 +
27  drivers/usb/host/dwc_common_port/dwc_dh.c          |  291 +
28  drivers/usb/host/dwc_common_port/dwc_dh.h          |  106 +
29  drivers/usb/host/dwc_common_port/dwc_list.h        |  594 ++
30  drivers/usb/host/dwc_common_port/dwc_mem.c         |  245 +
31  drivers/usb/host/dwc_common_port/dwc_modpow.c      |  636 ++
32  drivers/usb/host/dwc_common_port/dwc_modpow.h      |   34 +
33  drivers/usb/host/dwc_common_port/dwc_notifier.c    |  319 +
34  drivers/usb/host/dwc_common_port/dwc_notifier.h    |  122 +
35  drivers/usb/host/dwc_common_port/dwc_os.h          | 1260 ++++
36  drivers/usb/host/dwc_common_port/usb.h             |  946 +++
37  drivers/usb/host/dwc_otg/Makefile                  |   80 +
38  drivers/usb/host/dwc_otg/doc/doxygen.cfg           |  224 +
39  drivers/usb/host/dwc_otg/dummy_audio.c             | 1575 +++++
40  drivers/usb/host/dwc_otg/dwc_cfi_common.h          |  142 +
41  drivers/usb/host/dwc_otg/dwc_otg_adp.c             |  854 +++
42  drivers/usb/host/dwc_otg/dwc_otg_adp.h             |   80 +
43  drivers/usb/host/dwc_otg/dwc_otg_attr.c            | 1210 ++++
44  drivers/usb/host/dwc_otg/dwc_otg_attr.h            |   89 +
45  drivers/usb/host/dwc_otg/dwc_otg_cfi.c             | 1876 +++++
46  drivers/usb/host/dwc_otg/dwc_otg_cfi.h             |  320 +
47  drivers/usb/host/dwc_otg/dwc_otg_cil.c             | 7151 ++++++++++++++++++++
48  drivers/usb/host/dwc_otg/dwc_otg_cil.h             | 1464 ++++
49  drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c        | 1563 +++++
50  drivers/usb/host/dwc_otg/dwc_otg_core_if.h         |  705 ++
51  drivers/usb/host/dwc_otg/dwc_otg_dbg.h             |  116 +
52  drivers/usb/host/dwc_otg/dwc_otg_driver.c          | 1700 +++++
53  drivers/usb/host/dwc_otg/dwc_otg_driver.h          |   86 +
54  drivers/usb/host/dwc_otg/dwc_otg_hcd.c             | 3473 ++++++++++
55  drivers/usb/host/dwc_otg/dwc_otg_hcd.h             |  824 +++
56  drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c        | 1133 ++++
57  drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h          |  412 ++
58  drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c        | 2106 ++++++
59  drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c       |  893 +++
60  drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c       |  922 +++
61  drivers/usb/host/dwc_otg/dwc_otg_os_dep.h          |  185 +
62  drivers/usb/host/dwc_otg/dwc_otg_pcd.c             | 2708 ++++++++
63  drivers/usb/host/dwc_otg/dwc_otg_pcd.h             |  266 +
64  drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h          |  360 +
65  drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c        | 5147 ++++++++++++++
66  drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c       | 1358 ++++
67  drivers/usb/host/dwc_otg/dwc_otg_regs.h            | 2550 +++++++
68  drivers/usb/host/dwc_otg/test/Makefile             |   16 +
69  drivers/usb/host/dwc_otg/test/dwc_otg_test.pm      |  337 +
70  drivers/usb/host/dwc_otg/test/test_mod_param.pl    |  133 +
71  drivers/usb/host/dwc_otg/test/test_sysfs.pl        |  193 +
72  64 files changed, 56440 insertions(+), 43 deletions(-)
73  create mode 100644 drivers/usb/gadget/file_storage.c
74  create mode 100644 drivers/usb/host/dwc_common_port/Makefile
75  create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd
76  create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux
77  create mode 100644 drivers/usb/host/dwc_common_port/changes.txt
78  create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg
79  create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c
80  create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h
81  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
82  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c
83  create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
84  create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c
85  create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h
86  create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c
87  create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h
88  create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h
89  create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c
90  create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c
91  create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h
92  create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c
93  create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h
94  create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h
95  create mode 100644 drivers/usb/host/dwc_common_port/usb.h
96  create mode 100644 drivers/usb/host/dwc_otg/Makefile
97  create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg
98  create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c
99  create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h
100  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.c
101  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.h
102  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c
103  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h
104  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c
105  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h
106  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c
107  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h
108  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
109  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h
110  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
111  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c
112  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h
113  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
114  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h
115  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
116  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
117  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
118  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
119  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
120  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
121  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c
122  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h
123  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
124  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
125  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
126  create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h
127  create mode 100644 drivers/usb/host/dwc_otg/test/Makefile
128  create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
129  create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl
130  create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl
131
132 --- a/drivers/usb/Makefile
133 +++ b/drivers/usb/Makefile
134 @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_U132_HCD)    += host/
135  obj-$(CONFIG_USB_R8A66597_HCD) += host/
136  obj-$(CONFIG_USB_HWA_HCD)      += host/
137  obj-$(CONFIG_USB_ISP1760_HCD)  += host/
138 +obj-$(CONFIG_USB_DWCOTG)       += host/
139  obj-$(CONFIG_USB_IMX21_HCD)    += host/
140  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += host/
141  obj-$(CONFIG_USB_FUSBH200_HCD) += host/
142 --- a/drivers/usb/core/generic.c
143 +++ b/drivers/usb/core/generic.c
144 @@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_
145                 dev_warn(&udev->dev,
146                         "no configuration chosen from %d choice%s\n",
147                         num_configs, plural(num_configs));
148 +               dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
149         }
150         return i;
151  }
152 --- a/drivers/usb/core/message.c
153 +++ b/drivers/usb/core/message.c
154 @@ -1888,6 +1888,85 @@ free_interfaces:
155         if (cp->string == NULL &&
156                         !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
157                 cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
158 +/* Uncomment this define to enable the HS Electrical Test support */
159 +#define DWC_HS_ELECT_TST 1
160 +#ifdef DWC_HS_ELECT_TST
161 +               /* Here we implement the HS Electrical Test support. The
162 +                * tester uses a vendor ID of 0x1A0A to indicate we should
163 +                * run a special test sequence. The product ID tells us
164 +                * which sequence to run. We invoke the test sequence by
165 +                * sending a non-standard SetFeature command to our root
166 +                * hub port. Our dwc_otg_hcd_hub_control() routine will
167 +                * recognize the command and perform the desired test
168 +                * sequence.
169 +                */
170 +               if (dev->descriptor.idVendor == 0x1A0A) {
171 +                       /* HSOTG Electrical Test */
172 +                       dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
173 +
174 +                       if (dev->bus && dev->bus->root_hub) {
175 +                               struct usb_device *hdev = dev->bus->root_hub;
176 +                               dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
177 +
178 +                               switch (dev->descriptor.idProduct) {
179 +                               case 0x0101:    /* TEST_SE0_NAK */
180 +                                       dev_warn(&dev->dev, "TEST_SE0_NAK\n");
181 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
182 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
183 +                                                       USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
184 +                                       break;
185 +
186 +                               case 0x0102:    /* TEST_J */
187 +                                       dev_warn(&dev->dev, "TEST_J\n");
188 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
189 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
190 +                                                       USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
191 +                                       break;
192 +
193 +                               case 0x0103:    /* TEST_K */
194 +                                       dev_warn(&dev->dev, "TEST_K\n");
195 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
196 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
197 +                                                       USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
198 +                                       break;
199 +
200 +                               case 0x0104:    /* TEST_PACKET */
201 +                                       dev_warn(&dev->dev, "TEST_PACKET\n");
202 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
203 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
204 +                                                       USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
205 +                                       break;
206 +
207 +                               case 0x0105:    /* TEST_FORCE_ENABLE */
208 +                                       dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
209 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
210 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
211 +                                                       USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
212 +                                       break;
213 +
214 +                               case 0x0106:    /* HS_HOST_PORT_SUSPEND_RESUME */
215 +                                       dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
216 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
217 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
218 +                                                       USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
219 +                                       break;
220 +
221 +                               case 0x0107:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
222 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
223 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
224 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
225 +                                                       USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
226 +                                       break;
227 +
228 +                               case 0x0108:    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
229 +                                       dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
230 +                                       usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
231 +                                                       USB_REQ_SET_FEATURE, USB_RT_PORT,
232 +                                                       USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
233 +                               }
234 +                       }
235 +               }
236 +#endif /* DWC_HS_ELECT_TST */
237  
238         /* Now that the interfaces are installed, re-enable LPM. */
239         usb_unlocked_enable_lpm(dev);
240 --- a/drivers/usb/core/otg_whitelist.h
241 +++ b/drivers/usb/core/otg_whitelist.h
242 @@ -19,33 +19,82 @@
243  static struct usb_device_id whitelist_table [] = {
244  
245  /* hubs are optional in OTG, but very handy ... */
246 +#define CERT_WITHOUT_HUBS
247 +#if defined(CERT_WITHOUT_HUBS)
248 +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
249 +#else
250  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
251  { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
252 +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
253 +#endif
254  
255  #ifdef CONFIG_USB_PRINTER              /* ignoring nonstatic linkage! */
256  /* FIXME actually, printers are NOT supposed to use device classes;
257   * they're supposed to use interface classes...
258   */
259 -{ USB_DEVICE_INFO(7, 1, 1) },
260 -{ USB_DEVICE_INFO(7, 1, 2) },
261 -{ USB_DEVICE_INFO(7, 1, 3) },
262 +//{ USB_DEVICE_INFO(7, 1, 1) },
263 +//{ USB_DEVICE_INFO(7, 1, 2) },
264 +//{ USB_DEVICE_INFO(7, 1, 3) },
265  #endif
266  
267  #ifdef CONFIG_USB_NET_CDCETHER
268  /* Linux-USB CDC Ethernet gadget */
269 -{ USB_DEVICE(0x0525, 0xa4a1), },
270 +//{ USB_DEVICE(0x0525, 0xa4a1), },
271  /* Linux-USB CDC Ethernet + RNDIS gadget */
272 -{ USB_DEVICE(0x0525, 0xa4a2), },
273 +//{ USB_DEVICE(0x0525, 0xa4a2), },
274  #endif
275  
276  #if    defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
277  /* gadget zero, for testing */
278 -{ USB_DEVICE(0x0525, 0xa4a0), },
279 +//{ USB_DEVICE(0x0525, 0xa4a0), },
280  #endif
281  
282 +/* OPT Tester */
283 +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
284 +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
285 +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
286 +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
287 +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
288 +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME  */
289 +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
290 +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
291 +
292 +/* Sony cameras */
293 +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
294 +
295 +/* Memory Devices */
296 +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
297 +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
298 +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
299 +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD  */
300 +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
301 +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
302 +
303 +/* HP Printers */
304 +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
305 +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
306 +
307 +/* Speakers */
308 +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
309 +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
310 +
311  { }    /* Terminating entry */
312  };
313  
314 +static inline void report_errors(struct usb_device *dev)
315 +{
316 +       /* OTG MESSAGE: report errors here, customize to match your product */
317 +       dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
318 +                le16_to_cpu(dev->descriptor.idVendor),
319 +                le16_to_cpu(dev->descriptor.idProduct));
320 +        if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
321 +                dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
322 +        } else {
323 +                dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
324 +        }
325 +}
326 +
327 +
328  static int is_targeted(struct usb_device *dev)
329  {
330         struct usb_device_id    *id = whitelist_table;
331 @@ -55,58 +104,83 @@ static int is_targeted(struct usb_device
332                 return 1;
333  
334         /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
335 -       if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
336 -            le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
337 -               return 0;
338 +       if (dev->descriptor.idVendor == 0x1a0a &&
339 +            dev->descriptor.idProduct == 0xbadd) {
340 +                return 0;
341 +       } else if (!enable_whitelist) {
342 +               return 1;
343 +        } else {
344  
345 -       /* NOTE: can't use usb_match_id() since interface caches
346 -        * aren't set up yet. this is cut/paste from that code.
347 -        */
348 -       for (id = whitelist_table; id->match_flags; id++) {
349 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
350 -                   id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
351 -                       continue;
352 -
353 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
354 -                   id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
355 -                       continue;
356 -
357 -               /* No need to test id->bcdDevice_lo != 0, since 0 is never
358 -                  greater than any unsigned number. */
359 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
360 -                   (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
361 -                       continue;
362 -
363 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
364 -                   (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
365 -                       continue;
366 -
367 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
368 -                   (id->bDeviceClass != dev->descriptor.bDeviceClass))
369 -                       continue;
370 -
371 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
372 -                   (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
373 -                       continue;
374 -
375 -               if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
376 -                   (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
377 -                       continue;
378 +#ifdef DEBUG
379 +                dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
380 +                        dev->descriptor.idVendor,
381 +                        dev->descriptor.idProduct,
382 +                        dev->descriptor.bDeviceClass,
383 +                        dev->descriptor.bDeviceSubClass,
384 +                        dev->descriptor.bDeviceProtocol);
385 +#endif
386  
387                 return 1;
388 +               /* NOTE: can't use usb_match_id() since interface caches
389 +                * aren't set up yet. this is cut/paste from that code.
390 +                */
391 +               for (id = whitelist_table; id->match_flags; id++) {
392 +#ifdef DEBUG
393 +                       dev_dbg(&dev->dev,
394 +                               "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
395 +                               id->idVendor,
396 +                               id->idProduct,
397 +                               id->bDeviceClass,
398 +                               id->bDeviceSubClass,
399 +                               id->bDeviceProtocol);
400 +#endif
401 +
402 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
403 +                           id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
404 +                               continue;
405 +
406 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
407 +                           id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
408 +                               continue;
409 +
410 +                       /* No need to test id->bcdDevice_lo != 0, since 0 is never
411 +                          greater than any unsigned number. */
412 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
413 +                           (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
414 +                               continue;
415 +
416 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
417 +                           (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
418 +                               continue;
419 +
420 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
421 +                           (id->bDeviceClass != dev->descriptor.bDeviceClass))
422 +                               continue;
423 +
424 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
425 +                           (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
426 +                               continue;
427 +
428 +                       if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
429 +                           (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
430 +                               continue;
431 +
432 +                       return 1;
433 +               }
434         }
435  
436         /* add other match criteria here ... */
437  
438 -
439 -       /* OTG MESSAGE: report errors here, customize to match your product */
440 -       dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
441 -               le16_to_cpu(dev->descriptor.idVendor),
442 -               le16_to_cpu(dev->descriptor.idProduct));
443  #ifdef CONFIG_USB_OTG_WHITELIST
444 +       report_errors(dev);
445         return 0;
446  #else
447 -       return 1;
448 +       if (enable_whitelist) {
449 +               report_errors(dev);
450 +               return 0;
451 +       } else {
452 +               return 1;
453 +       }
454  #endif
455  }
456  
457 --- /dev/null
458 +++ b/drivers/usb/gadget/file_storage.c
459 @@ -0,0 +1,3676 @@
460 +/*
461 + * file_storage.c -- File-backed USB Storage Gadget, for USB development
462 + *
463 + * Copyright (C) 2003-2008 Alan Stern
464 + * All rights reserved.
465 + *
466 + * Redistribution and use in source and binary forms, with or without
467 + * modification, are permitted provided that the following conditions
468 + * are met:
469 + * 1. Redistributions of source code must retain the above copyright
470 + *    notice, this list of conditions, and the following disclaimer,
471 + *    without modification.
472 + * 2. Redistributions in binary form must reproduce the above copyright
473 + *    notice, this list of conditions and the following disclaimer in the
474 + *    documentation and/or other materials provided with the distribution.
475 + * 3. The names of the above-listed copyright holders may not be used
476 + *    to endorse or promote products derived from this software without
477 + *    specific prior written permission.
478 + *
479 + * ALTERNATIVELY, this software may be distributed under the terms of the
480 + * GNU General Public License ("GPL") as published by the Free Software
481 + * Foundation, either version 2 of that License or (at your option) any
482 + * later version.
483 + *
484 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
485 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
486 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
487 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
488 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
489 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
490 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
491 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
492 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
493 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
494 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
495 + */
496 +
497 +
498 +/*
499 + * The File-backed Storage Gadget acts as a USB Mass Storage device,
500 + * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
501 + * to providing an example of a genuinely useful gadget driver for a USB
502 + * device, it also illustrates a technique of double-buffering for increased
503 + * throughput.  Last but not least, it gives an easy way to probe the
504 + * behavior of the Mass Storage drivers in a USB host.
505 + *
506 + * Backing storage is provided by a regular file or a block device, specified
507 + * by the "file" module parameter.  Access can be limited to read-only by
508 + * setting the optional "ro" module parameter.  (For CD-ROM emulation,
509 + * access is always read-only.)  The gadget will indicate that it has
510 + * removable media if the optional "removable" module parameter is set.
511 + *
512 + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
513 + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
514 + * by the optional "transport" module parameter.  It also supports the
515 + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
516 + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
517 + * the optional "protocol" module parameter.  In addition, the default
518 + * Vendor ID, Product ID, release number and serial number can be overridden.
519 + *
520 + * There is support for multiple logical units (LUNs), each of which has
521 + * its own backing file.  The number of LUNs can be set using the optional
522 + * "luns" module parameter (anywhere from 1 to 8), and the corresponding
523 + * files are specified using comma-separated lists for "file" and "ro".
524 + * The default number of LUNs is taken from the number of "file" elements;
525 + * it is 1 if "file" is not given.  If "removable" is not set then a backing
526 + * file must be specified for each LUN.  If it is set, then an unspecified
527 + * or empty backing filename means the LUN's medium is not loaded.  Ideally
528 + * each LUN would be settable independently as a disk drive or a CD-ROM
529 + * drive, but currently all LUNs have to be the same type.  The CD-ROM
530 + * emulation includes a single data track and no audio tracks; hence there
531 + * need be only one backing file per LUN.
532 + *
533 + * Requirements are modest; only a bulk-in and a bulk-out endpoint are
534 + * needed (an interrupt-out endpoint is also needed for CBI).  The memory
535 + * requirement amounts to two 16K buffers, size configurable by a parameter.
536 + * Support is included for both full-speed and high-speed operation.
537 + *
538 + * Note that the driver is slightly non-portable in that it assumes a
539 + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
540 + * interrupt-in endpoints.  With most device controllers this isn't an
541 + * issue, but there may be some with hardware restrictions that prevent
542 + * a buffer from being used by more than one endpoint.
543 + *
544 + * Module options:
545 + *
546 + *     file=filename[,filename...]
547 + *                             Required if "removable" is not set, names of
548 + *                                     the files or block devices used for
549 + *                                     backing storage
550 + *     serial=HHHH...          Required serial number (string of hex chars)
551 + *     ro=b[,b...]             Default false, booleans for read-only access
552 + *     removable               Default false, boolean for removable media
553 + *     luns=N                  Default N = number of filenames, number of
554 + *                                     LUNs to support
555 + *     nofua=b[,b...]          Default false, booleans for ignore FUA flag
556 + *                                     in SCSI WRITE(10,12) commands
557 + *     stall                   Default determined according to the type of
558 + *                                     USB device controller (usually true),
559 + *                                     boolean to permit the driver to halt
560 + *                                     bulk endpoints
561 + *     cdrom                   Default false, boolean for whether to emulate
562 + *                                     a CD-ROM drive
563 + *     transport=XXX           Default BBB, transport name (CB, CBI, or BBB)
564 + *     protocol=YYY            Default SCSI, protocol name (RBC, 8020 or
565 + *                                     ATAPI, QIC, UFI, 8070, or SCSI;
566 + *                                     also 1 - 6)
567 + *     vendor=0xVVVV           Default 0x0525 (NetChip), USB Vendor ID
568 + *     product=0xPPPP          Default 0xa4a5 (FSG), USB Product ID
569 + *     release=0xRRRR          Override the USB release number (bcdDevice)
570 + *     buflen=N                Default N=16384, buffer size used (will be
571 + *                                     rounded down to a multiple of
572 + *                                     PAGE_CACHE_SIZE)
573 + *
574 + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
575 + * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
576 + * default values are used for everything else.
577 + *
578 + * The pathnames of the backing files and the ro settings are available in
579 + * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
580 + * the gadget's sysfs directory.  If the "removable" option is set, writing to
581 + * these files will simulate ejecting/loading the medium (writing an empty
582 + * line means eject) and adjusting a write-enable tab.  Changes to the ro
583 + * setting are not allowed when the medium is loaded or if CD-ROM emulation
584 + * is being used.
585 + *
586 + * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
587 + * The driver's SCSI command interface was based on the "Information
588 + * technology - Small Computer System Interface - 2" document from
589 + * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
590 + * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
591 + * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
592 + * "Universal Serial Bus Mass Storage Class UFI Command Specification"
593 + * document, Revision 1.0, December 14, 1998, available at
594 + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
595 + */
596 +
597 +
598 +/*
599 + *                             Driver Design
600 + *
601 + * The FSG driver is fairly straightforward.  There is a main kernel
602 + * thread that handles most of the work.  Interrupt routines field
603 + * callbacks from the controller driver: bulk- and interrupt-request
604 + * completion notifications, endpoint-0 events, and disconnect events.
605 + * Completion events are passed to the main thread by wakeup calls.  Many
606 + * ep0 requests are handled at interrupt time, but SetInterface,
607 + * SetConfiguration, and device reset requests are forwarded to the
608 + * thread in the form of "exceptions" using SIGUSR1 signals (since they
609 + * should interrupt any ongoing file I/O operations).
610 + *
611 + * The thread's main routine implements the standard command/data/status
612 + * parts of a SCSI interaction.  It and its subroutines are full of tests
613 + * for pending signals/exceptions -- all this polling is necessary since
614 + * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
615 + * indication that the driver really wants to be running in userspace.)
616 + * An important point is that so long as the thread is alive it keeps an
617 + * open reference to the backing file.  This will prevent unmounting
618 + * the backing file's underlying filesystem and could cause problems
619 + * during system shutdown, for example.  To prevent such problems, the
620 + * thread catches INT, TERM, and KILL signals and converts them into
621 + * an EXIT exception.
622 + *
623 + * In normal operation the main thread is started during the gadget's
624 + * fsg_bind() callback and stopped during fsg_unbind().  But it can also
625 + * exit when it receives a signal, and there's no point leaving the
626 + * gadget running when the thread is dead.  So just before the thread
627 + * exits, it deregisters the gadget driver.  This makes things a little
628 + * tricky: The driver is deregistered at two places, and the exiting
629 + * thread can indirectly call fsg_unbind() which in turn can tell the
630 + * thread to exit.  The first problem is resolved through the use of the
631 + * REGISTERED atomic bitflag; the driver will only be deregistered once.
632 + * The second problem is resolved by having fsg_unbind() check
633 + * fsg->state; it won't try to stop the thread if the state is already
634 + * FSG_STATE_TERMINATED.
635 + *
636 + * To provide maximum throughput, the driver uses a circular pipeline of
637 + * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
638 + * arbitrarily long; in practice the benefits don't justify having more
639 + * than 2 stages (i.e., double buffering).  But it helps to think of the
640 + * pipeline as being a long one.  Each buffer head contains a bulk-in and
641 + * a bulk-out request pointer (since the buffer can be used for both
642 + * output and input -- directions always are given from the host's
643 + * point of view) as well as a pointer to the buffer and various state
644 + * variables.
645 + *
646 + * Use of the pipeline follows a simple protocol.  There is a variable
647 + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
648 + * At any time that buffer head may still be in use from an earlier
649 + * request, so each buffer head has a state variable indicating whether
650 + * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
651 + * buffer head to be EMPTY, filling the buffer either by file I/O or by
652 + * USB I/O (during which the buffer head is BUSY), and marking the buffer
653 + * head FULL when the I/O is complete.  Then the buffer will be emptied
654 + * (again possibly by USB I/O, during which it is marked BUSY) and
655 + * finally marked EMPTY again (possibly by a completion routine).
656 + *
657 + * A module parameter tells the driver to avoid stalling the bulk
658 + * endpoints wherever the transport specification allows.  This is
659 + * necessary for some UDCs like the SuperH, which cannot reliably clear a
660 + * halt on a bulk endpoint.  However, under certain circumstances the
661 + * Bulk-only specification requires a stall.  In such cases the driver
662 + * will halt the endpoint and set a flag indicating that it should clear
663 + * the halt in software during the next device reset.  Hopefully this
664 + * will permit everything to work correctly.  Furthermore, although the
665 + * specification allows the bulk-out endpoint to halt when the host sends
666 + * too much data, implementing this would cause an unavoidable race.
667 + * The driver will always use the "no-stall" approach for OUT transfers.
668 + *
669 + * One subtle point concerns sending status-stage responses for ep0
670 + * requests.  Some of these requests, such as device reset, can involve
671 + * interrupting an ongoing file I/O operation, which might take an
672 + * arbitrarily long time.  During that delay the host might give up on
673 + * the original ep0 request and issue a new one.  When that happens the
674 + * driver should not notify the host about completion of the original
675 + * request, as the host will no longer be waiting for it.  So the driver
676 + * assigns to each ep0 request a unique tag, and it keeps track of the
677 + * tag value of the request associated with a long-running exception
678 + * (device-reset, interface-change, or configuration-change).  When the
679 + * exception handler is finished, the status-stage response is submitted
680 + * only if the current ep0 request tag is equal to the exception request
681 + * tag.  Thus only the most recently received ep0 request will get a
682 + * status-stage response.
683 + *
684 + * Warning: This driver source file is too long.  It ought to be split up
685 + * into a header file plus about 3 separate .c files, to handle the details
686 + * of the Gadget, USB Mass Storage, and SCSI protocols.
687 + */
688 +
689 +
690 +/* #define VERBOSE_DEBUG */
691 +/* #define DUMP_MSGS */
692 +
693 +
694 +#include <linux/blkdev.h>
695 +#include <linux/completion.h>
696 +#include <linux/dcache.h>
697 +#include <linux/delay.h>
698 +#include <linux/device.h>
699 +#include <linux/fcntl.h>
700 +#include <linux/file.h>
701 +#include <linux/fs.h>
702 +#include <linux/kref.h>
703 +#include <linux/kthread.h>
704 +#include <linux/limits.h>
705 +#include <linux/module.h>
706 +#include <linux/rwsem.h>
707 +#include <linux/slab.h>
708 +#include <linux/spinlock.h>
709 +#include <linux/string.h>
710 +#include <linux/freezer.h>
711 +#include <linux/utsname.h>
712 +
713 +#include <linux/usb/ch9.h>
714 +#include <linux/usb/gadget.h>
715 +
716 +#include "gadget_chips.h"
717 +
718 +
719 +
720 +/*
721 + * Kbuild is not very cooperative with respect to linking separately
722 + * compiled library objects into one module.  So for now we won't use
723 + * separate compilation ... ensuring init/exit sections work to shrink
724 + * the runtime footprint, and giving us at least some parts of what
725 + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
726 + */
727 +#include "usbstring.c"
728 +#include "config.c"
729 +#include "epautoconf.c"
730 +
731 +/*-------------------------------------------------------------------------*/
732 +
733 +#define DRIVER_DESC            "File-backed Storage Gadget"
734 +#define DRIVER_NAME            "g_file_storage"
735 +#define DRIVER_VERSION         "1 September 2010"
736 +
737 +static       char fsg_string_manufacturer[64];
738 +static const char fsg_string_product[] = DRIVER_DESC;
739 +static const char fsg_string_config[] = "Self-powered";
740 +static const char fsg_string_interface[] = "Mass Storage";
741 +
742 +
743 +#include "storage_common.c"
744 +
745 +
746 +MODULE_DESCRIPTION(DRIVER_DESC);
747 +MODULE_AUTHOR("Alan Stern");
748 +MODULE_LICENSE("Dual BSD/GPL");
749 +
750 +/*
751 + * This driver assumes self-powered hardware and has no way for users to
752 + * trigger remote wakeup.  It uses autoconfiguration to select endpoints
753 + * and endpoint addresses.
754 + */
755 +
756 +
757 +/*-------------------------------------------------------------------------*/
758 +
759 +
760 +/* Encapsulate the module parameter settings */
761 +
762 +static struct {
763 +       char            *file[FSG_MAX_LUNS];
764 +       char            *serial;
765 +       bool            ro[FSG_MAX_LUNS];
766 +       bool            nofua[FSG_MAX_LUNS];
767 +       unsigned int    num_filenames;
768 +       unsigned int    num_ros;
769 +       unsigned int    num_nofuas;
770 +       unsigned int    nluns;
771 +
772 +       bool            removable;
773 +       bool            can_stall;
774 +       bool            cdrom;
775 +
776 +       char            *transport_parm;
777 +       char            *protocol_parm;
778 +       unsigned short  vendor;
779 +       unsigned short  product;
780 +       unsigned short  release;
781 +       unsigned int    buflen;
782 +
783 +       int             transport_type;
784 +       char            *transport_name;
785 +       int             protocol_type;
786 +       char            *protocol_name;
787 +
788 +} mod_data = {                                 // Default values
789 +       .transport_parm         = "BBB",
790 +       .protocol_parm          = "SCSI",
791 +       .removable              = 0,
792 +       .can_stall              = 1,
793 +       .cdrom                  = 0,
794 +       .vendor                 = FSG_VENDOR_ID,
795 +       .product                = FSG_PRODUCT_ID,
796 +       .release                = 0xffff,       // Use controller chip type
797 +       .buflen                 = 16384,
798 +       };
799 +
800 +
801 +module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
802 +               S_IRUGO);
803 +MODULE_PARM_DESC(file, "names of backing files or devices");
804 +
805 +module_param_named(serial, mod_data.serial, charp, S_IRUGO);
806 +MODULE_PARM_DESC(serial, "USB serial number");
807 +
808 +module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
809 +MODULE_PARM_DESC(ro, "true to force read-only");
810 +
811 +module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
812 +               S_IRUGO);
813 +MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
814 +
815 +module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
816 +MODULE_PARM_DESC(luns, "number of LUNs");
817 +
818 +module_param_named(removable, mod_data.removable, bool, S_IRUGO);
819 +MODULE_PARM_DESC(removable, "true to simulate removable media");
820 +
821 +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
822 +MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
823 +
824 +module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
825 +MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
826 +
827 +/* In the non-TEST version, only the module parameters listed above
828 + * are available. */
829 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
830 +
831 +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
832 +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
833 +
834 +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
835 +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
836 +               "8070, or SCSI)");
837 +
838 +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
839 +MODULE_PARM_DESC(vendor, "USB Vendor ID");
840 +
841 +module_param_named(product, mod_data.product, ushort, S_IRUGO);
842 +MODULE_PARM_DESC(product, "USB Product ID");
843 +
844 +module_param_named(release, mod_data.release, ushort, S_IRUGO);
845 +MODULE_PARM_DESC(release, "USB release number");
846 +
847 +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
848 +MODULE_PARM_DESC(buflen, "I/O buffer size");
849 +
850 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
851 +
852 +
853 +/*
854 + * These definitions will permit the compiler to avoid generating code for
855 + * parts of the driver that aren't used in the non-TEST version.  Even gcc
856 + * can recognize when a test of a constant expression yields a dead code
857 + * path.
858 + */
859 +
860 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
861 +
862 +#define transport_is_bbb()     (mod_data.transport_type == USB_PR_BULK)
863 +#define transport_is_cbi()     (mod_data.transport_type == USB_PR_CBI)
864 +#define protocol_is_scsi()     (mod_data.protocol_type == USB_SC_SCSI)
865 +
866 +#else
867 +
868 +#define transport_is_bbb()     1
869 +#define transport_is_cbi()     0
870 +#define protocol_is_scsi()     1
871 +
872 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
873 +
874 +
875 +/*-------------------------------------------------------------------------*/
876 +
877 +
878 +struct fsg_dev {
879 +       /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
880 +       spinlock_t              lock;
881 +       struct usb_gadget       *gadget;
882 +
883 +       /* filesem protects: backing files in use */
884 +       struct rw_semaphore     filesem;
885 +
886 +       /* reference counting: wait until all LUNs are released */
887 +       struct kref             ref;
888 +
889 +       struct usb_ep           *ep0;           // Handy copy of gadget->ep0
890 +       struct usb_request      *ep0req;        // For control responses
891 +       unsigned int            ep0_req_tag;
892 +       const char              *ep0req_name;
893 +
894 +       struct usb_request      *intreq;        // For interrupt responses
895 +       int                     intreq_busy;
896 +       struct fsg_buffhd       *intr_buffhd;
897 +
898 +       unsigned int            bulk_out_maxpacket;
899 +       enum fsg_state          state;          // For exception handling
900 +       unsigned int            exception_req_tag;
901 +
902 +       u8                      config, new_config;
903 +
904 +       unsigned int            running : 1;
905 +       unsigned int            bulk_in_enabled : 1;
906 +       unsigned int            bulk_out_enabled : 1;
907 +       unsigned int            intr_in_enabled : 1;
908 +       unsigned int            phase_error : 1;
909 +       unsigned int            short_packet_received : 1;
910 +       unsigned int            bad_lun_okay : 1;
911 +
912 +       unsigned long           atomic_bitflags;
913 +#define REGISTERED             0
914 +#define IGNORE_BULK_OUT                1
915 +#define SUSPENDED              2
916 +
917 +       struct usb_ep           *bulk_in;
918 +       struct usb_ep           *bulk_out;
919 +       struct usb_ep           *intr_in;
920 +
921 +       struct fsg_buffhd       *next_buffhd_to_fill;
922 +       struct fsg_buffhd       *next_buffhd_to_drain;
923 +
924 +       int                     thread_wakeup_needed;
925 +       struct completion       thread_notifier;
926 +       struct task_struct      *thread_task;
927 +
928 +       int                     cmnd_size;
929 +       u8                      cmnd[MAX_COMMAND_SIZE];
930 +       enum data_direction     data_dir;
931 +       u32                     data_size;
932 +       u32                     data_size_from_cmnd;
933 +       u32                     tag;
934 +       unsigned int            lun;
935 +       u32                     residue;
936 +       u32                     usb_amount_left;
937 +
938 +       /* The CB protocol offers no way for a host to know when a command
939 +        * has completed.  As a result the next command may arrive early,
940 +        * and we will still have to handle it.  For that reason we need
941 +        * a buffer to store new commands when using CB (or CBI, which
942 +        * does not oblige a host to wait for command completion either). */
943 +       int                     cbbuf_cmnd_size;
944 +       u8                      cbbuf_cmnd[MAX_COMMAND_SIZE];
945 +
946 +       unsigned int            nluns;
947 +       struct fsg_lun          *luns;
948 +       struct fsg_lun          *curlun;
949 +       /* Must be the last entry */
950 +       struct fsg_buffhd       buffhds[];
951 +};
952 +
953 +typedef void (*fsg_routine_t)(struct fsg_dev *);
954 +
955 +static int exception_in_progress(struct fsg_dev *fsg)
956 +{
957 +       return (fsg->state > FSG_STATE_IDLE);
958 +}
959 +
960 +/* Make bulk-out requests be divisible by the maxpacket size */
961 +static void set_bulk_out_req_length(struct fsg_dev *fsg,
962 +               struct fsg_buffhd *bh, unsigned int length)
963 +{
964 +       unsigned int    rem;
965 +
966 +       bh->bulk_out_intended_length = length;
967 +       rem = length % fsg->bulk_out_maxpacket;
968 +       if (rem > 0)
969 +               length += fsg->bulk_out_maxpacket - rem;
970 +       bh->outreq->length = length;
971 +}
972 +
973 +static struct fsg_dev                  *the_fsg;
974 +static struct usb_gadget_driver                fsg_driver;
975 +
976 +
977 +/*-------------------------------------------------------------------------*/
978 +
979 +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
980 +{
981 +       const char      *name;
982 +
983 +       if (ep == fsg->bulk_in)
984 +               name = "bulk-in";
985 +       else if (ep == fsg->bulk_out)
986 +               name = "bulk-out";
987 +       else
988 +               name = ep->name;
989 +       DBG(fsg, "%s set halt\n", name);
990 +       return usb_ep_set_halt(ep);
991 +}
992 +
993 +
994 +/*-------------------------------------------------------------------------*/
995 +
996 +/*
997 + * DESCRIPTORS ... most are static, but strings and (full) configuration
998 + * descriptors are built on demand.  Also the (static) config and interface
999 + * descriptors are adjusted during fsg_bind().
1000 + */
1001 +
1002 +/* There is only one configuration. */
1003 +#define        CONFIG_VALUE            1
1004 +
1005 +static struct usb_device_descriptor
1006 +device_desc = {
1007 +       .bLength =              sizeof device_desc,
1008 +       .bDescriptorType =      USB_DT_DEVICE,
1009 +
1010 +       .bcdUSB =               cpu_to_le16(0x0200),
1011 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
1012 +
1013 +       /* The next three values can be overridden by module parameters */
1014 +       .idVendor =             cpu_to_le16(FSG_VENDOR_ID),
1015 +       .idProduct =            cpu_to_le16(FSG_PRODUCT_ID),
1016 +       .bcdDevice =            cpu_to_le16(0xffff),
1017 +
1018 +       .iManufacturer =        FSG_STRING_MANUFACTURER,
1019 +       .iProduct =             FSG_STRING_PRODUCT,
1020 +       .iSerialNumber =        FSG_STRING_SERIAL,
1021 +       .bNumConfigurations =   1,
1022 +};
1023 +
1024 +static struct usb_config_descriptor
1025 +config_desc = {
1026 +       .bLength =              sizeof config_desc,
1027 +       .bDescriptorType =      USB_DT_CONFIG,
1028 +
1029 +       /* wTotalLength computed by usb_gadget_config_buf() */
1030 +       .bNumInterfaces =       1,
1031 +       .bConfigurationValue =  CONFIG_VALUE,
1032 +       .iConfiguration =       FSG_STRING_CONFIG,
1033 +       .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
1034 +       .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
1035 +};
1036 +
1037 +
1038 +static struct usb_qualifier_descriptor
1039 +dev_qualifier = {
1040 +       .bLength =              sizeof dev_qualifier,
1041 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
1042 +
1043 +       .bcdUSB =               cpu_to_le16(0x0200),
1044 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
1045 +
1046 +       .bNumConfigurations =   1,
1047 +};
1048 +
1049 +static int populate_bos(struct fsg_dev *fsg, u8 *buf)
1050 +{
1051 +       memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
1052 +       buf += USB_DT_BOS_SIZE;
1053 +
1054 +       memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
1055 +       buf += USB_DT_USB_EXT_CAP_SIZE;
1056 +
1057 +       memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
1058 +
1059 +       return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
1060 +               + USB_DT_USB_EXT_CAP_SIZE;
1061 +}
1062 +
1063 +/*
1064 + * Config descriptors must agree with the code that sets configurations
1065 + * and with code managing interfaces and their altsettings.  They must
1066 + * also handle different speeds and other-speed requests.
1067 + */
1068 +static int populate_config_buf(struct usb_gadget *gadget,
1069 +               u8 *buf, u8 type, unsigned index)
1070 +{
1071 +       enum usb_device_speed                   speed = gadget->speed;
1072 +       int                                     len;
1073 +       const struct usb_descriptor_header      **function;
1074 +
1075 +       if (index > 0)
1076 +               return -EINVAL;
1077 +
1078 +       if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
1079 +               speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
1080 +       function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
1081 +               ? (const struct usb_descriptor_header **)fsg_hs_function
1082 +               : (const struct usb_descriptor_header **)fsg_fs_function;
1083 +
1084 +       /* for now, don't advertise srp-only devices */
1085 +       if (!gadget_is_otg(gadget))
1086 +               function++;
1087 +
1088 +       len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
1089 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
1090 +       return len;
1091 +}
1092 +
1093 +
1094 +/*-------------------------------------------------------------------------*/
1095 +
1096 +/* These routines may be called in process context or in_irq */
1097 +
1098 +/* Caller must hold fsg->lock */
1099 +static void wakeup_thread(struct fsg_dev *fsg)
1100 +{
1101 +       /* Tell the main thread that something has happened */
1102 +       fsg->thread_wakeup_needed = 1;
1103 +       if (fsg->thread_task)
1104 +               wake_up_process(fsg->thread_task);
1105 +}
1106 +
1107 +
1108 +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
1109 +{
1110 +       unsigned long           flags;
1111 +
1112 +       /* Do nothing if a higher-priority exception is already in progress.
1113 +        * If a lower-or-equal priority exception is in progress, preempt it
1114 +        * and notify the main thread by sending it a signal. */
1115 +       spin_lock_irqsave(&fsg->lock, flags);
1116 +       if (fsg->state <= new_state) {
1117 +               fsg->exception_req_tag = fsg->ep0_req_tag;
1118 +               fsg->state = new_state;
1119 +               if (fsg->thread_task)
1120 +                       send_sig_info(SIGUSR1, SEND_SIG_FORCED,
1121 +                                       fsg->thread_task);
1122 +       }
1123 +       spin_unlock_irqrestore(&fsg->lock, flags);
1124 +}
1125 +
1126 +
1127 +/*-------------------------------------------------------------------------*/
1128 +
1129 +/* The disconnect callback and ep0 routines.  These always run in_irq,
1130 + * except that ep0_queue() is called in the main thread to acknowledge
1131 + * completion of various requests: set config, set interface, and
1132 + * Bulk-only device reset. */
1133 +
1134 +static void fsg_disconnect(struct usb_gadget *gadget)
1135 +{
1136 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1137 +
1138 +       DBG(fsg, "disconnect or port reset\n");
1139 +       raise_exception(fsg, FSG_STATE_DISCONNECT);
1140 +}
1141 +
1142 +
1143 +static int ep0_queue(struct fsg_dev *fsg)
1144 +{
1145 +       int     rc;
1146 +
1147 +       rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
1148 +       if (rc != 0 && rc != -ESHUTDOWN) {
1149 +
1150 +               /* We can't do much more than wait for a reset */
1151 +               WARNING(fsg, "error in submission: %s --> %d\n",
1152 +                               fsg->ep0->name, rc);
1153 +       }
1154 +       return rc;
1155 +}
1156 +
1157 +static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
1158 +{
1159 +       struct fsg_dev          *fsg = ep->driver_data;
1160 +
1161 +       if (req->actual > 0)
1162 +               dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
1163 +       if (req->status || req->actual != req->length)
1164 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1165 +                               req->status, req->actual, req->length);
1166 +       if (req->status == -ECONNRESET)         // Request was cancelled
1167 +               usb_ep_fifo_flush(ep);
1168 +
1169 +       if (req->status == 0 && req->context)
1170 +               ((fsg_routine_t) (req->context))(fsg);
1171 +}
1172 +
1173 +
1174 +/*-------------------------------------------------------------------------*/
1175 +
1176 +/* Bulk and interrupt endpoint completion handlers.
1177 + * These always run in_irq. */
1178 +
1179 +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
1180 +{
1181 +       struct fsg_dev          *fsg = ep->driver_data;
1182 +       struct fsg_buffhd       *bh = req->context;
1183 +
1184 +       if (req->status || req->actual != req->length)
1185 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1186 +                               req->status, req->actual, req->length);
1187 +       if (req->status == -ECONNRESET)         // Request was cancelled
1188 +               usb_ep_fifo_flush(ep);
1189 +
1190 +       /* Hold the lock while we update the request and buffer states */
1191 +       smp_wmb();
1192 +       spin_lock(&fsg->lock);
1193 +       bh->inreq_busy = 0;
1194 +       bh->state = BUF_STATE_EMPTY;
1195 +       wakeup_thread(fsg);
1196 +       spin_unlock(&fsg->lock);
1197 +}
1198 +
1199 +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
1200 +{
1201 +       struct fsg_dev          *fsg = ep->driver_data;
1202 +       struct fsg_buffhd       *bh = req->context;
1203 +
1204 +       dump_msg(fsg, "bulk-out", req->buf, req->actual);
1205 +       if (req->status || req->actual != bh->bulk_out_intended_length)
1206 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1207 +                               req->status, req->actual,
1208 +                               bh->bulk_out_intended_length);
1209 +       if (req->status == -ECONNRESET)         // Request was cancelled
1210 +               usb_ep_fifo_flush(ep);
1211 +
1212 +       /* Hold the lock while we update the request and buffer states */
1213 +       smp_wmb();
1214 +       spin_lock(&fsg->lock);
1215 +       bh->outreq_busy = 0;
1216 +       bh->state = BUF_STATE_FULL;
1217 +       wakeup_thread(fsg);
1218 +       spin_unlock(&fsg->lock);
1219 +}
1220 +
1221 +
1222 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1223 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1224 +{
1225 +       struct fsg_dev          *fsg = ep->driver_data;
1226 +       struct fsg_buffhd       *bh = req->context;
1227 +
1228 +       if (req->status || req->actual != req->length)
1229 +               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
1230 +                               req->status, req->actual, req->length);
1231 +       if (req->status == -ECONNRESET)         // Request was cancelled
1232 +               usb_ep_fifo_flush(ep);
1233 +
1234 +       /* Hold the lock while we update the request and buffer states */
1235 +       smp_wmb();
1236 +       spin_lock(&fsg->lock);
1237 +       fsg->intreq_busy = 0;
1238 +       bh->state = BUF_STATE_EMPTY;
1239 +       wakeup_thread(fsg);
1240 +       spin_unlock(&fsg->lock);
1241 +}
1242 +
1243 +#else
1244 +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
1245 +{}
1246 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1247 +
1248 +
1249 +/*-------------------------------------------------------------------------*/
1250 +
1251 +/* Ep0 class-specific handlers.  These always run in_irq. */
1252 +
1253 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
1254 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1255 +{
1256 +       struct usb_request      *req = fsg->ep0req;
1257 +       static u8               cbi_reset_cmnd[6] = {
1258 +                       SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
1259 +
1260 +       /* Error in command transfer? */
1261 +       if (req->status || req->length != req->actual ||
1262 +                       req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
1263 +
1264 +               /* Not all controllers allow a protocol stall after
1265 +                * receiving control-out data, but we'll try anyway. */
1266 +               fsg_set_halt(fsg, fsg->ep0);
1267 +               return;                 // Wait for reset
1268 +       }
1269 +
1270 +       /* Is it the special reset command? */
1271 +       if (req->actual >= sizeof cbi_reset_cmnd &&
1272 +                       memcmp(req->buf, cbi_reset_cmnd,
1273 +                               sizeof cbi_reset_cmnd) == 0) {
1274 +
1275 +               /* Raise an exception to stop the current operation
1276 +                * and reinitialize our state. */
1277 +               DBG(fsg, "cbi reset request\n");
1278 +               raise_exception(fsg, FSG_STATE_RESET);
1279 +               return;
1280 +       }
1281 +
1282 +       VDBG(fsg, "CB[I] accept device-specific command\n");
1283 +       spin_lock(&fsg->lock);
1284 +
1285 +       /* Save the command for later */
1286 +       if (fsg->cbbuf_cmnd_size)
1287 +               WARNING(fsg, "CB[I] overwriting previous command\n");
1288 +       fsg->cbbuf_cmnd_size = req->actual;
1289 +       memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
1290 +
1291 +       wakeup_thread(fsg);
1292 +       spin_unlock(&fsg->lock);
1293 +}
1294 +
1295 +#else
1296 +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
1297 +{}
1298 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
1299 +
1300 +
1301 +static int class_setup_req(struct fsg_dev *fsg,
1302 +               const struct usb_ctrlrequest *ctrl)
1303 +{
1304 +       struct usb_request      *req = fsg->ep0req;
1305 +       int                     value = -EOPNOTSUPP;
1306 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1307 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1308 +       u16                     w_length = le16_to_cpu(ctrl->wLength);
1309 +
1310 +       if (!fsg->config)
1311 +               return value;
1312 +
1313 +       /* Handle Bulk-only class-specific requests */
1314 +       if (transport_is_bbb()) {
1315 +               switch (ctrl->bRequest) {
1316 +
1317 +               case US_BULK_RESET_REQUEST:
1318 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1319 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1320 +                               break;
1321 +                       if (w_index != 0 || w_value != 0 || w_length != 0) {
1322 +                               value = -EDOM;
1323 +                               break;
1324 +                       }
1325 +
1326 +                       /* Raise an exception to stop the current operation
1327 +                        * and reinitialize our state. */
1328 +                       DBG(fsg, "bulk reset request\n");
1329 +                       raise_exception(fsg, FSG_STATE_RESET);
1330 +                       value = DELAYED_STATUS;
1331 +                       break;
1332 +
1333 +               case US_BULK_GET_MAX_LUN:
1334 +                       if (ctrl->bRequestType != (USB_DIR_IN |
1335 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1336 +                               break;
1337 +                       if (w_index != 0 || w_value != 0 || w_length != 1) {
1338 +                               value = -EDOM;
1339 +                               break;
1340 +                       }
1341 +                       VDBG(fsg, "get max LUN\n");
1342 +                       *(u8 *) req->buf = fsg->nluns - 1;
1343 +                       value = 1;
1344 +                       break;
1345 +               }
1346 +       }
1347 +
1348 +       /* Handle CBI class-specific requests */
1349 +       else {
1350 +               switch (ctrl->bRequest) {
1351 +
1352 +               case USB_CBI_ADSC_REQUEST:
1353 +                       if (ctrl->bRequestType != (USB_DIR_OUT |
1354 +                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
1355 +                               break;
1356 +                       if (w_index != 0 || w_value != 0) {
1357 +                               value = -EDOM;
1358 +                               break;
1359 +                       }
1360 +                       if (w_length > MAX_COMMAND_SIZE) {
1361 +                               value = -EOVERFLOW;
1362 +                               break;
1363 +                       }
1364 +                       value = w_length;
1365 +                       fsg->ep0req->context = received_cbi_adsc;
1366 +                       break;
1367 +               }
1368 +       }
1369 +
1370 +       if (value == -EOPNOTSUPP)
1371 +               VDBG(fsg,
1372 +                       "unknown class-specific control req "
1373 +                       "%02x.%02x v%04x i%04x l%u\n",
1374 +                       ctrl->bRequestType, ctrl->bRequest,
1375 +                       le16_to_cpu(ctrl->wValue), w_index, w_length);
1376 +       return value;
1377 +}
1378 +
1379 +
1380 +/*-------------------------------------------------------------------------*/
1381 +
1382 +/* Ep0 standard request handlers.  These always run in_irq. */
1383 +
1384 +static int standard_setup_req(struct fsg_dev *fsg,
1385 +               const struct usb_ctrlrequest *ctrl)
1386 +{
1387 +       struct usb_request      *req = fsg->ep0req;
1388 +       int                     value = -EOPNOTSUPP;
1389 +       u16                     w_index = le16_to_cpu(ctrl->wIndex);
1390 +       u16                     w_value = le16_to_cpu(ctrl->wValue);
1391 +
1392 +       /* Usually this just stores reply data in the pre-allocated ep0 buffer,
1393 +        * but config change events will also reconfigure hardware. */
1394 +       switch (ctrl->bRequest) {
1395 +
1396 +       case USB_REQ_GET_DESCRIPTOR:
1397 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1398 +                               USB_RECIP_DEVICE))
1399 +                       break;
1400 +               switch (w_value >> 8) {
1401 +
1402 +               case USB_DT_DEVICE:
1403 +                       VDBG(fsg, "get device descriptor\n");
1404 +                       device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
1405 +                       value = sizeof device_desc;
1406 +                       memcpy(req->buf, &device_desc, value);
1407 +                       break;
1408 +               case USB_DT_DEVICE_QUALIFIER:
1409 +                       VDBG(fsg, "get device qualifier\n");
1410 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1411 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1412 +                               break;
1413 +                       /*
1414 +                        * Assume ep0 uses the same maxpacket value for both
1415 +                        * speeds
1416 +                        */
1417 +                       dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
1418 +                       value = sizeof dev_qualifier;
1419 +                       memcpy(req->buf, &dev_qualifier, value);
1420 +                       break;
1421 +
1422 +               case USB_DT_OTHER_SPEED_CONFIG:
1423 +                       VDBG(fsg, "get other-speed config descriptor\n");
1424 +                       if (!gadget_is_dualspeed(fsg->gadget) ||
1425 +                                       fsg->gadget->speed == USB_SPEED_SUPER)
1426 +                               break;
1427 +                       goto get_config;
1428 +               case USB_DT_CONFIG:
1429 +                       VDBG(fsg, "get configuration descriptor\n");
1430 +get_config:
1431 +                       value = populate_config_buf(fsg->gadget,
1432 +                                       req->buf,
1433 +                                       w_value >> 8,
1434 +                                       w_value & 0xff);
1435 +                       break;
1436 +
1437 +               case USB_DT_STRING:
1438 +                       VDBG(fsg, "get string descriptor\n");
1439 +
1440 +                       /* wIndex == language code */
1441 +                       value = usb_gadget_get_string(&fsg_stringtab,
1442 +                                       w_value & 0xff, req->buf);
1443 +                       break;
1444 +
1445 +               case USB_DT_BOS:
1446 +                       VDBG(fsg, "get bos descriptor\n");
1447 +
1448 +                       if (gadget_is_superspeed(fsg->gadget))
1449 +                               value = populate_bos(fsg, req->buf);
1450 +                       break;
1451 +               }
1452 +
1453 +               break;
1454 +
1455 +       /* One config, two speeds */
1456 +       case USB_REQ_SET_CONFIGURATION:
1457 +               if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
1458 +                               USB_RECIP_DEVICE))
1459 +                       break;
1460 +               VDBG(fsg, "set configuration\n");
1461 +               if (w_value == CONFIG_VALUE || w_value == 0) {
1462 +                       fsg->new_config = w_value;
1463 +
1464 +                       /* Raise an exception to wipe out previous transaction
1465 +                        * state (queued bufs, etc) and set the new config. */
1466 +                       raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
1467 +                       value = DELAYED_STATUS;
1468 +               }
1469 +               break;
1470 +       case USB_REQ_GET_CONFIGURATION:
1471 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1472 +                               USB_RECIP_DEVICE))
1473 +                       break;
1474 +               VDBG(fsg, "get configuration\n");
1475 +               *(u8 *) req->buf = fsg->config;
1476 +               value = 1;
1477 +               break;
1478 +
1479 +       case USB_REQ_SET_INTERFACE:
1480 +               if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
1481 +                               USB_RECIP_INTERFACE))
1482 +                       break;
1483 +               if (fsg->config && w_index == 0) {
1484 +
1485 +                       /* Raise an exception to wipe out previous transaction
1486 +                        * state (queued bufs, etc) and install the new
1487 +                        * interface altsetting. */
1488 +                       raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
1489 +                       value = DELAYED_STATUS;
1490 +               }
1491 +               break;
1492 +       case USB_REQ_GET_INTERFACE:
1493 +               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
1494 +                               USB_RECIP_INTERFACE))
1495 +                       break;
1496 +               if (!fsg->config)
1497 +                       break;
1498 +               if (w_index != 0) {
1499 +                       value = -EDOM;
1500 +                       break;
1501 +               }
1502 +               VDBG(fsg, "get interface\n");
1503 +               *(u8 *) req->buf = 0;
1504 +               value = 1;
1505 +               break;
1506 +
1507 +       default:
1508 +               VDBG(fsg,
1509 +                       "unknown control req %02x.%02x v%04x i%04x l%u\n",
1510 +                       ctrl->bRequestType, ctrl->bRequest,
1511 +                       w_value, w_index, le16_to_cpu(ctrl->wLength));
1512 +       }
1513 +
1514 +       return value;
1515 +}
1516 +
1517 +
1518 +static int fsg_setup(struct usb_gadget *gadget,
1519 +               const struct usb_ctrlrequest *ctrl)
1520 +{
1521 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
1522 +       int                     rc;
1523 +       int                     w_length = le16_to_cpu(ctrl->wLength);
1524 +
1525 +       ++fsg->ep0_req_tag;             // Record arrival of a new request
1526 +       fsg->ep0req->context = NULL;
1527 +       fsg->ep0req->length = 0;
1528 +       dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
1529 +
1530 +       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
1531 +               rc = class_setup_req(fsg, ctrl);
1532 +       else
1533 +               rc = standard_setup_req(fsg, ctrl);
1534 +
1535 +       /* Respond with data/status or defer until later? */
1536 +       if (rc >= 0 && rc != DELAYED_STATUS) {
1537 +               rc = min(rc, w_length);
1538 +               fsg->ep0req->length = rc;
1539 +               fsg->ep0req->zero = rc < w_length;
1540 +               fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
1541 +                               "ep0-in" : "ep0-out");
1542 +               rc = ep0_queue(fsg);
1543 +       }
1544 +
1545 +       /* Device either stalls (rc < 0) or reports success */
1546 +       return rc;
1547 +}
1548 +
1549 +
1550 +/*-------------------------------------------------------------------------*/
1551 +
1552 +/* All the following routines run in process context */
1553 +
1554 +
1555 +/* Use this for bulk or interrupt transfers, not ep0 */
1556 +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
1557 +               struct usb_request *req, int *pbusy,
1558 +               enum fsg_buffer_state *state)
1559 +{
1560 +       int     rc;
1561 +
1562 +       if (ep == fsg->bulk_in)
1563 +               dump_msg(fsg, "bulk-in", req->buf, req->length);
1564 +       else if (ep == fsg->intr_in)
1565 +               dump_msg(fsg, "intr-in", req->buf, req->length);
1566 +
1567 +       spin_lock_irq(&fsg->lock);
1568 +       *pbusy = 1;
1569 +       *state = BUF_STATE_BUSY;
1570 +       spin_unlock_irq(&fsg->lock);
1571 +       rc = usb_ep_queue(ep, req, GFP_KERNEL);
1572 +       if (rc != 0) {
1573 +               *pbusy = 0;
1574 +               *state = BUF_STATE_EMPTY;
1575 +
1576 +               /* We can't do much more than wait for a reset */
1577 +
1578 +               /* Note: currently the net2280 driver fails zero-length
1579 +                * submissions if DMA is enabled. */
1580 +               if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
1581 +                                               req->length == 0))
1582 +                       WARNING(fsg, "error in submission: %s --> %d\n",
1583 +                                       ep->name, rc);
1584 +       }
1585 +}
1586 +
1587 +
1588 +static int sleep_thread(struct fsg_dev *fsg)
1589 +{
1590 +       int     rc = 0;
1591 +
1592 +       /* Wait until a signal arrives or we are woken up */
1593 +       for (;;) {
1594 +               try_to_freeze();
1595 +               set_current_state(TASK_INTERRUPTIBLE);
1596 +               if (signal_pending(current)) {
1597 +                       rc = -EINTR;
1598 +                       break;
1599 +               }
1600 +               if (fsg->thread_wakeup_needed)
1601 +                       break;
1602 +               schedule();
1603 +       }
1604 +       __set_current_state(TASK_RUNNING);
1605 +       fsg->thread_wakeup_needed = 0;
1606 +       return rc;
1607 +}
1608 +
1609 +
1610 +/*-------------------------------------------------------------------------*/
1611 +
1612 +static int do_read(struct fsg_dev *fsg)
1613 +{
1614 +       struct fsg_lun          *curlun = fsg->curlun;
1615 +       u32                     lba;
1616 +       struct fsg_buffhd       *bh;
1617 +       int                     rc;
1618 +       u32                     amount_left;
1619 +       loff_t                  file_offset, file_offset_tmp;
1620 +       unsigned int            amount;
1621 +       ssize_t                 nread;
1622 +
1623 +       /* Get the starting Logical Block Address and check that it's
1624 +        * not too big */
1625 +       if (fsg->cmnd[0] == READ_6)
1626 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1627 +       else {
1628 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1629 +
1630 +               /* We allow DPO (Disable Page Out = don't save data in the
1631 +                * cache) and FUA (Force Unit Access = don't read from the
1632 +                * cache), but we don't implement them. */
1633 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1634 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1635 +                       return -EINVAL;
1636 +               }
1637 +       }
1638 +       if (lba >= curlun->num_sectors) {
1639 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1640 +               return -EINVAL;
1641 +       }
1642 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1643 +
1644 +       /* Carry out the file reads */
1645 +       amount_left = fsg->data_size_from_cmnd;
1646 +       if (unlikely(amount_left == 0))
1647 +               return -EIO;            // No default reply
1648 +
1649 +       for (;;) {
1650 +
1651 +               /* Figure out how much we need to read:
1652 +                * Try to read the remaining amount.
1653 +                * But don't read more than the buffer size.
1654 +                * And don't try to read past the end of the file.
1655 +                */
1656 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1657 +               amount = min((loff_t) amount,
1658 +                               curlun->file_length - file_offset);
1659 +
1660 +               /* Wait for the next buffer to become available */
1661 +               bh = fsg->next_buffhd_to_fill;
1662 +               while (bh->state != BUF_STATE_EMPTY) {
1663 +                       rc = sleep_thread(fsg);
1664 +                       if (rc)
1665 +                               return rc;
1666 +               }
1667 +
1668 +               /* If we were asked to read past the end of file,
1669 +                * end with an empty buffer. */
1670 +               if (amount == 0) {
1671 +                       curlun->sense_data =
1672 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1673 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1674 +                       curlun->info_valid = 1;
1675 +                       bh->inreq->length = 0;
1676 +                       bh->state = BUF_STATE_FULL;
1677 +                       break;
1678 +               }
1679 +
1680 +               /* Perform the read */
1681 +               file_offset_tmp = file_offset;
1682 +               nread = vfs_read(curlun->filp,
1683 +                               (char __user *) bh->buf,
1684 +                               amount, &file_offset_tmp);
1685 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
1686 +                               (unsigned long long) file_offset,
1687 +                               (int) nread);
1688 +               if (signal_pending(current))
1689 +                       return -EINTR;
1690 +
1691 +               if (nread < 0) {
1692 +                       LDBG(curlun, "error in file read: %d\n",
1693 +                                       (int) nread);
1694 +                       nread = 0;
1695 +               } else if (nread < amount) {
1696 +                       LDBG(curlun, "partial file read: %d/%u\n",
1697 +                                       (int) nread, amount);
1698 +                       nread = round_down(nread, curlun->blksize);
1699 +               }
1700 +               file_offset  += nread;
1701 +               amount_left  -= nread;
1702 +               fsg->residue -= nread;
1703 +
1704 +               /* Except at the end of the transfer, nread will be
1705 +                * equal to the buffer size, which is divisible by the
1706 +                * bulk-in maxpacket size.
1707 +                */
1708 +               bh->inreq->length = nread;
1709 +               bh->state = BUF_STATE_FULL;
1710 +
1711 +               /* If an error occurred, report it and its position */
1712 +               if (nread < amount) {
1713 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
1714 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
1715 +                       curlun->info_valid = 1;
1716 +                       break;
1717 +               }
1718 +
1719 +               if (amount_left == 0)
1720 +                       break;          // No more left to read
1721 +
1722 +               /* Send this buffer and go read some more */
1723 +               bh->inreq->zero = 0;
1724 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
1725 +                               &bh->inreq_busy, &bh->state);
1726 +               fsg->next_buffhd_to_fill = bh->next;
1727 +       }
1728 +
1729 +       return -EIO;            // No default reply
1730 +}
1731 +
1732 +
1733 +/*-------------------------------------------------------------------------*/
1734 +
1735 +static int do_write(struct fsg_dev *fsg)
1736 +{
1737 +       struct fsg_lun          *curlun = fsg->curlun;
1738 +       u32                     lba;
1739 +       struct fsg_buffhd       *bh;
1740 +       int                     get_some_more;
1741 +       u32                     amount_left_to_req, amount_left_to_write;
1742 +       loff_t                  usb_offset, file_offset, file_offset_tmp;
1743 +       unsigned int            amount;
1744 +       ssize_t                 nwritten;
1745 +       int                     rc;
1746 +
1747 +       if (curlun->ro) {
1748 +               curlun->sense_data = SS_WRITE_PROTECTED;
1749 +               return -EINVAL;
1750 +       }
1751 +       spin_lock(&curlun->filp->f_lock);
1752 +       curlun->filp->f_flags &= ~O_SYNC;       // Default is not to wait
1753 +       spin_unlock(&curlun->filp->f_lock);
1754 +
1755 +       /* Get the starting Logical Block Address and check that it's
1756 +        * not too big */
1757 +       if (fsg->cmnd[0] == WRITE_6)
1758 +               lba = get_unaligned_be24(&fsg->cmnd[1]);
1759 +       else {
1760 +               lba = get_unaligned_be32(&fsg->cmnd[2]);
1761 +
1762 +               /* We allow DPO (Disable Page Out = don't save data in the
1763 +                * cache) and FUA (Force Unit Access = write directly to the
1764 +                * medium).  We don't implement DPO; we implement FUA by
1765 +                * performing synchronous output. */
1766 +               if ((fsg->cmnd[1] & ~0x18) != 0) {
1767 +                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1768 +                       return -EINVAL;
1769 +               }
1770 +               /* FUA */
1771 +               if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
1772 +                       spin_lock(&curlun->filp->f_lock);
1773 +                       curlun->filp->f_flags |= O_DSYNC;
1774 +                       spin_unlock(&curlun->filp->f_lock);
1775 +               }
1776 +       }
1777 +       if (lba >= curlun->num_sectors) {
1778 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1779 +               return -EINVAL;
1780 +       }
1781 +
1782 +       /* Carry out the file writes */
1783 +       get_some_more = 1;
1784 +       file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
1785 +       amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
1786 +
1787 +       while (amount_left_to_write > 0) {
1788 +
1789 +               /* Queue a request for more data from the host */
1790 +               bh = fsg->next_buffhd_to_fill;
1791 +               if (bh->state == BUF_STATE_EMPTY && get_some_more) {
1792 +
1793 +                       /* Figure out how much we want to get:
1794 +                        * Try to get the remaining amount,
1795 +                        * but not more than the buffer size.
1796 +                        */
1797 +                       amount = min(amount_left_to_req, mod_data.buflen);
1798 +
1799 +                       /* Beyond the end of the backing file? */
1800 +                       if (usb_offset >= curlun->file_length) {
1801 +                               get_some_more = 0;
1802 +                               curlun->sense_data =
1803 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1804 +                               curlun->sense_data_info = usb_offset >> curlun->blkbits;
1805 +                               curlun->info_valid = 1;
1806 +                               continue;
1807 +                       }
1808 +
1809 +                       /* Get the next buffer */
1810 +                       usb_offset += amount;
1811 +                       fsg->usb_amount_left -= amount;
1812 +                       amount_left_to_req -= amount;
1813 +                       if (amount_left_to_req == 0)
1814 +                               get_some_more = 0;
1815 +
1816 +                       /* Except at the end of the transfer, amount will be
1817 +                        * equal to the buffer size, which is divisible by
1818 +                        * the bulk-out maxpacket size.
1819 +                        */
1820 +                       set_bulk_out_req_length(fsg, bh, amount);
1821 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
1822 +                                       &bh->outreq_busy, &bh->state);
1823 +                       fsg->next_buffhd_to_fill = bh->next;
1824 +                       continue;
1825 +               }
1826 +
1827 +               /* Write the received data to the backing file */
1828 +               bh = fsg->next_buffhd_to_drain;
1829 +               if (bh->state == BUF_STATE_EMPTY && !get_some_more)
1830 +                       break;                  // We stopped early
1831 +               if (bh->state == BUF_STATE_FULL) {
1832 +                       smp_rmb();
1833 +                       fsg->next_buffhd_to_drain = bh->next;
1834 +                       bh->state = BUF_STATE_EMPTY;
1835 +
1836 +                       /* Did something go wrong with the transfer? */
1837 +                       if (bh->outreq->status != 0) {
1838 +                               curlun->sense_data = SS_COMMUNICATION_FAILURE;
1839 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1840 +                               curlun->info_valid = 1;
1841 +                               break;
1842 +                       }
1843 +
1844 +                       amount = bh->outreq->actual;
1845 +                       if (curlun->file_length - file_offset < amount) {
1846 +                               LERROR(curlun,
1847 +       "write %u @ %llu beyond end %llu\n",
1848 +       amount, (unsigned long long) file_offset,
1849 +       (unsigned long long) curlun->file_length);
1850 +                               amount = curlun->file_length - file_offset;
1851 +                       }
1852 +
1853 +                       /* Don't accept excess data.  The spec doesn't say
1854 +                        * what to do in this case.  We'll ignore the error.
1855 +                        */
1856 +                       amount = min(amount, bh->bulk_out_intended_length);
1857 +
1858 +                       /* Don't write a partial block */
1859 +                       amount = round_down(amount, curlun->blksize);
1860 +                       if (amount == 0)
1861 +                               goto empty_write;
1862 +
1863 +                       /* Perform the write */
1864 +                       file_offset_tmp = file_offset;
1865 +                       nwritten = vfs_write(curlun->filp,
1866 +                                       (char __user *) bh->buf,
1867 +                                       amount, &file_offset_tmp);
1868 +                       VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
1869 +                                       (unsigned long long) file_offset,
1870 +                                       (int) nwritten);
1871 +                       if (signal_pending(current))
1872 +                               return -EINTR;          // Interrupted!
1873 +
1874 +                       if (nwritten < 0) {
1875 +                               LDBG(curlun, "error in file write: %d\n",
1876 +                                               (int) nwritten);
1877 +                               nwritten = 0;
1878 +                       } else if (nwritten < amount) {
1879 +                               LDBG(curlun, "partial file write: %d/%u\n",
1880 +                                               (int) nwritten, amount);
1881 +                               nwritten = round_down(nwritten, curlun->blksize);
1882 +                       }
1883 +                       file_offset += nwritten;
1884 +                       amount_left_to_write -= nwritten;
1885 +                       fsg->residue -= nwritten;
1886 +
1887 +                       /* If an error occurred, report it and its position */
1888 +                       if (nwritten < amount) {
1889 +                               curlun->sense_data = SS_WRITE_ERROR;
1890 +                               curlun->sense_data_info = file_offset >> curlun->blkbits;
1891 +                               curlun->info_valid = 1;
1892 +                               break;
1893 +                       }
1894 +
1895 + empty_write:
1896 +                       /* Did the host decide to stop early? */
1897 +                       if (bh->outreq->actual < bh->bulk_out_intended_length) {
1898 +                               fsg->short_packet_received = 1;
1899 +                               break;
1900 +                       }
1901 +                       continue;
1902 +               }
1903 +
1904 +               /* Wait for something to happen */
1905 +               rc = sleep_thread(fsg);
1906 +               if (rc)
1907 +                       return rc;
1908 +       }
1909 +
1910 +       return -EIO;            // No default reply
1911 +}
1912 +
1913 +
1914 +/*-------------------------------------------------------------------------*/
1915 +
1916 +static int do_synchronize_cache(struct fsg_dev *fsg)
1917 +{
1918 +       struct fsg_lun  *curlun = fsg->curlun;
1919 +       int             rc;
1920 +
1921 +       /* We ignore the requested LBA and write out all file's
1922 +        * dirty data buffers. */
1923 +       rc = fsg_lun_fsync_sub(curlun);
1924 +       if (rc)
1925 +               curlun->sense_data = SS_WRITE_ERROR;
1926 +       return 0;
1927 +}
1928 +
1929 +
1930 +/*-------------------------------------------------------------------------*/
1931 +
1932 +static void invalidate_sub(struct fsg_lun *curlun)
1933 +{
1934 +       struct file     *filp = curlun->filp;
1935 +       struct inode    *inode = filp->f_path.dentry->d_inode;
1936 +       unsigned long   rc;
1937 +
1938 +       rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
1939 +       VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
1940 +}
1941 +
1942 +static int do_verify(struct fsg_dev *fsg)
1943 +{
1944 +       struct fsg_lun          *curlun = fsg->curlun;
1945 +       u32                     lba;
1946 +       u32                     verification_length;
1947 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
1948 +       loff_t                  file_offset, file_offset_tmp;
1949 +       u32                     amount_left;
1950 +       unsigned int            amount;
1951 +       ssize_t                 nread;
1952 +
1953 +       /* Get the starting Logical Block Address and check that it's
1954 +        * not too big */
1955 +       lba = get_unaligned_be32(&fsg->cmnd[2]);
1956 +       if (lba >= curlun->num_sectors) {
1957 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1958 +               return -EINVAL;
1959 +       }
1960 +
1961 +       /* We allow DPO (Disable Page Out = don't save data in the
1962 +        * cache) but we don't implement it. */
1963 +       if ((fsg->cmnd[1] & ~0x10) != 0) {
1964 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1965 +               return -EINVAL;
1966 +       }
1967 +
1968 +       verification_length = get_unaligned_be16(&fsg->cmnd[7]);
1969 +       if (unlikely(verification_length == 0))
1970 +               return -EIO;            // No default reply
1971 +
1972 +       /* Prepare to carry out the file verify */
1973 +       amount_left = verification_length << curlun->blkbits;
1974 +       file_offset = ((loff_t) lba) << curlun->blkbits;
1975 +
1976 +       /* Write out all the dirty buffers before invalidating them */
1977 +       fsg_lun_fsync_sub(curlun);
1978 +       if (signal_pending(current))
1979 +               return -EINTR;
1980 +
1981 +       invalidate_sub(curlun);
1982 +       if (signal_pending(current))
1983 +               return -EINTR;
1984 +
1985 +       /* Just try to read the requested blocks */
1986 +       while (amount_left > 0) {
1987 +
1988 +               /* Figure out how much we need to read:
1989 +                * Try to read the remaining amount, but not more than
1990 +                * the buffer size.
1991 +                * And don't try to read past the end of the file.
1992 +                */
1993 +               amount = min((unsigned int) amount_left, mod_data.buflen);
1994 +               amount = min((loff_t) amount,
1995 +                               curlun->file_length - file_offset);
1996 +               if (amount == 0) {
1997 +                       curlun->sense_data =
1998 +                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1999 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
2000 +                       curlun->info_valid = 1;
2001 +                       break;
2002 +               }
2003 +
2004 +               /* Perform the read */
2005 +               file_offset_tmp = file_offset;
2006 +               nread = vfs_read(curlun->filp,
2007 +                               (char __user *) bh->buf,
2008 +                               amount, &file_offset_tmp);
2009 +               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
2010 +                               (unsigned long long) file_offset,
2011 +                               (int) nread);
2012 +               if (signal_pending(current))
2013 +                       return -EINTR;
2014 +
2015 +               if (nread < 0) {
2016 +                       LDBG(curlun, "error in file verify: %d\n",
2017 +                                       (int) nread);
2018 +                       nread = 0;
2019 +               } else if (nread < amount) {
2020 +                       LDBG(curlun, "partial file verify: %d/%u\n",
2021 +                                       (int) nread, amount);
2022 +                       nread = round_down(nread, curlun->blksize);
2023 +               }
2024 +               if (nread == 0) {
2025 +                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
2026 +                       curlun->sense_data_info = file_offset >> curlun->blkbits;
2027 +                       curlun->info_valid = 1;
2028 +                       break;
2029 +               }
2030 +               file_offset += nread;
2031 +               amount_left -= nread;
2032 +       }
2033 +       return 0;
2034 +}
2035 +
2036 +
2037 +/*-------------------------------------------------------------------------*/
2038 +
2039 +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2040 +{
2041 +       u8      *buf = (u8 *) bh->buf;
2042 +
2043 +       static char vendor_id[] = "Linux   ";
2044 +       static char product_disk_id[] = "File-Stor Gadget";
2045 +       static char product_cdrom_id[] = "File-CD Gadget  ";
2046 +
2047 +       if (!fsg->curlun) {             // Unsupported LUNs are okay
2048 +               fsg->bad_lun_okay = 1;
2049 +               memset(buf, 0, 36);
2050 +               buf[0] = 0x7f;          // Unsupported, no device-type
2051 +               buf[4] = 31;            // Additional length
2052 +               return 36;
2053 +       }
2054 +
2055 +       memset(buf, 0, 8);
2056 +       buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
2057 +       if (mod_data.removable)
2058 +               buf[1] = 0x80;
2059 +       buf[2] = 2;             // ANSI SCSI level 2
2060 +       buf[3] = 2;             // SCSI-2 INQUIRY data format
2061 +       buf[4] = 31;            // Additional length
2062 +                               // No special options
2063 +       sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
2064 +                       (mod_data.cdrom ? product_cdrom_id :
2065 +                               product_disk_id),
2066 +                       mod_data.release);
2067 +       return 36;
2068 +}
2069 +
2070 +
2071 +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2072 +{
2073 +       struct fsg_lun  *curlun = fsg->curlun;
2074 +       u8              *buf = (u8 *) bh->buf;
2075 +       u32             sd, sdinfo;
2076 +       int             valid;
2077 +
2078 +       /*
2079 +        * From the SCSI-2 spec., section 7.9 (Unit attention condition):
2080 +        *
2081 +        * If a REQUEST SENSE command is received from an initiator
2082 +        * with a pending unit attention condition (before the target
2083 +        * generates the contingent allegiance condition), then the
2084 +        * target shall either:
2085 +        *   a) report any pending sense data and preserve the unit
2086 +        *      attention condition on the logical unit, or,
2087 +        *   b) report the unit attention condition, may discard any
2088 +        *      pending sense data, and clear the unit attention
2089 +        *      condition on the logical unit for that initiator.
2090 +        *
2091 +        * FSG normally uses option a); enable this code to use option b).
2092 +        */
2093 +#if 0
2094 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
2095 +               curlun->sense_data = curlun->unit_attention_data;
2096 +               curlun->unit_attention_data = SS_NO_SENSE;
2097 +       }
2098 +#endif
2099 +
2100 +       if (!curlun) {          // Unsupported LUNs are okay
2101 +               fsg->bad_lun_okay = 1;
2102 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2103 +               sdinfo = 0;
2104 +               valid = 0;
2105 +       } else {
2106 +               sd = curlun->sense_data;
2107 +               sdinfo = curlun->sense_data_info;
2108 +               valid = curlun->info_valid << 7;
2109 +               curlun->sense_data = SS_NO_SENSE;
2110 +               curlun->sense_data_info = 0;
2111 +               curlun->info_valid = 0;
2112 +       }
2113 +
2114 +       memset(buf, 0, 18);
2115 +       buf[0] = valid | 0x70;                  // Valid, current error
2116 +       buf[2] = SK(sd);
2117 +       put_unaligned_be32(sdinfo, &buf[3]);    /* Sense information */
2118 +       buf[7] = 18 - 8;                        // Additional sense length
2119 +       buf[12] = ASC(sd);
2120 +       buf[13] = ASCQ(sd);
2121 +       return 18;
2122 +}
2123 +
2124 +
2125 +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2126 +{
2127 +       struct fsg_lun  *curlun = fsg->curlun;
2128 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2129 +       int             pmi = fsg->cmnd[8];
2130 +       u8              *buf = (u8 *) bh->buf;
2131 +
2132 +       /* Check the PMI and LBA fields */
2133 +       if (pmi > 1 || (pmi == 0 && lba != 0)) {
2134 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2135 +               return -EINVAL;
2136 +       }
2137 +
2138 +       put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
2139 +                                               /* Max logical block */
2140 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2141 +       return 8;
2142 +}
2143 +
2144 +
2145 +static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2146 +{
2147 +       struct fsg_lun  *curlun = fsg->curlun;
2148 +       int             msf = fsg->cmnd[1] & 0x02;
2149 +       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
2150 +       u8              *buf = (u8 *) bh->buf;
2151 +
2152 +       if ((fsg->cmnd[1] & ~0x02) != 0) {              /* Mask away MSF */
2153 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2154 +               return -EINVAL;
2155 +       }
2156 +       if (lba >= curlun->num_sectors) {
2157 +               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
2158 +               return -EINVAL;
2159 +       }
2160 +
2161 +       memset(buf, 0, 8);
2162 +       buf[0] = 0x01;          /* 2048 bytes of user data, rest is EC */
2163 +       store_cdrom_address(&buf[4], msf, lba);
2164 +       return 8;
2165 +}
2166 +
2167 +
2168 +static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2169 +{
2170 +       struct fsg_lun  *curlun = fsg->curlun;
2171 +       int             msf = fsg->cmnd[1] & 0x02;
2172 +       int             start_track = fsg->cmnd[6];
2173 +       u8              *buf = (u8 *) bh->buf;
2174 +
2175 +       if ((fsg->cmnd[1] & ~0x02) != 0 ||              /* Mask away MSF */
2176 +                       start_track > 1) {
2177 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2178 +               return -EINVAL;
2179 +       }
2180 +
2181 +       memset(buf, 0, 20);
2182 +       buf[1] = (20-2);                /* TOC data length */
2183 +       buf[2] = 1;                     /* First track number */
2184 +       buf[3] = 1;                     /* Last track number */
2185 +       buf[5] = 0x16;                  /* Data track, copying allowed */
2186 +       buf[6] = 0x01;                  /* Only track is number 1 */
2187 +       store_cdrom_address(&buf[8], msf, 0);
2188 +
2189 +       buf[13] = 0x16;                 /* Lead-out track is data */
2190 +       buf[14] = 0xAA;                 /* Lead-out track number */
2191 +       store_cdrom_address(&buf[16], msf, curlun->num_sectors);
2192 +       return 20;
2193 +}
2194 +
2195 +
2196 +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2197 +{
2198 +       struct fsg_lun  *curlun = fsg->curlun;
2199 +       int             mscmnd = fsg->cmnd[0];
2200 +       u8              *buf = (u8 *) bh->buf;
2201 +       u8              *buf0 = buf;
2202 +       int             pc, page_code;
2203 +       int             changeable_values, all_pages;
2204 +       int             valid_page = 0;
2205 +       int             len, limit;
2206 +
2207 +       if ((fsg->cmnd[1] & ~0x08) != 0) {              // Mask away DBD
2208 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2209 +               return -EINVAL;
2210 +       }
2211 +       pc = fsg->cmnd[2] >> 6;
2212 +       page_code = fsg->cmnd[2] & 0x3f;
2213 +       if (pc == 3) {
2214 +               curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
2215 +               return -EINVAL;
2216 +       }
2217 +       changeable_values = (pc == 1);
2218 +       all_pages = (page_code == 0x3f);
2219 +
2220 +       /* Write the mode parameter header.  Fixed values are: default
2221 +        * medium type, no cache control (DPOFUA), and no block descriptors.
2222 +        * The only variable value is the WriteProtect bit.  We will fill in
2223 +        * the mode data length later. */
2224 +       memset(buf, 0, 8);
2225 +       if (mscmnd == MODE_SENSE) {
2226 +               buf[2] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2227 +               buf += 4;
2228 +               limit = 255;
2229 +       } else {                        // MODE_SENSE_10
2230 +               buf[3] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
2231 +               buf += 8;
2232 +               limit = 65535;          // Should really be mod_data.buflen
2233 +       }
2234 +
2235 +       /* No block descriptors */
2236 +
2237 +       /* The mode pages, in numerical order.  The only page we support
2238 +        * is the Caching page. */
2239 +       if (page_code == 0x08 || all_pages) {
2240 +               valid_page = 1;
2241 +               buf[0] = 0x08;          // Page code
2242 +               buf[1] = 10;            // Page length
2243 +               memset(buf+2, 0, 10);   // None of the fields are changeable
2244 +
2245 +               if (!changeable_values) {
2246 +                       buf[2] = 0x04;  // Write cache enable,
2247 +                                       // Read cache not disabled
2248 +                                       // No cache retention priorities
2249 +                       put_unaligned_be16(0xffff, &buf[4]);
2250 +                                       /* Don't disable prefetch */
2251 +                                       /* Minimum prefetch = 0 */
2252 +                       put_unaligned_be16(0xffff, &buf[8]);
2253 +                                       /* Maximum prefetch */
2254 +                       put_unaligned_be16(0xffff, &buf[10]);
2255 +                                       /* Maximum prefetch ceiling */
2256 +               }
2257 +               buf += 12;
2258 +       }
2259 +
2260 +       /* Check that a valid page was requested and the mode data length
2261 +        * isn't too long. */
2262 +       len = buf - buf0;
2263 +       if (!valid_page || len > limit) {
2264 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2265 +               return -EINVAL;
2266 +       }
2267 +
2268 +       /*  Store the mode data length */
2269 +       if (mscmnd == MODE_SENSE)
2270 +               buf0[0] = len - 1;
2271 +       else
2272 +               put_unaligned_be16(len - 2, buf0);
2273 +       return len;
2274 +}
2275 +
2276 +
2277 +static int do_start_stop(struct fsg_dev *fsg)
2278 +{
2279 +       struct fsg_lun  *curlun = fsg->curlun;
2280 +       int             loej, start;
2281 +
2282 +       if (!mod_data.removable) {
2283 +               curlun->sense_data = SS_INVALID_COMMAND;
2284 +               return -EINVAL;
2285 +       }
2286 +
2287 +       // int immed = fsg->cmnd[1] & 0x01;
2288 +       loej = fsg->cmnd[4] & 0x02;
2289 +       start = fsg->cmnd[4] & 0x01;
2290 +
2291 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
2292 +       if ((fsg->cmnd[1] & ~0x01) != 0 ||              // Mask away Immed
2293 +                       (fsg->cmnd[4] & ~0x03) != 0) {  // Mask LoEj, Start
2294 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2295 +               return -EINVAL;
2296 +       }
2297 +
2298 +       if (!start) {
2299 +
2300 +               /* Are we allowed to unload the media? */
2301 +               if (curlun->prevent_medium_removal) {
2302 +                       LDBG(curlun, "unload attempt prevented\n");
2303 +                       curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
2304 +                       return -EINVAL;
2305 +               }
2306 +               if (loej) {             // Simulate an unload/eject
2307 +                       up_read(&fsg->filesem);
2308 +                       down_write(&fsg->filesem);
2309 +                       fsg_lun_close(curlun);
2310 +                       up_write(&fsg->filesem);
2311 +                       down_read(&fsg->filesem);
2312 +               }
2313 +       } else {
2314 +
2315 +               /* Our emulation doesn't support mounting; the medium is
2316 +                * available for use as soon as it is loaded. */
2317 +               if (!fsg_lun_is_open(curlun)) {
2318 +                       curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2319 +                       return -EINVAL;
2320 +               }
2321 +       }
2322 +#endif
2323 +       return 0;
2324 +}
2325 +
2326 +
2327 +static int do_prevent_allow(struct fsg_dev *fsg)
2328 +{
2329 +       struct fsg_lun  *curlun = fsg->curlun;
2330 +       int             prevent;
2331 +
2332 +       if (!mod_data.removable) {
2333 +               curlun->sense_data = SS_INVALID_COMMAND;
2334 +               return -EINVAL;
2335 +       }
2336 +
2337 +       prevent = fsg->cmnd[4] & 0x01;
2338 +       if ((fsg->cmnd[4] & ~0x01) != 0) {              // Mask away Prevent
2339 +               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2340 +               return -EINVAL;
2341 +       }
2342 +
2343 +       if (curlun->prevent_medium_removal && !prevent)
2344 +               fsg_lun_fsync_sub(curlun);
2345 +       curlun->prevent_medium_removal = prevent;
2346 +       return 0;
2347 +}
2348 +
2349 +
2350 +static int do_read_format_capacities(struct fsg_dev *fsg,
2351 +                       struct fsg_buffhd *bh)
2352 +{
2353 +       struct fsg_lun  *curlun = fsg->curlun;
2354 +       u8              *buf = (u8 *) bh->buf;
2355 +
2356 +       buf[0] = buf[1] = buf[2] = 0;
2357 +       buf[3] = 8;             // Only the Current/Maximum Capacity Descriptor
2358 +       buf += 4;
2359 +
2360 +       put_unaligned_be32(curlun->num_sectors, &buf[0]);
2361 +                                               /* Number of blocks */
2362 +       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
2363 +       buf[4] = 0x02;                          /* Current capacity */
2364 +       return 12;
2365 +}
2366 +
2367 +
2368 +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
2369 +{
2370 +       struct fsg_lun  *curlun = fsg->curlun;
2371 +
2372 +       /* We don't support MODE SELECT */
2373 +       curlun->sense_data = SS_INVALID_COMMAND;
2374 +       return -EINVAL;
2375 +}
2376 +
2377 +
2378 +/*-------------------------------------------------------------------------*/
2379 +
2380 +static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
2381 +{
2382 +       int     rc;
2383 +
2384 +       rc = fsg_set_halt(fsg, fsg->bulk_in);
2385 +       if (rc == -EAGAIN)
2386 +               VDBG(fsg, "delayed bulk-in endpoint halt\n");
2387 +       while (rc != 0) {
2388 +               if (rc != -EAGAIN) {
2389 +                       WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
2390 +                       rc = 0;
2391 +                       break;
2392 +               }
2393 +
2394 +               /* Wait for a short time and then try again */
2395 +               if (msleep_interruptible(100) != 0)
2396 +                       return -EINTR;
2397 +               rc = usb_ep_set_halt(fsg->bulk_in);
2398 +       }
2399 +       return rc;
2400 +}
2401 +
2402 +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
2403 +{
2404 +       int     rc;
2405 +
2406 +       DBG(fsg, "bulk-in set wedge\n");
2407 +       rc = usb_ep_set_wedge(fsg->bulk_in);
2408 +       if (rc == -EAGAIN)
2409 +               VDBG(fsg, "delayed bulk-in endpoint wedge\n");
2410 +       while (rc != 0) {
2411 +               if (rc != -EAGAIN) {
2412 +                       WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
2413 +                       rc = 0;
2414 +                       break;
2415 +               }
2416 +
2417 +               /* Wait for a short time and then try again */
2418 +               if (msleep_interruptible(100) != 0)
2419 +                       return -EINTR;
2420 +               rc = usb_ep_set_wedge(fsg->bulk_in);
2421 +       }
2422 +       return rc;
2423 +}
2424 +
2425 +static int throw_away_data(struct fsg_dev *fsg)
2426 +{
2427 +       struct fsg_buffhd       *bh;
2428 +       u32                     amount;
2429 +       int                     rc;
2430 +
2431 +       while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
2432 +                       fsg->usb_amount_left > 0) {
2433 +
2434 +               /* Throw away the data in a filled buffer */
2435 +               if (bh->state == BUF_STATE_FULL) {
2436 +                       smp_rmb();
2437 +                       bh->state = BUF_STATE_EMPTY;
2438 +                       fsg->next_buffhd_to_drain = bh->next;
2439 +
2440 +                       /* A short packet or an error ends everything */
2441 +                       if (bh->outreq->actual < bh->bulk_out_intended_length ||
2442 +                                       bh->outreq->status != 0) {
2443 +                               raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2444 +                               return -EINTR;
2445 +                       }
2446 +                       continue;
2447 +               }
2448 +
2449 +               /* Try to submit another request if we need one */
2450 +               bh = fsg->next_buffhd_to_fill;
2451 +               if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
2452 +                       amount = min(fsg->usb_amount_left,
2453 +                                       (u32) mod_data.buflen);
2454 +
2455 +                       /* Except at the end of the transfer, amount will be
2456 +                        * equal to the buffer size, which is divisible by
2457 +                        * the bulk-out maxpacket size.
2458 +                        */
2459 +                       set_bulk_out_req_length(fsg, bh, amount);
2460 +                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
2461 +                                       &bh->outreq_busy, &bh->state);
2462 +                       fsg->next_buffhd_to_fill = bh->next;
2463 +                       fsg->usb_amount_left -= amount;
2464 +                       continue;
2465 +               }
2466 +
2467 +               /* Otherwise wait for something to happen */
2468 +               rc = sleep_thread(fsg);
2469 +               if (rc)
2470 +                       return rc;
2471 +       }
2472 +       return 0;
2473 +}
2474 +
2475 +
2476 +static int finish_reply(struct fsg_dev *fsg)
2477 +{
2478 +       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
2479 +       int                     rc = 0;
2480 +
2481 +       switch (fsg->data_dir) {
2482 +       case DATA_DIR_NONE:
2483 +               break;                  // Nothing to send
2484 +
2485 +       /* If we don't know whether the host wants to read or write,
2486 +        * this must be CB or CBI with an unknown command.  We mustn't
2487 +        * try to send or receive any data.  So stall both bulk pipes
2488 +        * if we can and wait for a reset. */
2489 +       case DATA_DIR_UNKNOWN:
2490 +               if (mod_data.can_stall) {
2491 +                       fsg_set_halt(fsg, fsg->bulk_out);
2492 +                       rc = halt_bulk_in_endpoint(fsg);
2493 +               }
2494 +               break;
2495 +
2496 +       /* All but the last buffer of data must have already been sent */
2497 +       case DATA_DIR_TO_HOST:
2498 +               if (fsg->data_size == 0)
2499 +                       ;               // Nothing to send
2500 +
2501 +               /* If there's no residue, simply send the last buffer */
2502 +               else if (fsg->residue == 0) {
2503 +                       bh->inreq->zero = 0;
2504 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2505 +                                       &bh->inreq_busy, &bh->state);
2506 +                       fsg->next_buffhd_to_fill = bh->next;
2507 +               }
2508 +
2509 +               /* There is a residue.  For CB and CBI, simply mark the end
2510 +                * of the data with a short packet.  However, if we are
2511 +                * allowed to stall, there was no data at all (residue ==
2512 +                * data_size), and the command failed (invalid LUN or
2513 +                * sense data is set), then halt the bulk-in endpoint
2514 +                * instead. */
2515 +               else if (!transport_is_bbb()) {
2516 +                       if (mod_data.can_stall &&
2517 +                                       fsg->residue == fsg->data_size &&
2518 +       (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
2519 +                               bh->state = BUF_STATE_EMPTY;
2520 +                               rc = halt_bulk_in_endpoint(fsg);
2521 +                       } else {
2522 +                               bh->inreq->zero = 1;
2523 +                               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2524 +                                               &bh->inreq_busy, &bh->state);
2525 +                               fsg->next_buffhd_to_fill = bh->next;
2526 +                       }
2527 +               }
2528 +
2529 +               /*
2530 +                * For Bulk-only, mark the end of the data with a short
2531 +                * packet.  If we are allowed to stall, halt the bulk-in
2532 +                * endpoint.  (Note: This violates the Bulk-Only Transport
2533 +                * specification, which requires us to pad the data if we
2534 +                * don't halt the endpoint.  Presumably nobody will mind.)
2535 +                */
2536 +               else {
2537 +                       bh->inreq->zero = 1;
2538 +                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
2539 +                                       &bh->inreq_busy, &bh->state);
2540 +                       fsg->next_buffhd_to_fill = bh->next;
2541 +                       if (mod_data.can_stall)
2542 +                               rc = halt_bulk_in_endpoint(fsg);
2543 +               }
2544 +               break;
2545 +
2546 +       /* We have processed all we want from the data the host has sent.
2547 +        * There may still be outstanding bulk-out requests. */
2548 +       case DATA_DIR_FROM_HOST:
2549 +               if (fsg->residue == 0)
2550 +                       ;               // Nothing to receive
2551 +
2552 +               /* Did the host stop sending unexpectedly early? */
2553 +               else if (fsg->short_packet_received) {
2554 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2555 +                       rc = -EINTR;
2556 +               }
2557 +
2558 +               /* We haven't processed all the incoming data.  Even though
2559 +                * we may be allowed to stall, doing so would cause a race.
2560 +                * The controller may already have ACK'ed all the remaining
2561 +                * bulk-out packets, in which case the host wouldn't see a
2562 +                * STALL.  Not realizing the endpoint was halted, it wouldn't
2563 +                * clear the halt -- leading to problems later on. */
2564 +#if 0
2565 +               else if (mod_data.can_stall) {
2566 +                       fsg_set_halt(fsg, fsg->bulk_out);
2567 +                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
2568 +                       rc = -EINTR;
2569 +               }
2570 +#endif
2571 +
2572 +               /* We can't stall.  Read in the excess data and throw it
2573 +                * all away. */
2574 +               else
2575 +                       rc = throw_away_data(fsg);
2576 +               break;
2577 +       }
2578 +       return rc;
2579 +}
2580 +
2581 +
2582 +static int send_status(struct fsg_dev *fsg)
2583 +{
2584 +       struct fsg_lun          *curlun = fsg->curlun;
2585 +       struct fsg_buffhd       *bh;
2586 +       int                     rc;
2587 +       u8                      status = US_BULK_STAT_OK;
2588 +       u32                     sd, sdinfo = 0;
2589 +
2590 +       /* Wait for the next buffer to become available */
2591 +       bh = fsg->next_buffhd_to_fill;
2592 +       while (bh->state != BUF_STATE_EMPTY) {
2593 +               rc = sleep_thread(fsg);
2594 +               if (rc)
2595 +                       return rc;
2596 +       }
2597 +
2598 +       if (curlun) {
2599 +               sd = curlun->sense_data;
2600 +               sdinfo = curlun->sense_data_info;
2601 +       } else if (fsg->bad_lun_okay)
2602 +               sd = SS_NO_SENSE;
2603 +       else
2604 +               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
2605 +
2606 +       if (fsg->phase_error) {
2607 +               DBG(fsg, "sending phase-error status\n");
2608 +               status = US_BULK_STAT_PHASE;
2609 +               sd = SS_INVALID_COMMAND;
2610 +       } else if (sd != SS_NO_SENSE) {
2611 +               DBG(fsg, "sending command-failure status\n");
2612 +               status = US_BULK_STAT_FAIL;
2613 +               VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
2614 +                               "  info x%x\n",
2615 +                               SK(sd), ASC(sd), ASCQ(sd), sdinfo);
2616 +       }
2617 +
2618 +       if (transport_is_bbb()) {
2619 +               struct bulk_cs_wrap     *csw = bh->buf;
2620 +
2621 +               /* Store and send the Bulk-only CSW */
2622 +               csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
2623 +               csw->Tag = fsg->tag;
2624 +               csw->Residue = cpu_to_le32(fsg->residue);
2625 +               csw->Status = status;
2626 +
2627 +               bh->inreq->length = US_BULK_CS_WRAP_LEN;
2628 +               bh->inreq->zero = 0;
2629 +               start_transfer(fsg, fsg->bulk_in, bh->inreq,
2630 +                               &bh->inreq_busy, &bh->state);
2631 +
2632 +       } else if (mod_data.transport_type == USB_PR_CB) {
2633 +
2634 +               /* Control-Bulk transport has no status phase! */
2635 +               return 0;
2636 +
2637 +       } else {                        // USB_PR_CBI
2638 +               struct interrupt_data   *buf = bh->buf;
2639 +
2640 +               /* Store and send the Interrupt data.  UFI sends the ASC
2641 +                * and ASCQ bytes.  Everything else sends a Type (which
2642 +                * is always 0) and the status Value. */
2643 +               if (mod_data.protocol_type == USB_SC_UFI) {
2644 +                       buf->bType = ASC(sd);
2645 +                       buf->bValue = ASCQ(sd);
2646 +               } else {
2647 +                       buf->bType = 0;
2648 +                       buf->bValue = status;
2649 +               }
2650 +               fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
2651 +
2652 +               fsg->intr_buffhd = bh;          // Point to the right buffhd
2653 +               fsg->intreq->buf = bh->inreq->buf;
2654 +               fsg->intreq->context = bh;
2655 +               start_transfer(fsg, fsg->intr_in, fsg->intreq,
2656 +                               &fsg->intreq_busy, &bh->state);
2657 +       }
2658 +
2659 +       fsg->next_buffhd_to_fill = bh->next;
2660 +       return 0;
2661 +}
2662 +
2663 +
2664 +/*-------------------------------------------------------------------------*/
2665 +
2666 +/* Check whether the command is properly formed and whether its data size
2667 + * and direction agree with the values we already have. */
2668 +static int check_command(struct fsg_dev *fsg, int cmnd_size,
2669 +               enum data_direction data_dir, unsigned int mask,
2670 +               int needs_medium, const char *name)
2671 +{
2672 +       int                     i;
2673 +       int                     lun = fsg->cmnd[1] >> 5;
2674 +       static const char       dirletter[4] = {'u', 'o', 'i', 'n'};
2675 +       char                    hdlen[20];
2676 +       struct fsg_lun          *curlun;
2677 +
2678 +       /* Adjust the expected cmnd_size for protocol encapsulation padding.
2679 +        * Transparent SCSI doesn't pad. */
2680 +       if (protocol_is_scsi())
2681 +               ;
2682 +
2683 +       /* There's some disagreement as to whether RBC pads commands or not.
2684 +        * We'll play it safe and accept either form. */
2685 +       else if (mod_data.protocol_type == USB_SC_RBC) {
2686 +               if (fsg->cmnd_size == 12)
2687 +                       cmnd_size = 12;
2688 +
2689 +       /* All the other protocols pad to 12 bytes */
2690 +       } else
2691 +               cmnd_size = 12;
2692 +
2693 +       hdlen[0] = 0;
2694 +       if (fsg->data_dir != DATA_DIR_UNKNOWN)
2695 +               sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
2696 +                               fsg->data_size);
2697 +       VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
2698 +                       name, cmnd_size, dirletter[(int) data_dir],
2699 +                       fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
2700 +
2701 +       /* We can't reply at all until we know the correct data direction
2702 +        * and size. */
2703 +       if (fsg->data_size_from_cmnd == 0)
2704 +               data_dir = DATA_DIR_NONE;
2705 +       if (fsg->data_dir == DATA_DIR_UNKNOWN) {        // CB or CBI
2706 +               fsg->data_dir = data_dir;
2707 +               fsg->data_size = fsg->data_size_from_cmnd;
2708 +
2709 +       } else {                                        // Bulk-only
2710 +               if (fsg->data_size < fsg->data_size_from_cmnd) {
2711 +
2712 +                       /* Host data size < Device data size is a phase error.
2713 +                        * Carry out the command, but only transfer as much
2714 +                        * as we are allowed. */
2715 +                       fsg->data_size_from_cmnd = fsg->data_size;
2716 +                       fsg->phase_error = 1;
2717 +               }
2718 +       }
2719 +       fsg->residue = fsg->usb_amount_left = fsg->data_size;
2720 +
2721 +       /* Conflicting data directions is a phase error */
2722 +       if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
2723 +               fsg->phase_error = 1;
2724 +               return -EINVAL;
2725 +       }
2726 +
2727 +       /* Verify the length of the command itself */
2728 +       if (cmnd_size != fsg->cmnd_size) {
2729 +
2730 +               /* Special case workaround: There are plenty of buggy SCSI
2731 +                * implementations. Many have issues with cbw->Length
2732 +                * field passing a wrong command size. For those cases we
2733 +                * always try to work around the problem by using the length
2734 +                * sent by the host side provided it is at least as large
2735 +                * as the correct command length.
2736 +                * Examples of such cases would be MS-Windows, which issues
2737 +                * REQUEST SENSE with cbw->Length == 12 where it should
2738 +                * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
2739 +                * REQUEST SENSE with cbw->Length == 10 where it should
2740 +                * be 6 as well.
2741 +                */
2742 +               if (cmnd_size <= fsg->cmnd_size) {
2743 +                       DBG(fsg, "%s is buggy! Expected length %d "
2744 +                                       "but we got %d\n", name,
2745 +                                       cmnd_size, fsg->cmnd_size);
2746 +                       cmnd_size = fsg->cmnd_size;
2747 +               } else {
2748 +                       fsg->phase_error = 1;
2749 +                       return -EINVAL;
2750 +               }
2751 +       }
2752 +
2753 +       /* Check that the LUN values are consistent */
2754 +       if (transport_is_bbb()) {
2755 +               if (fsg->lun != lun)
2756 +                       DBG(fsg, "using LUN %d from CBW, "
2757 +                                       "not LUN %d from CDB\n",
2758 +                                       fsg->lun, lun);
2759 +       }
2760 +
2761 +       /* Check the LUN */
2762 +       curlun = fsg->curlun;
2763 +       if (curlun) {
2764 +               if (fsg->cmnd[0] != REQUEST_SENSE) {
2765 +                       curlun->sense_data = SS_NO_SENSE;
2766 +                       curlun->sense_data_info = 0;
2767 +                       curlun->info_valid = 0;
2768 +               }
2769 +       } else {
2770 +               fsg->bad_lun_okay = 0;
2771 +
2772 +               /* INQUIRY and REQUEST SENSE commands are explicitly allowed
2773 +                * to use unsupported LUNs; all others may not. */
2774 +               if (fsg->cmnd[0] != INQUIRY &&
2775 +                               fsg->cmnd[0] != REQUEST_SENSE) {
2776 +                       DBG(fsg, "unsupported LUN %d\n", fsg->lun);
2777 +                       return -EINVAL;
2778 +               }
2779 +       }
2780 +
2781 +       /* If a unit attention condition exists, only INQUIRY and
2782 +        * REQUEST SENSE commands are allowed; anything else must fail. */
2783 +       if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
2784 +                       fsg->cmnd[0] != INQUIRY &&
2785 +                       fsg->cmnd[0] != REQUEST_SENSE) {
2786 +               curlun->sense_data = curlun->unit_attention_data;
2787 +               curlun->unit_attention_data = SS_NO_SENSE;
2788 +               return -EINVAL;
2789 +       }
2790 +
2791 +       /* Check that only command bytes listed in the mask are non-zero */
2792 +       fsg->cmnd[1] &= 0x1f;                   // Mask away the LUN
2793 +       for (i = 1; i < cmnd_size; ++i) {
2794 +               if (fsg->cmnd[i] && !(mask & (1 << i))) {
2795 +                       if (curlun)
2796 +                               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
2797 +                       return -EINVAL;
2798 +               }
2799 +       }
2800 +
2801 +       /* If the medium isn't mounted and the command needs to access
2802 +        * it, return an error. */
2803 +       if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
2804 +               curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
2805 +               return -EINVAL;
2806 +       }
2807 +
2808 +       return 0;
2809 +}
2810 +
2811 +/* wrapper of check_command for data size in blocks handling */
2812 +static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
2813 +               enum data_direction data_dir, unsigned int mask,
2814 +               int needs_medium, const char *name)
2815 +{
2816 +       if (fsg->curlun)
2817 +               fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
2818 +       return check_command(fsg, cmnd_size, data_dir,
2819 +                       mask, needs_medium, name);
2820 +}
2821 +
2822 +static int do_scsi_command(struct fsg_dev *fsg)
2823 +{
2824 +       struct fsg_buffhd       *bh;
2825 +       int                     rc;
2826 +       int                     reply = -EINVAL;
2827 +       int                     i;
2828 +       static char             unknown[16];
2829 +
2830 +       dump_cdb(fsg);
2831 +
2832 +       /* Wait for the next buffer to become available for data or status */
2833 +       bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
2834 +       while (bh->state != BUF_STATE_EMPTY) {
2835 +               rc = sleep_thread(fsg);
2836 +               if (rc)
2837 +                       return rc;
2838 +       }
2839 +       fsg->phase_error = 0;
2840 +       fsg->short_packet_received = 0;
2841 +
2842 +       down_read(&fsg->filesem);       // We're using the backing file
2843 +       switch (fsg->cmnd[0]) {
2844 +
2845 +       case INQUIRY:
2846 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2847 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2848 +                               (1<<4), 0,
2849 +                               "INQUIRY")) == 0)
2850 +                       reply = do_inquiry(fsg, bh);
2851 +               break;
2852 +
2853 +       case MODE_SELECT:
2854 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2855 +               if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
2856 +                               (1<<1) | (1<<4), 0,
2857 +                               "MODE SELECT(6)")) == 0)
2858 +                       reply = do_mode_select(fsg, bh);
2859 +               break;
2860 +
2861 +       case MODE_SELECT_10:
2862 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2863 +               if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
2864 +                               (1<<1) | (3<<7), 0,
2865 +                               "MODE SELECT(10)")) == 0)
2866 +                       reply = do_mode_select(fsg, bh);
2867 +               break;
2868 +
2869 +       case MODE_SENSE:
2870 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2871 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2872 +                               (1<<1) | (1<<2) | (1<<4), 0,
2873 +                               "MODE SENSE(6)")) == 0)
2874 +                       reply = do_mode_sense(fsg, bh);
2875 +               break;
2876 +
2877 +       case MODE_SENSE_10:
2878 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2879 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2880 +                               (1<<1) | (1<<2) | (3<<7), 0,
2881 +                               "MODE SENSE(10)")) == 0)
2882 +                       reply = do_mode_sense(fsg, bh);
2883 +               break;
2884 +
2885 +       case ALLOW_MEDIUM_REMOVAL:
2886 +               fsg->data_size_from_cmnd = 0;
2887 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2888 +                               (1<<4), 0,
2889 +                               "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
2890 +                       reply = do_prevent_allow(fsg);
2891 +               break;
2892 +
2893 +       case READ_6:
2894 +               i = fsg->cmnd[4];
2895 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
2896 +               if ((reply = check_command_size_in_blocks(fsg, 6,
2897 +                               DATA_DIR_TO_HOST,
2898 +                               (7<<1) | (1<<4), 1,
2899 +                               "READ(6)")) == 0)
2900 +                       reply = do_read(fsg);
2901 +               break;
2902 +
2903 +       case READ_10:
2904 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2905 +               if ((reply = check_command_size_in_blocks(fsg, 10,
2906 +                               DATA_DIR_TO_HOST,
2907 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2908 +                               "READ(10)")) == 0)
2909 +                       reply = do_read(fsg);
2910 +               break;
2911 +
2912 +       case READ_12:
2913 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
2914 +               if ((reply = check_command_size_in_blocks(fsg, 12,
2915 +                               DATA_DIR_TO_HOST,
2916 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
2917 +                               "READ(12)")) == 0)
2918 +                       reply = do_read(fsg);
2919 +               break;
2920 +
2921 +       case READ_CAPACITY:
2922 +               fsg->data_size_from_cmnd = 8;
2923 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2924 +                               (0xf<<2) | (1<<8), 1,
2925 +                               "READ CAPACITY")) == 0)
2926 +                       reply = do_read_capacity(fsg, bh);
2927 +               break;
2928 +
2929 +       case READ_HEADER:
2930 +               if (!mod_data.cdrom)
2931 +                       goto unknown_cmnd;
2932 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2933 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2934 +                               (3<<7) | (0x1f<<1), 1,
2935 +                               "READ HEADER")) == 0)
2936 +                       reply = do_read_header(fsg, bh);
2937 +               break;
2938 +
2939 +       case READ_TOC:
2940 +               if (!mod_data.cdrom)
2941 +                       goto unknown_cmnd;
2942 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2943 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2944 +                               (7<<6) | (1<<1), 1,
2945 +                               "READ TOC")) == 0)
2946 +                       reply = do_read_toc(fsg, bh);
2947 +               break;
2948 +
2949 +       case READ_FORMAT_CAPACITIES:
2950 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
2951 +               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
2952 +                               (3<<7), 1,
2953 +                               "READ FORMAT CAPACITIES")) == 0)
2954 +                       reply = do_read_format_capacities(fsg, bh);
2955 +               break;
2956 +
2957 +       case REQUEST_SENSE:
2958 +               fsg->data_size_from_cmnd = fsg->cmnd[4];
2959 +               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
2960 +                               (1<<4), 0,
2961 +                               "REQUEST SENSE")) == 0)
2962 +                       reply = do_request_sense(fsg, bh);
2963 +               break;
2964 +
2965 +       case START_STOP:
2966 +               fsg->data_size_from_cmnd = 0;
2967 +               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
2968 +                               (1<<1) | (1<<4), 0,
2969 +                               "START-STOP UNIT")) == 0)
2970 +                       reply = do_start_stop(fsg);
2971 +               break;
2972 +
2973 +       case SYNCHRONIZE_CACHE:
2974 +               fsg->data_size_from_cmnd = 0;
2975 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2976 +                               (0xf<<2) | (3<<7), 1,
2977 +                               "SYNCHRONIZE CACHE")) == 0)
2978 +                       reply = do_synchronize_cache(fsg);
2979 +               break;
2980 +
2981 +       case TEST_UNIT_READY:
2982 +               fsg->data_size_from_cmnd = 0;
2983 +               reply = check_command(fsg, 6, DATA_DIR_NONE,
2984 +                               0, 1,
2985 +                               "TEST UNIT READY");
2986 +               break;
2987 +
2988 +       /* Although optional, this command is used by MS-Windows.  We
2989 +        * support a minimal version: BytChk must be 0. */
2990 +       case VERIFY:
2991 +               fsg->data_size_from_cmnd = 0;
2992 +               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
2993 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
2994 +                               "VERIFY")) == 0)
2995 +                       reply = do_verify(fsg);
2996 +               break;
2997 +
2998 +       case WRITE_6:
2999 +               i = fsg->cmnd[4];
3000 +               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
3001 +               if ((reply = check_command_size_in_blocks(fsg, 6,
3002 +                               DATA_DIR_FROM_HOST,
3003 +                               (7<<1) | (1<<4), 1,
3004 +                               "WRITE(6)")) == 0)
3005 +                       reply = do_write(fsg);
3006 +               break;
3007 +
3008 +       case WRITE_10:
3009 +               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
3010 +               if ((reply = check_command_size_in_blocks(fsg, 10,
3011 +                               DATA_DIR_FROM_HOST,
3012 +                               (1<<1) | (0xf<<2) | (3<<7), 1,
3013 +                               "WRITE(10)")) == 0)
3014 +                       reply = do_write(fsg);
3015 +               break;
3016 +
3017 +       case WRITE_12:
3018 +               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
3019 +               if ((reply = check_command_size_in_blocks(fsg, 12,
3020 +                               DATA_DIR_FROM_HOST,
3021 +                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
3022 +                               "WRITE(12)")) == 0)
3023 +                       reply = do_write(fsg);
3024 +               break;
3025 +
3026 +       /* Some mandatory commands that we recognize but don't implement.
3027 +        * They don't mean much in this setting.  It's left as an exercise
3028 +        * for anyone interested to implement RESERVE and RELEASE in terms
3029 +        * of Posix locks. */
3030 +       case FORMAT_UNIT:
3031 +       case RELEASE:
3032 +       case RESERVE:
3033 +       case SEND_DIAGNOSTIC:
3034 +               // Fall through
3035 +
3036 +       default:
3037 + unknown_cmnd:
3038 +               fsg->data_size_from_cmnd = 0;
3039 +               sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
3040 +               if ((reply = check_command(fsg, fsg->cmnd_size,
3041 +                               DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
3042 +                       fsg->curlun->sense_data = SS_INVALID_COMMAND;
3043 +                       reply = -EINVAL;
3044 +               }
3045 +               break;
3046 +       }
3047 +       up_read(&fsg->filesem);
3048 +
3049 +       if (reply == -EINTR || signal_pending(current))
3050 +               return -EINTR;
3051 +
3052 +       /* Set up the single reply buffer for finish_reply() */
3053 +       if (reply == -EINVAL)
3054 +               reply = 0;              // Error reply length
3055 +       if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
3056 +               reply = min((u32) reply, fsg->data_size_from_cmnd);
3057 +               bh->inreq->length = reply;
3058 +               bh->state = BUF_STATE_FULL;
3059 +               fsg->residue -= reply;
3060 +       }                               // Otherwise it's already set
3061 +
3062 +       return 0;
3063 +}
3064 +
3065 +
3066 +/*-------------------------------------------------------------------------*/
3067 +
3068 +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
3069 +{
3070 +       struct usb_request              *req = bh->outreq;
3071 +       struct bulk_cb_wrap     *cbw = req->buf;
3072 +
3073 +       /* Was this a real packet?  Should it be ignored? */
3074 +       if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3075 +               return -EINVAL;
3076 +
3077 +       /* Is the CBW valid? */
3078 +       if (req->actual != US_BULK_CB_WRAP_LEN ||
3079 +                       cbw->Signature != cpu_to_le32(
3080 +                               US_BULK_CB_SIGN)) {
3081 +               DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
3082 +                               req->actual,
3083 +                               le32_to_cpu(cbw->Signature));
3084 +
3085 +               /* The Bulk-only spec says we MUST stall the IN endpoint
3086 +                * (6.6.1), so it's unavoidable.  It also says we must
3087 +                * retain this state until the next reset, but there's
3088 +                * no way to tell the controller driver it should ignore
3089 +                * Clear-Feature(HALT) requests.
3090 +                *
3091 +                * We aren't required to halt the OUT endpoint; instead
3092 +                * we can simply accept and discard any data received
3093 +                * until the next reset. */
3094 +               wedge_bulk_in_endpoint(fsg);
3095 +               set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3096 +               return -EINVAL;
3097 +       }
3098 +
3099 +       /* Is the CBW meaningful? */
3100 +       if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
3101 +                       cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
3102 +               DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
3103 +                               "cmdlen %u\n",
3104 +                               cbw->Lun, cbw->Flags, cbw->Length);
3105 +
3106 +               /* We can do anything we want here, so let's stall the
3107 +                * bulk pipes if we are allowed to. */
3108 +               if (mod_data.can_stall) {
3109 +                       fsg_set_halt(fsg, fsg->bulk_out);
3110 +                       halt_bulk_in_endpoint(fsg);
3111 +               }
3112 +               return -EINVAL;
3113 +       }
3114 +
3115 +       /* Save the command for later */
3116 +       fsg->cmnd_size = cbw->Length;
3117 +       memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
3118 +       if (cbw->Flags & US_BULK_FLAG_IN)
3119 +               fsg->data_dir = DATA_DIR_TO_HOST;
3120 +       else
3121 +               fsg->data_dir = DATA_DIR_FROM_HOST;
3122 +       fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
3123 +       if (fsg->data_size == 0)
3124 +               fsg->data_dir = DATA_DIR_NONE;
3125 +       fsg->lun = cbw->Lun;
3126 +       fsg->tag = cbw->Tag;
3127 +       return 0;
3128 +}
3129 +
3130 +
3131 +static int get_next_command(struct fsg_dev *fsg)
3132 +{
3133 +       struct fsg_buffhd       *bh;
3134 +       int                     rc = 0;
3135 +
3136 +       if (transport_is_bbb()) {
3137 +
3138 +               /* Wait for the next buffer to become available */
3139 +               bh = fsg->next_buffhd_to_fill;
3140 +               while (bh->state != BUF_STATE_EMPTY) {
3141 +                       rc = sleep_thread(fsg);
3142 +                       if (rc)
3143 +                               return rc;
3144 +               }
3145 +
3146 +               /* Queue a request to read a Bulk-only CBW */
3147 +               set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
3148 +               start_transfer(fsg, fsg->bulk_out, bh->outreq,
3149 +                               &bh->outreq_busy, &bh->state);
3150 +
3151 +               /* We will drain the buffer in software, which means we
3152 +                * can reuse it for the next filling.  No need to advance
3153 +                * next_buffhd_to_fill. */
3154 +
3155 +               /* Wait for the CBW to arrive */
3156 +               while (bh->state != BUF_STATE_FULL) {
3157 +                       rc = sleep_thread(fsg);
3158 +                       if (rc)
3159 +                               return rc;
3160 +               }
3161 +               smp_rmb();
3162 +               rc = received_cbw(fsg, bh);
3163 +               bh->state = BUF_STATE_EMPTY;
3164 +
3165 +       } else {                // USB_PR_CB or USB_PR_CBI
3166 +
3167 +               /* Wait for the next command to arrive */
3168 +               while (fsg->cbbuf_cmnd_size == 0) {
3169 +                       rc = sleep_thread(fsg);
3170 +                       if (rc)
3171 +                               return rc;
3172 +               }
3173 +
3174 +               /* Is the previous status interrupt request still busy?
3175 +                * The host is allowed to skip reading the status,
3176 +                * so we must cancel it. */
3177 +               if (fsg->intreq_busy)
3178 +                       usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3179 +
3180 +               /* Copy the command and mark the buffer empty */
3181 +               fsg->data_dir = DATA_DIR_UNKNOWN;
3182 +               spin_lock_irq(&fsg->lock);
3183 +               fsg->cmnd_size = fsg->cbbuf_cmnd_size;
3184 +               memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
3185 +               fsg->cbbuf_cmnd_size = 0;
3186 +               spin_unlock_irq(&fsg->lock);
3187 +
3188 +               /* Use LUN from the command */
3189 +               fsg->lun = fsg->cmnd[1] >> 5;
3190 +       }
3191 +
3192 +       /* Update current lun */
3193 +       if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
3194 +               fsg->curlun = &fsg->luns[fsg->lun];
3195 +       else
3196 +               fsg->curlun = NULL;
3197 +
3198 +       return rc;
3199 +}
3200 +
3201 +
3202 +/*-------------------------------------------------------------------------*/
3203 +
3204 +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
3205 +               const struct usb_endpoint_descriptor *d)
3206 +{
3207 +       int     rc;
3208 +
3209 +       ep->driver_data = fsg;
3210 +       ep->desc = d;
3211 +       rc = usb_ep_enable(ep);
3212 +       if (rc)
3213 +               ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
3214 +       return rc;
3215 +}
3216 +
3217 +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
3218 +               struct usb_request **preq)
3219 +{
3220 +       *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
3221 +       if (*preq)
3222 +               return 0;
3223 +       ERROR(fsg, "can't allocate request for %s\n", ep->name);
3224 +       return -ENOMEM;
3225 +}
3226 +
3227 +/*
3228 + * Reset interface setting and re-init endpoint state (toggle etc).
3229 + * Call with altsetting < 0 to disable the interface.  The only other
3230 + * available altsetting is 0, which enables the interface.
3231 + */
3232 +static int do_set_interface(struct fsg_dev *fsg, int altsetting)
3233 +{
3234 +       int     rc = 0;
3235 +       int     i;
3236 +       const struct usb_endpoint_descriptor    *d;
3237 +
3238 +       if (fsg->running)
3239 +               DBG(fsg, "reset interface\n");
3240 +
3241 +reset:
3242 +       /* Deallocate the requests */
3243 +       for (i = 0; i < fsg_num_buffers; ++i) {
3244 +               struct fsg_buffhd *bh = &fsg->buffhds[i];
3245 +
3246 +               if (bh->inreq) {
3247 +                       usb_ep_free_request(fsg->bulk_in, bh->inreq);
3248 +                       bh->inreq = NULL;
3249 +               }
3250 +               if (bh->outreq) {
3251 +                       usb_ep_free_request(fsg->bulk_out, bh->outreq);
3252 +                       bh->outreq = NULL;
3253 +               }
3254 +       }
3255 +       if (fsg->intreq) {
3256 +               usb_ep_free_request(fsg->intr_in, fsg->intreq);
3257 +               fsg->intreq = NULL;
3258 +       }
3259 +
3260 +       /* Disable the endpoints */
3261 +       if (fsg->bulk_in_enabled) {
3262 +               usb_ep_disable(fsg->bulk_in);
3263 +               fsg->bulk_in_enabled = 0;
3264 +       }
3265 +       if (fsg->bulk_out_enabled) {
3266 +               usb_ep_disable(fsg->bulk_out);
3267 +               fsg->bulk_out_enabled = 0;
3268 +       }
3269 +       if (fsg->intr_in_enabled) {
3270 +               usb_ep_disable(fsg->intr_in);
3271 +               fsg->intr_in_enabled = 0;
3272 +       }
3273 +
3274 +       fsg->running = 0;
3275 +       if (altsetting < 0 || rc != 0)
3276 +               return rc;
3277 +
3278 +       DBG(fsg, "set interface %d\n", altsetting);
3279 +
3280 +       /* Enable the endpoints */
3281 +       d = fsg_ep_desc(fsg->gadget,
3282 +                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
3283 +                       &fsg_ss_bulk_in_desc);
3284 +       if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
3285 +               goto reset;
3286 +       fsg->bulk_in_enabled = 1;
3287 +
3288 +       d = fsg_ep_desc(fsg->gadget,
3289 +                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
3290 +                       &fsg_ss_bulk_out_desc);
3291 +       if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
3292 +               goto reset;
3293 +       fsg->bulk_out_enabled = 1;
3294 +       fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
3295 +       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
3296 +
3297 +       if (transport_is_cbi()) {
3298 +               d = fsg_ep_desc(fsg->gadget,
3299 +                               &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
3300 +                               &fsg_ss_intr_in_desc);
3301 +               if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
3302 +                       goto reset;
3303 +               fsg->intr_in_enabled = 1;
3304 +       }
3305 +
3306 +       /* Allocate the requests */
3307 +       for (i = 0; i < fsg_num_buffers; ++i) {
3308 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3309 +
3310 +               if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
3311 +                       goto reset;
3312 +               if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
3313 +                       goto reset;
3314 +               bh->inreq->buf = bh->outreq->buf = bh->buf;
3315 +               bh->inreq->context = bh->outreq->context = bh;
3316 +               bh->inreq->complete = bulk_in_complete;
3317 +               bh->outreq->complete = bulk_out_complete;
3318 +       }
3319 +       if (transport_is_cbi()) {
3320 +               if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
3321 +                       goto reset;
3322 +               fsg->intreq->complete = intr_in_complete;
3323 +       }
3324 +
3325 +       fsg->running = 1;
3326 +       for (i = 0; i < fsg->nluns; ++i)
3327 +               fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3328 +       return rc;
3329 +}
3330 +
3331 +
3332 +/*
3333 + * Change our operational configuration.  This code must agree with the code
3334 + * that returns config descriptors, and with interface altsetting code.
3335 + *
3336 + * It's also responsible for power management interactions.  Some
3337 + * configurations might not work with our current power sources.
3338 + * For now we just assume the gadget is always self-powered.
3339 + */
3340 +static int do_set_config(struct fsg_dev *fsg, u8 new_config)
3341 +{
3342 +       int     rc = 0;
3343 +
3344 +       /* Disable the single interface */
3345 +       if (fsg->config != 0) {
3346 +               DBG(fsg, "reset config\n");
3347 +               fsg->config = 0;
3348 +               rc = do_set_interface(fsg, -1);
3349 +       }
3350 +
3351 +       /* Enable the interface */
3352 +       if (new_config != 0) {
3353 +               fsg->config = new_config;
3354 +               if ((rc = do_set_interface(fsg, 0)) != 0)
3355 +                       fsg->config = 0;        // Reset on errors
3356 +               else
3357 +                       INFO(fsg, "%s config #%d\n",
3358 +                            usb_speed_string(fsg->gadget->speed),
3359 +                            fsg->config);
3360 +       }
3361 +       return rc;
3362 +}
3363 +
3364 +
3365 +/*-------------------------------------------------------------------------*/
3366 +
3367 +static void handle_exception(struct fsg_dev *fsg)
3368 +{
3369 +       siginfo_t               info;
3370 +       int                     sig;
3371 +       int                     i;
3372 +       int                     num_active;
3373 +       struct fsg_buffhd       *bh;
3374 +       enum fsg_state          old_state;
3375 +       u8                      new_config;
3376 +       struct fsg_lun          *curlun;
3377 +       unsigned int            exception_req_tag;
3378 +       int                     rc;
3379 +
3380 +       /* Clear the existing signals.  Anything but SIGUSR1 is converted
3381 +        * into a high-priority EXIT exception. */
3382 +       for (;;) {
3383 +               sig = dequeue_signal_lock(current, &current->blocked, &info);
3384 +               if (!sig)
3385 +                       break;
3386 +               if (sig != SIGUSR1) {
3387 +                       if (fsg->state < FSG_STATE_EXIT)
3388 +                               DBG(fsg, "Main thread exiting on signal\n");
3389 +                       raise_exception(fsg, FSG_STATE_EXIT);
3390 +               }
3391 +       }
3392 +
3393 +       /* Cancel all the pending transfers */
3394 +       if (fsg->intreq_busy)
3395 +               usb_ep_dequeue(fsg->intr_in, fsg->intreq);
3396 +       for (i = 0; i < fsg_num_buffers; ++i) {
3397 +               bh = &fsg->buffhds[i];
3398 +               if (bh->inreq_busy)
3399 +                       usb_ep_dequeue(fsg->bulk_in, bh->inreq);
3400 +               if (bh->outreq_busy)
3401 +                       usb_ep_dequeue(fsg->bulk_out, bh->outreq);
3402 +       }
3403 +
3404 +       /* Wait until everything is idle */
3405 +       for (;;) {
3406 +               num_active = fsg->intreq_busy;
3407 +               for (i = 0; i < fsg_num_buffers; ++i) {
3408 +                       bh = &fsg->buffhds[i];
3409 +                       num_active += bh->inreq_busy + bh->outreq_busy;
3410 +               }
3411 +               if (num_active == 0)
3412 +                       break;
3413 +               if (sleep_thread(fsg))
3414 +                       return;
3415 +       }
3416 +
3417 +       /* Clear out the controller's fifos */
3418 +       if (fsg->bulk_in_enabled)
3419 +               usb_ep_fifo_flush(fsg->bulk_in);
3420 +       if (fsg->bulk_out_enabled)
3421 +               usb_ep_fifo_flush(fsg->bulk_out);
3422 +       if (fsg->intr_in_enabled)
3423 +               usb_ep_fifo_flush(fsg->intr_in);
3424 +
3425 +       /* Reset the I/O buffer states and pointers, the SCSI
3426 +        * state, and the exception.  Then invoke the handler. */
3427 +       spin_lock_irq(&fsg->lock);
3428 +
3429 +       for (i = 0; i < fsg_num_buffers; ++i) {
3430 +               bh = &fsg->buffhds[i];
3431 +               bh->state = BUF_STATE_EMPTY;
3432 +       }
3433 +       fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
3434 +                       &fsg->buffhds[0];
3435 +
3436 +       exception_req_tag = fsg->exception_req_tag;
3437 +       new_config = fsg->new_config;
3438 +       old_state = fsg->state;
3439 +
3440 +       if (old_state == FSG_STATE_ABORT_BULK_OUT)
3441 +               fsg->state = FSG_STATE_STATUS_PHASE;
3442 +       else {
3443 +               for (i = 0; i < fsg->nluns; ++i) {
3444 +                       curlun = &fsg->luns[i];
3445 +                       curlun->prevent_medium_removal = 0;
3446 +                       curlun->sense_data = curlun->unit_attention_data =
3447 +                                       SS_NO_SENSE;
3448 +                       curlun->sense_data_info = 0;
3449 +                       curlun->info_valid = 0;
3450 +               }
3451 +               fsg->state = FSG_STATE_IDLE;
3452 +       }
3453 +       spin_unlock_irq(&fsg->lock);
3454 +
3455 +       /* Carry out any extra actions required for the exception */
3456 +       switch (old_state) {
3457 +       default:
3458 +               break;
3459 +
3460 +       case FSG_STATE_ABORT_BULK_OUT:
3461 +               send_status(fsg);
3462 +               spin_lock_irq(&fsg->lock);
3463 +               if (fsg->state == FSG_STATE_STATUS_PHASE)
3464 +                       fsg->state = FSG_STATE_IDLE;
3465 +               spin_unlock_irq(&fsg->lock);
3466 +               break;
3467 +
3468 +       case FSG_STATE_RESET:
3469 +               /* In case we were forced against our will to halt a
3470 +                * bulk endpoint, clear the halt now.  (The SuperH UDC
3471 +                * requires this.) */
3472 +               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
3473 +                       usb_ep_clear_halt(fsg->bulk_in);
3474 +
3475 +               if (transport_is_bbb()) {
3476 +                       if (fsg->ep0_req_tag == exception_req_tag)
3477 +                               ep0_queue(fsg); // Complete the status stage
3478 +
3479 +               } else if (transport_is_cbi())
3480 +                       send_status(fsg);       // Status by interrupt pipe
3481 +
3482 +               /* Technically this should go here, but it would only be
3483 +                * a waste of time.  Ditto for the INTERFACE_CHANGE and
3484 +                * CONFIG_CHANGE cases. */
3485 +               // for (i = 0; i < fsg->nluns; ++i)
3486 +               //      fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
3487 +               break;
3488 +
3489 +       case FSG_STATE_INTERFACE_CHANGE:
3490 +               rc = do_set_interface(fsg, 0);
3491 +               if (fsg->ep0_req_tag != exception_req_tag)
3492 +                       break;
3493 +               if (rc != 0)                    // STALL on errors
3494 +                       fsg_set_halt(fsg, fsg->ep0);
3495 +               else                            // Complete the status stage
3496 +                       ep0_queue(fsg);
3497 +               break;
3498 +
3499 +       case FSG_STATE_CONFIG_CHANGE:
3500 +               rc = do_set_config(fsg, new_config);
3501 +               if (fsg->ep0_req_tag != exception_req_tag)
3502 +                       break;
3503 +               if (rc != 0)                    // STALL on errors
3504 +                       fsg_set_halt(fsg, fsg->ep0);
3505 +               else                            // Complete the status stage
3506 +                       ep0_queue(fsg);
3507 +               break;
3508 +
3509 +       case FSG_STATE_DISCONNECT:
3510 +               for (i = 0; i < fsg->nluns; ++i)
3511 +                       fsg_lun_fsync_sub(fsg->luns + i);
3512 +               do_set_config(fsg, 0);          // Unconfigured state
3513 +               break;
3514 +
3515 +       case FSG_STATE_EXIT:
3516 +       case FSG_STATE_TERMINATED:
3517 +               do_set_config(fsg, 0);                  // Free resources
3518 +               spin_lock_irq(&fsg->lock);
3519 +               fsg->state = FSG_STATE_TERMINATED;      // Stop the thread
3520 +               spin_unlock_irq(&fsg->lock);
3521 +               break;
3522 +       }
3523 +}
3524 +
3525 +
3526 +/*-------------------------------------------------------------------------*/
3527 +
3528 +static int fsg_main_thread(void *fsg_)
3529 +{
3530 +       struct fsg_dev          *fsg = fsg_;
3531 +
3532 +       /* Allow the thread to be killed by a signal, but set the signal mask
3533 +        * to block everything but INT, TERM, KILL, and USR1. */
3534 +       allow_signal(SIGINT);
3535 +       allow_signal(SIGTERM);
3536 +       allow_signal(SIGKILL);
3537 +       allow_signal(SIGUSR1);
3538 +
3539 +       /* Allow the thread to be frozen */
3540 +       set_freezable();
3541 +
3542 +       /* Arrange for userspace references to be interpreted as kernel
3543 +        * pointers.  That way we can pass a kernel pointer to a routine
3544 +        * that expects a __user pointer and it will work okay. */
3545 +       set_fs(get_ds());
3546 +
3547 +       /* The main loop */
3548 +       while (fsg->state != FSG_STATE_TERMINATED) {
3549 +               if (exception_in_progress(fsg) || signal_pending(current)) {
3550 +                       handle_exception(fsg);
3551 +                       continue;
3552 +               }
3553 +
3554 +               if (!fsg->running) {
3555 +                       sleep_thread(fsg);
3556 +                       continue;
3557 +               }
3558 +
3559 +               if (get_next_command(fsg))
3560 +                       continue;
3561 +
3562 +               spin_lock_irq(&fsg->lock);
3563 +               if (!exception_in_progress(fsg))
3564 +                       fsg->state = FSG_STATE_DATA_PHASE;
3565 +               spin_unlock_irq(&fsg->lock);
3566 +
3567 +               if (do_scsi_command(fsg) || finish_reply(fsg))
3568 +                       continue;
3569 +
3570 +               spin_lock_irq(&fsg->lock);
3571 +               if (!exception_in_progress(fsg))
3572 +                       fsg->state = FSG_STATE_STATUS_PHASE;
3573 +               spin_unlock_irq(&fsg->lock);
3574 +
3575 +               if (send_status(fsg))
3576 +                       continue;
3577 +
3578 +               spin_lock_irq(&fsg->lock);
3579 +               if (!exception_in_progress(fsg))
3580 +                       fsg->state = FSG_STATE_IDLE;
3581 +               spin_unlock_irq(&fsg->lock);
3582 +               }
3583 +
3584 +       spin_lock_irq(&fsg->lock);
3585 +       fsg->thread_task = NULL;
3586 +       spin_unlock_irq(&fsg->lock);
3587 +
3588 +       /* If we are exiting because of a signal, unregister the
3589 +        * gadget driver. */
3590 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
3591 +               usb_gadget_unregister_driver(&fsg_driver);
3592 +
3593 +       /* Let the unbind and cleanup routines know the thread has exited */
3594 +       complete_and_exit(&fsg->thread_notifier, 0);
3595 +}
3596 +
3597 +
3598 +/*-------------------------------------------------------------------------*/
3599 +
3600 +
3601 +/* The write permissions and store_xxx pointers are set in fsg_bind() */
3602 +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
3603 +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
3604 +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
3605 +
3606 +
3607 +/*-------------------------------------------------------------------------*/
3608 +
3609 +static void fsg_release(struct kref *ref)
3610 +{
3611 +       struct fsg_dev  *fsg = container_of(ref, struct fsg_dev, ref);
3612 +
3613 +       kfree(fsg->luns);
3614 +       kfree(fsg);
3615 +}
3616 +
3617 +static void lun_release(struct device *dev)
3618 +{
3619 +       struct rw_semaphore     *filesem = dev_get_drvdata(dev);
3620 +       struct fsg_dev          *fsg =
3621 +               container_of(filesem, struct fsg_dev, filesem);
3622 +
3623 +       kref_put(&fsg->ref, fsg_release);
3624 +}
3625 +
3626 +static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
3627 +{
3628 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
3629 +       int                     i;
3630 +       struct fsg_lun          *curlun;
3631 +       struct usb_request      *req = fsg->ep0req;
3632 +
3633 +       DBG(fsg, "unbind\n");
3634 +       clear_bit(REGISTERED, &fsg->atomic_bitflags);
3635 +
3636 +       /* If the thread isn't already dead, tell it to exit now */
3637 +       if (fsg->state != FSG_STATE_TERMINATED) {
3638 +               raise_exception(fsg, FSG_STATE_EXIT);
3639 +               wait_for_completion(&fsg->thread_notifier);
3640 +
3641 +               /* The cleanup routine waits for this completion also */
3642 +               complete(&fsg->thread_notifier);
3643 +       }
3644 +
3645 +       /* Unregister the sysfs attribute files and the LUNs */
3646 +       for (i = 0; i < fsg->nluns; ++i) {
3647 +               curlun = &fsg->luns[i];
3648 +               if (curlun->registered) {
3649 +                       device_remove_file(&curlun->dev, &dev_attr_nofua);
3650 +                       device_remove_file(&curlun->dev, &dev_attr_ro);
3651 +                       device_remove_file(&curlun->dev, &dev_attr_file);
3652 +                       fsg_lun_close(curlun);
3653 +                       device_unregister(&curlun->dev);
3654 +                       curlun->registered = 0;
3655 +               }
3656 +       }
3657 +
3658 +       /* Free the data buffers */
3659 +       for (i = 0; i < fsg_num_buffers; ++i)
3660 +               kfree(fsg->buffhds[i].buf);
3661 +
3662 +       /* Free the request and buffer for endpoint 0 */
3663 +       if (req) {
3664 +               kfree(req->buf);
3665 +               usb_ep_free_request(fsg->ep0, req);
3666 +       }
3667 +
3668 +       set_gadget_data(gadget, NULL);
3669 +}
3670 +
3671 +
3672 +static int __init check_parameters(struct fsg_dev *fsg)
3673 +{
3674 +       int     prot;
3675 +       int     gcnum;
3676 +
3677 +       /* Store the default values */
3678 +       mod_data.transport_type = USB_PR_BULK;
3679 +       mod_data.transport_name = "Bulk-only";
3680 +       mod_data.protocol_type = USB_SC_SCSI;
3681 +       mod_data.protocol_name = "Transparent SCSI";
3682 +
3683 +       /* Some peripheral controllers are known not to be able to
3684 +        * halt bulk endpoints correctly.  If one of them is present,
3685 +        * disable stalls.
3686 +        */
3687 +       if (gadget_is_at91(fsg->gadget))
3688 +               mod_data.can_stall = 0;
3689 +
3690 +       if (mod_data.release == 0xffff) {       // Parameter wasn't set
3691 +               gcnum = usb_gadget_controller_number(fsg->gadget);
3692 +               if (gcnum >= 0)
3693 +                       mod_data.release = 0x0300 + gcnum;
3694 +               else {
3695 +                       WARNING(fsg, "controller '%s' not recognized\n",
3696 +                               fsg->gadget->name);
3697 +                       mod_data.release = 0x0399;
3698 +               }
3699 +       }
3700 +
3701 +       prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
3702 +
3703 +#ifdef CONFIG_USB_FILE_STORAGE_TEST
3704 +       if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
3705 +               ;               // Use default setting
3706 +       } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
3707 +               mod_data.transport_type = USB_PR_CB;
3708 +               mod_data.transport_name = "Control-Bulk";
3709 +       } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
3710 +               mod_data.transport_type = USB_PR_CBI;
3711 +               mod_data.transport_name = "Control-Bulk-Interrupt";
3712 +       } else {
3713 +               ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
3714 +               return -EINVAL;
3715 +       }
3716 +
3717 +       if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
3718 +                       prot == USB_SC_SCSI) {
3719 +               ;               // Use default setting
3720 +       } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
3721 +                       prot == USB_SC_RBC) {
3722 +               mod_data.protocol_type = USB_SC_RBC;
3723 +               mod_data.protocol_name = "RBC";
3724 +       } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
3725 +                       strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
3726 +                       prot == USB_SC_8020) {
3727 +               mod_data.protocol_type = USB_SC_8020;
3728 +               mod_data.protocol_name = "8020i (ATAPI)";
3729 +       } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
3730 +                       prot == USB_SC_QIC) {
3731 +               mod_data.protocol_type = USB_SC_QIC;
3732 +               mod_data.protocol_name = "QIC-157";
3733 +       } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
3734 +                       prot == USB_SC_UFI) {
3735 +               mod_data.protocol_type = USB_SC_UFI;
3736 +               mod_data.protocol_name = "UFI";
3737 +       } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
3738 +                       prot == USB_SC_8070) {
3739 +               mod_data.protocol_type = USB_SC_8070;
3740 +               mod_data.protocol_name = "8070i";
3741 +       } else {
3742 +               ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
3743 +               return -EINVAL;
3744 +       }
3745 +
3746 +       mod_data.buflen &= PAGE_CACHE_MASK;
3747 +       if (mod_data.buflen <= 0) {
3748 +               ERROR(fsg, "invalid buflen\n");
3749 +               return -ETOOSMALL;
3750 +       }
3751 +
3752 +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
3753 +
3754 +       /* Serial string handling.
3755 +        * On a real device, the serial string would be loaded
3756 +        * from permanent storage. */
3757 +       if (mod_data.serial) {
3758 +               const char *ch;
3759 +               unsigned len = 0;
3760 +
3761 +               /* Sanity check :
3762 +                * The CB[I] specification limits the serial string to
3763 +                * 12 uppercase hexadecimal characters.
3764 +                * BBB need at least 12 uppercase hexadecimal characters,
3765 +                * with a maximum of 126. */
3766 +               for (ch = mod_data.serial; *ch; ++ch) {
3767 +                       ++len;
3768 +                       if ((*ch < '0' || *ch > '9') &&
3769 +                           (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
3770 +                               WARNING(fsg,
3771 +                                       "Invalid serial string character: %c\n",
3772 +                                       *ch);
3773 +                               goto no_serial;
3774 +                       }
3775 +               }
3776 +               if (len > 126 ||
3777 +                   (mod_data.transport_type == USB_PR_BULK && len < 12) ||
3778 +                   (mod_data.transport_type != USB_PR_BULK && len > 12)) {
3779 +                       WARNING(fsg, "Invalid serial string length!\n");
3780 +                       goto no_serial;
3781 +               }
3782 +               fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
3783 +       } else {
3784 +               WARNING(fsg, "No serial-number string provided!\n");
3785 + no_serial:
3786 +               device_desc.iSerialNumber = 0;
3787 +       }
3788 +
3789 +       return 0;
3790 +}
3791 +
3792 +
3793 +static int __init fsg_bind(struct usb_gadget *gadget)
3794 +{
3795 +       struct fsg_dev          *fsg = the_fsg;
3796 +       int                     rc;
3797 +       int                     i;
3798 +       struct fsg_lun          *curlun;
3799 +       struct usb_ep           *ep;
3800 +       struct usb_request      *req;
3801 +       char                    *pathbuf, *p;
3802 +
3803 +       fsg->gadget = gadget;
3804 +       set_gadget_data(gadget, fsg);
3805 +       fsg->ep0 = gadget->ep0;
3806 +       fsg->ep0->driver_data = fsg;
3807 +
3808 +       if ((rc = check_parameters(fsg)) != 0)
3809 +               goto out;
3810 +
3811 +       if (mod_data.removable) {       // Enable the store_xxx attributes
3812 +               dev_attr_file.attr.mode = 0644;
3813 +               dev_attr_file.store = fsg_store_file;
3814 +               if (!mod_data.cdrom) {
3815 +                       dev_attr_ro.attr.mode = 0644;
3816 +                       dev_attr_ro.store = fsg_store_ro;
3817 +               }
3818 +       }
3819 +
3820 +       /* Only for removable media? */
3821 +       dev_attr_nofua.attr.mode = 0644;
3822 +       dev_attr_nofua.store = fsg_store_nofua;
3823 +
3824 +       /* Find out how many LUNs there should be */
3825 +       i = mod_data.nluns;
3826 +       if (i == 0)
3827 +               i = max(mod_data.num_filenames, 1u);
3828 +       if (i > FSG_MAX_LUNS) {
3829 +               ERROR(fsg, "invalid number of LUNs: %d\n", i);
3830 +               rc = -EINVAL;
3831 +               goto out;
3832 +       }
3833 +
3834 +       /* Create the LUNs, open their backing files, and register the
3835 +        * LUN devices in sysfs. */
3836 +       fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
3837 +       if (!fsg->luns) {
3838 +               rc = -ENOMEM;
3839 +               goto out;
3840 +       }
3841 +       fsg->nluns = i;
3842 +
3843 +       for (i = 0; i < fsg->nluns; ++i) {
3844 +               curlun = &fsg->luns[i];
3845 +               curlun->cdrom = !!mod_data.cdrom;
3846 +               curlun->ro = mod_data.cdrom || mod_data.ro[i];
3847 +               curlun->initially_ro = curlun->ro;
3848 +               curlun->removable = mod_data.removable;
3849 +               curlun->nofua = mod_data.nofua[i];
3850 +               curlun->dev.release = lun_release;
3851 +               curlun->dev.parent = &gadget->dev;
3852 +               curlun->dev.driver = &fsg_driver.driver;
3853 +               dev_set_drvdata(&curlun->dev, &fsg->filesem);
3854 +               dev_set_name(&curlun->dev,"%s-lun%d",
3855 +                            dev_name(&gadget->dev), i);
3856 +
3857 +               kref_get(&fsg->ref);
3858 +               rc = device_register(&curlun->dev);
3859 +               if (rc) {
3860 +                       INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
3861 +                       put_device(&curlun->dev);
3862 +                       goto out;
3863 +               }
3864 +               curlun->registered = 1;
3865 +
3866 +               rc = device_create_file(&curlun->dev, &dev_attr_ro);
3867 +               if (rc)
3868 +                       goto out;
3869 +               rc = device_create_file(&curlun->dev, &dev_attr_nofua);
3870 +               if (rc)
3871 +                       goto out;
3872 +               rc = device_create_file(&curlun->dev, &dev_attr_file);
3873 +               if (rc)
3874 +                       goto out;
3875 +
3876 +               if (mod_data.file[i] && *mod_data.file[i]) {
3877 +                       rc = fsg_lun_open(curlun, mod_data.file[i]);
3878 +                       if (rc)
3879 +                               goto out;
3880 +               } else if (!mod_data.removable) {
3881 +                       ERROR(fsg, "no file given for LUN%d\n", i);
3882 +                       rc = -EINVAL;
3883 +                       goto out;
3884 +               }
3885 +       }
3886 +
3887 +       /* Find all the endpoints we will use */
3888 +       usb_ep_autoconfig_reset(gadget);
3889 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
3890 +       if (!ep)
3891 +               goto autoconf_fail;
3892 +       ep->driver_data = fsg;          // claim the endpoint
3893 +       fsg->bulk_in = ep;
3894 +
3895 +       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
3896 +       if (!ep)
3897 +               goto autoconf_fail;
3898 +       ep->driver_data = fsg;          // claim the endpoint
3899 +       fsg->bulk_out = ep;
3900 +
3901 +       if (transport_is_cbi()) {
3902 +               ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
3903 +               if (!ep)
3904 +                       goto autoconf_fail;
3905 +               ep->driver_data = fsg;          // claim the endpoint
3906 +               fsg->intr_in = ep;
3907 +       }
3908 +
3909 +       /* Fix up the descriptors */
3910 +       device_desc.idVendor = cpu_to_le16(mod_data.vendor);
3911 +       device_desc.idProduct = cpu_to_le16(mod_data.product);
3912 +       device_desc.bcdDevice = cpu_to_le16(mod_data.release);
3913 +
3914 +       i = (transport_is_cbi() ? 3 : 2);       // Number of endpoints
3915 +       fsg_intf_desc.bNumEndpoints = i;
3916 +       fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
3917 +       fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
3918 +       fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3919 +
3920 +       if (gadget_is_dualspeed(gadget)) {
3921 +               fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3922 +
3923 +               /* Assume endpoint addresses are the same for both speeds */
3924 +               fsg_hs_bulk_in_desc.bEndpointAddress =
3925 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3926 +               fsg_hs_bulk_out_desc.bEndpointAddress =
3927 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3928 +               fsg_hs_intr_in_desc.bEndpointAddress =
3929 +                       fsg_fs_intr_in_desc.bEndpointAddress;
3930 +       }
3931 +
3932 +       if (gadget_is_superspeed(gadget)) {
3933 +               unsigned                max_burst;
3934 +
3935 +               fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
3936 +
3937 +               /* Calculate bMaxBurst, we know packet size is 1024 */
3938 +               max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
3939 +
3940 +               /* Assume endpoint addresses are the same for both speeds */
3941 +               fsg_ss_bulk_in_desc.bEndpointAddress =
3942 +                       fsg_fs_bulk_in_desc.bEndpointAddress;
3943 +               fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
3944 +
3945 +               fsg_ss_bulk_out_desc.bEndpointAddress =
3946 +                       fsg_fs_bulk_out_desc.bEndpointAddress;
3947 +               fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
3948 +       }
3949 +
3950 +       if (gadget_is_otg(gadget))
3951 +               fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
3952 +
3953 +       rc = -ENOMEM;
3954 +
3955 +       /* Allocate the request and buffer for endpoint 0 */
3956 +       fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
3957 +       if (!req)
3958 +               goto out;
3959 +       req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
3960 +       if (!req->buf)
3961 +               goto out;
3962 +       req->complete = ep0_complete;
3963 +
3964 +       /* Allocate the data buffers */
3965 +       for (i = 0; i < fsg_num_buffers; ++i) {
3966 +               struct fsg_buffhd       *bh = &fsg->buffhds[i];
3967 +
3968 +               /* Allocate for the bulk-in endpoint.  We assume that
3969 +                * the buffer will also work with the bulk-out (and
3970 +                * interrupt-in) endpoint. */
3971 +               bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
3972 +               if (!bh->buf)
3973 +                       goto out;
3974 +               bh->next = bh + 1;
3975 +       }
3976 +       fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
3977 +
3978 +       /* This should reflect the actual gadget power source */
3979 +       usb_gadget_set_selfpowered(gadget);
3980 +
3981 +       snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
3982 +                       "%s %s with %s",
3983 +                       init_utsname()->sysname, init_utsname()->release,
3984 +                       gadget->name);
3985 +
3986 +       fsg->thread_task = kthread_create(fsg_main_thread, fsg,
3987 +                       "file-storage-gadget");
3988 +       if (IS_ERR(fsg->thread_task)) {
3989 +               rc = PTR_ERR(fsg->thread_task);
3990 +               goto out;
3991 +       }
3992 +
3993 +       INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
3994 +       INFO(fsg, "NOTE: This driver is deprecated.  "
3995 +                       "Consider using g_mass_storage instead.\n");
3996 +       INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
3997 +
3998 +       pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
3999 +       for (i = 0; i < fsg->nluns; ++i) {
4000 +               curlun = &fsg->luns[i];
4001 +               if (fsg_lun_is_open(curlun)) {
4002 +                       p = NULL;
4003 +                       if (pathbuf) {
4004 +                               p = d_path(&curlun->filp->f_path,
4005 +                                          pathbuf, PATH_MAX);
4006 +                               if (IS_ERR(p))
4007 +                                       p = NULL;
4008 +                       }
4009 +                       LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
4010 +                             curlun->ro, curlun->nofua, (p ? p : "(error)"));
4011 +               }
4012 +       }
4013 +       kfree(pathbuf);
4014 +
4015 +       DBG(fsg, "transport=%s (x%02x)\n",
4016 +                       mod_data.transport_name, mod_data.transport_type);
4017 +       DBG(fsg, "protocol=%s (x%02x)\n",
4018 +                       mod_data.protocol_name, mod_data.protocol_type);
4019 +       DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
4020 +                       mod_data.vendor, mod_data.product, mod_data.release);
4021 +       DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
4022 +                       mod_data.removable, mod_data.can_stall,
4023 +                       mod_data.cdrom, mod_data.buflen);
4024 +       DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
4025 +
4026 +       set_bit(REGISTERED, &fsg->atomic_bitflags);
4027 +
4028 +       /* Tell the thread to start working */
4029 +       wake_up_process(fsg->thread_task);
4030 +       return 0;
4031 +
4032 +autoconf_fail:
4033 +       ERROR(fsg, "unable to autoconfigure all endpoints\n");
4034 +       rc = -ENOTSUPP;
4035 +
4036 +out:
4037 +       fsg->state = FSG_STATE_TERMINATED;      // The thread is dead
4038 +       fsg_unbind(gadget);
4039 +       complete(&fsg->thread_notifier);
4040 +       return rc;
4041 +}
4042 +
4043 +
4044 +/*-------------------------------------------------------------------------*/
4045 +
4046 +static void fsg_suspend(struct usb_gadget *gadget)
4047 +{
4048 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4049 +
4050 +       DBG(fsg, "suspend\n");
4051 +       set_bit(SUSPENDED, &fsg->atomic_bitflags);
4052 +}
4053 +
4054 +static void fsg_resume(struct usb_gadget *gadget)
4055 +{
4056 +       struct fsg_dev          *fsg = get_gadget_data(gadget);
4057 +
4058 +       DBG(fsg, "resume\n");
4059 +       clear_bit(SUSPENDED, &fsg->atomic_bitflags);
4060 +}
4061 +
4062 +
4063 +/*-------------------------------------------------------------------------*/
4064 +
4065 +static struct usb_gadget_driver                fsg_driver = {
4066 +       .max_speed      = USB_SPEED_SUPER,
4067 +       .function       = (char *) fsg_string_product,
4068 +       .unbind         = fsg_unbind,
4069 +       .disconnect     = fsg_disconnect,
4070 +       .setup          = fsg_setup,
4071 +       .suspend        = fsg_suspend,
4072 +       .resume         = fsg_resume,
4073 +
4074 +       .driver         = {
4075 +               .name           = DRIVER_NAME,
4076 +               .owner          = THIS_MODULE,
4077 +               // .release = ...
4078 +               // .suspend = ...
4079 +               // .resume = ...
4080 +       },
4081 +};
4082 +
4083 +
4084 +static int __init fsg_alloc(void)
4085 +{
4086 +       struct fsg_dev          *fsg;
4087 +
4088 +       fsg = kzalloc(sizeof *fsg +
4089 +                     fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
4090 +
4091 +       if (!fsg)
4092 +               return -ENOMEM;
4093 +       spin_lock_init(&fsg->lock);
4094 +       init_rwsem(&fsg->filesem);
4095 +       kref_init(&fsg->ref);
4096 +       init_completion(&fsg->thread_notifier);
4097 +
4098 +       the_fsg = fsg;
4099 +       return 0;
4100 +}
4101 +
4102 +
4103 +static int __init fsg_init(void)
4104 +{
4105 +       int             rc;
4106 +       struct fsg_dev  *fsg;
4107 +
4108 +       rc = fsg_num_buffers_validate();
4109 +       if (rc != 0)
4110 +               return rc;
4111 +
4112 +       if ((rc = fsg_alloc()) != 0)
4113 +               return rc;
4114 +       fsg = the_fsg;
4115 +       if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
4116 +               kref_put(&fsg->ref, fsg_release);
4117 +       return rc;
4118 +}
4119 +module_init(fsg_init);
4120 +
4121 +
4122 +static void __exit fsg_cleanup(void)
4123 +{
4124 +       struct fsg_dev  *fsg = the_fsg;
4125 +
4126 +       /* Unregister the driver iff the thread hasn't already done so */
4127 +       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
4128 +               usb_gadget_unregister_driver(&fsg_driver);
4129 +
4130 +       /* Wait for the thread to finish up */
4131 +       wait_for_completion(&fsg->thread_notifier);
4132 +
4133 +       kref_put(&fsg->ref, fsg_release);
4134 +}
4135 +module_exit(fsg_cleanup);
4136 --- a/drivers/usb/host/Kconfig
4137 +++ b/drivers/usb/host/Kconfig
4138 @@ -689,6 +689,19 @@ config USB_HWA_HCD
4139           To compile this driver a module, choose M here: the module
4140           will be called "hwa-hc".
4141  
4142 +config USB_DWCOTG
4143 +       tristate "Synopsis DWC host support"
4144 +       depends on USB
4145 +       help
4146 +         The Synopsis DWC controller is a dual-role
4147 +         host/peripheral/OTG ("On The Go") USB controllers.
4148 +
4149 +         Enable this option to support this IP in host controller mode.
4150 +         If unsure, say N.
4151 +
4152 +         To compile this driver as a module, choose M here: the
4153 +         modules built will be called dwc_otg and dwc_common_port.
4154 +
4155  config USB_IMX21_HCD
4156         tristate "i.MX21 HCD support"
4157         depends on ARM && ARCH_MXC
4158 --- a/drivers/usb/host/Makefile
4159 +++ b/drivers/usb/host/Makefile
4160 @@ -63,6 +63,8 @@ obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
4161  obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
4162  obj-$(CONFIG_USB_ISP1760_HCD)  += isp1760.o
4163  obj-$(CONFIG_USB_HWA_HCD)      += hwa-hc.o
4164 +
4165 +obj-$(CONFIG_USB_DWCOTG)        += dwc_otg/ dwc_common_port/
4166  obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
4167  obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
4168  obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
4169 --- /dev/null
4170 +++ b/drivers/usb/host/dwc_common_port/Makefile
4171 @@ -0,0 +1,58 @@
4172 +#
4173 +# Makefile for DWC_common library
4174 +#
4175 +
4176 +ifneq ($(KERNELRELEASE),)
4177 +
4178 +ccflags-y      += -DDWC_LINUX
4179 +#ccflags-y     += -DDEBUG
4180 +#ccflags-y     += -DDWC_DEBUG_REGS
4181 +#ccflags-y     += -DDWC_DEBUG_MEMORY
4182 +
4183 +ccflags-y      += -DDWC_LIBMODULE
4184 +ccflags-y      += -DDWC_CCLIB
4185 +#ccflags-y     += -DDWC_CRYPTOLIB
4186 +ccflags-y      += -DDWC_NOTIFYLIB
4187 +ccflags-y      += -DDWC_UTFLIB
4188 +
4189 +obj-$(CONFIG_USB_DWCOTG)       += dwc_common_port_lib.o
4190 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4191 +                           dwc_crypto.o dwc_notifier.o \
4192 +                           dwc_common_linux.o dwc_mem.o
4193 +
4194 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
4195 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
4196 +
4197 +ifneq ($(kernrel3),2.6.20)
4198 +# grayg - I only know that we use ccflags-y in 2.6.31 actually
4199 +ccflags-y += $(CPPFLAGS)
4200 +endif
4201 +
4202 +else
4203 +
4204 +#ifeq ($(KDIR),)
4205 +#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4206 +#endif
4207 +
4208 +ifeq ($(ARCH),)
4209 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4210 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4211 +endif
4212 +
4213 +ifeq ($(DOXYGEN),)
4214 +DOXYGEN                := doxygen
4215 +endif
4216 +
4217 +default:
4218 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4219 +
4220 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4221 +       $(DOXYGEN) doc/doxygen.cfg
4222 +
4223 +tags:  $(wildcard *.[hc])
4224 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4225 +
4226 +endif
4227 +
4228 +clean:
4229 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4230 --- /dev/null
4231 +++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd
4232 @@ -0,0 +1,17 @@
4233 +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
4234 +CFLAGS += -DDWC_FREEBSD
4235 +CFLAGS += -DDEBUG
4236 +#CFLAGS        += -DDWC_DEBUG_REGS
4237 +#CFLAGS        += -DDWC_DEBUG_MEMORY
4238 +
4239 +#CFLAGS        += -DDWC_LIBMODULE
4240 +#CFLAGS        += -DDWC_CCLIB
4241 +#CFLAGS        += -DDWC_CRYPTOLIB
4242 +#CFLAGS        += -DDWC_NOTIFYLIB
4243 +#CFLAGS        += -DDWC_UTFLIB
4244 +
4245 +KMOD = dwc_common_port_lib
4246 +SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \
4247 +       dwc_common_fbsd.c dwc_mem.c
4248 +
4249 +.include <bsd.kmod.mk>
4250 --- /dev/null
4251 +++ b/drivers/usb/host/dwc_common_port/Makefile.linux
4252 @@ -0,0 +1,49 @@
4253 +#
4254 +# Makefile for DWC_common library
4255 +#
4256 +ifneq ($(KERNELRELEASE),)
4257 +
4258 +ccflags-y      += -DDWC_LINUX
4259 +#ccflags-y     += -DDEBUG
4260 +#ccflags-y     += -DDWC_DEBUG_REGS
4261 +#ccflags-y     += -DDWC_DEBUG_MEMORY
4262 +
4263 +ccflags-y      += -DDWC_LIBMODULE
4264 +ccflags-y      += -DDWC_CCLIB
4265 +ccflags-y      += -DDWC_CRYPTOLIB
4266 +ccflags-y      += -DDWC_NOTIFYLIB
4267 +ccflags-y      += -DDWC_UTFLIB
4268 +
4269 +obj-m                   := dwc_common_port_lib.o
4270 +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
4271 +                           dwc_crypto.o dwc_notifier.o \
4272 +                           dwc_common_linux.o dwc_mem.o
4273 +
4274 +else
4275 +
4276 +ifeq ($(KDIR),)
4277 +$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
4278 +endif
4279 +
4280 +ifeq ($(ARCH),)
4281 +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
4282 + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
4283 +endif
4284 +
4285 +ifeq ($(DOXYGEN),)
4286 +DOXYGEN                := doxygen
4287 +endif
4288 +
4289 +default:
4290 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
4291 +
4292 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
4293 +       $(DOXYGEN) doc/doxygen.cfg
4294 +
4295 +tags:  $(wildcard *.[hc])
4296 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
4297 +
4298 +endif
4299 +
4300 +clean:
4301 +       rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
4302 --- /dev/null
4303 +++ b/drivers/usb/host/dwc_common_port/changes.txt
4304 @@ -0,0 +1,174 @@
4305 +
4306 +dwc_read_reg32() and friends now take an additional parameter, a pointer to an
4307 +IO context struct. The IO context struct should live in an os-dependent struct
4308 +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct
4309 +named 'os_dep' embedded in the main device struct. So there these calls look
4310 +like this:
4311 +
4312 +       dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);
4313 +
4314 +       dwc_write_reg32(&usb3_dev->os_dep.ioctx,
4315 +                       &pcd->dev_global_regs->dcfg, 0);
4316 +
4317 +Note that for the existing Linux driver ports, it is not necessary to actually
4318 +define the 'ioctx' member in the os-dependent struct. Since Linux does not
4319 +require an IO context, its macros for dwc_read_reg32() and friends do not
4320 +use the context pointer, so it is optimized away by the compiler. But it is
4321 +necessary to add the pointer parameter to all of the call sites, to be ready
4322 +for any future ports (such as FreeBSD) which do require an IO context.
4323 +
4324 +
4325 +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now
4326 +take an additional parameter, a pointer to a memory context. Examples:
4327 +
4328 +       addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);
4329 +
4330 +       dwc_free(&usb3_dev->os_dep.memctx, addr);
4331 +
4332 +Again, for the Linux ports, it is not necessary to actually define the memctx
4333 +member, but it is necessary to add the pointer parameter to all of the call
4334 +sites.
4335 +
4336 +
4337 +Same for dwc_dma_alloc() and dwc_dma_free(). Examples:
4338 +
4339 +       virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);
4340 +
4341 +       dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);
4342 +
4343 +
4344 +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:
4345 +
4346 +       mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);
4347 +
4348 +       dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);
4349 +
4350 +
4351 +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:
4352 +
4353 +       lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);
4354 +
4355 +       dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);
4356 +
4357 +
4358 +Same for dwc_timer_alloc(). Example:
4359 +
4360 +       timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",
4361 +                               cb_func, cb_data);
4362 +
4363 +
4364 +Same for dwc_waitq_alloc(). Example:
4365 +
4366 +       waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);
4367 +
4368 +
4369 +Same for dwc_thread_run(). Example:
4370 +
4371 +       thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,
4372 +                               "dwc_usb3_thd1", data);
4373 +
4374 +
4375 +Same for dwc_workq_alloc(). Example:
4376 +
4377 +       workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");
4378 +
4379 +
4380 +Same for dwc_task_alloc(). Example:
4381 +
4382 +       task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",
4383 +                             cb_func, cb_data);
4384 +
4385 +
4386 +In addition to the context pointer additions, a few core functions have had
4387 +other changes made to their parameters:
4388 +
4389 +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()
4390 +has been changed from a uint64_t to a dwc_irqflags_t.
4391 +
4392 +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the
4393 +FreeBSD equivalent of that function requires it.
4394 +
4395 +And, in addition to the context pointer, dwc_task_alloc() also adds a
4396 +'char *name' parameter, to be consistent with dwc_thread_run() and
4397 +dwc_workq_alloc(), and because the FreeBSD equivalent of that function
4398 +requires a unique name.
4399 +
4400 +
4401 +Here is a complete list of the core functions that now take a pointer to a
4402 +context as their first parameter:
4403 +
4404 +       dwc_read_reg32
4405 +       dwc_read_reg64
4406 +       dwc_write_reg32
4407 +       dwc_write_reg64
4408 +       dwc_modify_reg32
4409 +       dwc_modify_reg64
4410 +       dwc_alloc
4411 +       dwc_alloc_atomic
4412 +       dwc_strdup
4413 +       dwc_free
4414 +       dwc_dma_alloc
4415 +       dwc_dma_free
4416 +       dwc_mutex_alloc
4417 +       dwc_mutex_free
4418 +       dwc_spinlock_alloc
4419 +       dwc_spinlock_free
4420 +       dwc_timer_alloc
4421 +       dwc_waitq_alloc
4422 +       dwc_thread_run
4423 +       dwc_workq_alloc
4424 +       dwc_task_alloc     Also adds a 'char *name' as its 2nd parameter
4425 +
4426 +And here are the core functions that have other changes to their parameters:
4427 +
4428 +       dwc_spinlock_irqsave      'flags' param is now a 'dwc_irqflags_t *'
4429 +       dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'
4430 +       dwc_thread_should_stop    Adds a 'dwc_thread_t *' parameter
4431 +
4432 +
4433 +
4434 +The changes to the core functions also require some of the other library
4435 +functions to change:
4436 +
4437 +       dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'
4438 +       (for memory allocation) as the 1st param and a 'void *mtxctx'
4439 +       (for mutex allocation) as the 2nd param.
4440 +
4441 +       dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),
4442 +       dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a
4443 +       'void *memctx' as the 1st param.
4444 +
4445 +       dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a
4446 +       'void *memctx' as the 1st param.
4447 +
4448 +       dwc_modpow() now takes a 'void *memctx' as the 1st param.
4449 +
4450 +       dwc_alloc_notification_manager() now takes a 'void *memctx' as the
4451 +       1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd
4452 +       param, and also now returns an integer value that is non-zero if
4453 +       allocation of its data structures or work queue fails.
4454 +
4455 +       dwc_register_notifier() now takes a 'void *memctx' as the 1st param.
4456 +
4457 +       dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first
4458 +       param, and also now returns an integer value that is non-zero if
4459 +       allocation of its data structures fails.
4460 +
4461 +
4462 +
4463 +Other miscellaneous changes:
4464 +
4465 +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to
4466 +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.
4467 +
4468 +The following #define's have been added to allow selectively compiling library
4469 +features:
4470 +
4471 +       DWC_CCLIB
4472 +       DWC_CRYPTOLIB
4473 +       DWC_NOTIFYLIB
4474 +       DWC_UTFLIB
4475 +
4476 +A DWC_LIBMODULE #define has also been added. If this is not defined, then the
4477 +module code in dwc_common_linux.c is not compiled in. This allows linking the
4478 +library code directly into a driver module, instead of as a standalone module.
4479 --- /dev/null
4480 +++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
4481 @@ -0,0 +1,270 @@
4482 +# Doxyfile 1.4.5
4483 +
4484 +#---------------------------------------------------------------------------
4485 +# Project related configuration options
4486 +#---------------------------------------------------------------------------
4487 +PROJECT_NAME           = "Synopsys DWC Portability and Common Library for UWB"
4488 +PROJECT_NUMBER         =
4489 +OUTPUT_DIRECTORY       = doc
4490 +CREATE_SUBDIRS         = NO
4491 +OUTPUT_LANGUAGE        = English
4492 +BRIEF_MEMBER_DESC      = YES
4493 +REPEAT_BRIEF           = YES
4494 +ABBREVIATE_BRIEF       = "The $name class" \
4495 +                         "The $name widget" \
4496 +                         "The $name file" \
4497 +                         is \
4498 +                         provides \
4499 +                         specifies \
4500 +                         contains \
4501 +                         represents \
4502 +                         a \
4503 +                         an \
4504 +                         the
4505 +ALWAYS_DETAILED_SEC    = YES
4506 +INLINE_INHERITED_MEMB  = NO
4507 +FULL_PATH_NAMES        = NO
4508 +STRIP_FROM_PATH        = ..
4509 +STRIP_FROM_INC_PATH    =
4510 +SHORT_NAMES            = NO
4511 +JAVADOC_AUTOBRIEF      = YES
4512 +MULTILINE_CPP_IS_BRIEF = NO
4513 +DETAILS_AT_TOP         = YES
4514 +INHERIT_DOCS           = YES
4515 +SEPARATE_MEMBER_PAGES  = NO
4516 +TAB_SIZE               = 8
4517 +ALIASES                =
4518 +OPTIMIZE_OUTPUT_FOR_C  = YES
4519 +OPTIMIZE_OUTPUT_JAVA   = NO
4520 +BUILTIN_STL_SUPPORT    = NO
4521 +DISTRIBUTE_GROUP_DOC   = NO
4522 +SUBGROUPING            = NO
4523 +#---------------------------------------------------------------------------
4524 +# Build related configuration options
4525 +#---------------------------------------------------------------------------
4526 +EXTRACT_ALL            = NO
4527 +EXTRACT_PRIVATE        = NO
4528 +EXTRACT_STATIC         = YES
4529 +EXTRACT_LOCAL_CLASSES  = NO
4530 +EXTRACT_LOCAL_METHODS  = NO
4531 +HIDE_UNDOC_MEMBERS     = NO
4532 +HIDE_UNDOC_CLASSES     = NO
4533 +HIDE_FRIEND_COMPOUNDS  = NO
4534 +HIDE_IN_BODY_DOCS      = NO
4535 +INTERNAL_DOCS          = NO
4536 +CASE_SENSE_NAMES       = YES
4537 +HIDE_SCOPE_NAMES       = NO
4538 +SHOW_INCLUDE_FILES     = NO
4539 +INLINE_INFO            = YES
4540 +SORT_MEMBER_DOCS       = NO
4541 +SORT_BRIEF_DOCS        = NO
4542 +SORT_BY_SCOPE_NAME     = NO
4543 +GENERATE_TODOLIST      = YES
4544 +GENERATE_TESTLIST      = YES
4545 +GENERATE_BUGLIST       = YES
4546 +GENERATE_DEPRECATEDLIST= YES
4547 +ENABLED_SECTIONS       =
4548 +MAX_INITIALIZER_LINES  = 30
4549 +SHOW_USED_FILES        = YES
4550 +SHOW_DIRECTORIES       = YES
4551 +FILE_VERSION_FILTER    =
4552 +#---------------------------------------------------------------------------
4553 +# configuration options related to warning and progress messages
4554 +#---------------------------------------------------------------------------
4555 +QUIET                  = YES
4556 +WARNINGS               = YES
4557 +WARN_IF_UNDOCUMENTED   = NO
4558 +WARN_IF_DOC_ERROR      = YES
4559 +WARN_NO_PARAMDOC       = YES
4560 +WARN_FORMAT            = "$file:$line: $text"
4561 +WARN_LOGFILE           =
4562 +#---------------------------------------------------------------------------
4563 +# configuration options related to the input files
4564 +#---------------------------------------------------------------------------
4565 +INPUT                  = .
4566 +FILE_PATTERNS          = *.c \
4567 +                         *.cc \
4568 +                         *.cxx \
4569 +                         *.cpp \
4570 +                         *.c++ \
4571 +                         *.d \
4572 +                         *.java \
4573 +                         *.ii \
4574 +                         *.ixx \
4575 +                         *.ipp \
4576 +                         *.i++ \
4577 +                         *.inl \
4578 +                         *.h \
4579 +                         *.hh \
4580 +                         *.hxx \
4581 +                         *.hpp \
4582 +                         *.h++ \
4583 +                         *.idl \
4584 +                         *.odl \
4585 +                         *.cs \
4586 +                         *.php \
4587 +                         *.php3 \
4588 +                         *.inc \
4589 +                         *.m \
4590 +                         *.mm \
4591 +                         *.dox \
4592 +                         *.py \
4593 +                         *.C \
4594 +                         *.CC \
4595 +                         *.C++ \
4596 +                         *.II \
4597 +                         *.I++ \
4598 +                         *.H \
4599 +                         *.HH \
4600 +                         *.H++ \
4601 +                         *.CS \
4602 +                         *.PHP \
4603 +                         *.PHP3 \
4604 +                         *.M \
4605 +                         *.MM \
4606 +                         *.PY
4607 +RECURSIVE              = NO
4608 +EXCLUDE                =
4609 +EXCLUDE_SYMLINKS       = NO
4610 +EXCLUDE_PATTERNS       =
4611 +EXAMPLE_PATH           =
4612 +EXAMPLE_PATTERNS       = *
4613 +EXAMPLE_RECURSIVE      = NO
4614 +IMAGE_PATH             =
4615 +INPUT_FILTER           =
4616 +FILTER_PATTERNS        =
4617 +FILTER_SOURCE_FILES    = NO
4618 +#---------------------------------------------------------------------------
4619 +# configuration options related to source browsing
4620 +#---------------------------------------------------------------------------
4621 +SOURCE_BROWSER         = NO
4622 +INLINE_SOURCES         = NO
4623 +STRIP_CODE_COMMENTS    = YES
4624 +REFERENCED_BY_RELATION = YES
4625 +REFERENCES_RELATION    = YES
4626 +USE_HTAGS              = NO
4627 +VERBATIM_HEADERS       = NO
4628 +#---------------------------------------------------------------------------
4629 +# configuration options related to the alphabetical class index
4630 +#---------------------------------------------------------------------------
4631 +ALPHABETICAL_INDEX     = NO
4632 +COLS_IN_ALPHA_INDEX    = 5
4633 +IGNORE_PREFIX          =
4634 +#---------------------------------------------------------------------------
4635 +# configuration options related to the HTML output
4636 +#---------------------------------------------------------------------------
4637 +GENERATE_HTML          = YES
4638 +HTML_OUTPUT            = html
4639 +HTML_FILE_EXTENSION    = .html
4640 +HTML_HEADER            =
4641 +HTML_FOOTER            =
4642 +HTML_STYLESHEET        =
4643 +HTML_ALIGN_MEMBERS     = YES
4644 +GENERATE_HTMLHELP      = NO
4645 +CHM_FILE               =
4646 +HHC_LOCATION           =
4647 +GENERATE_CHI           = NO
4648 +BINARY_TOC             = NO
4649 +TOC_EXPAND             = NO
4650 +DISABLE_INDEX          = NO
4651 +ENUM_VALUES_PER_LINE   = 4
4652 +GENERATE_TREEVIEW      = YES
4653 +TREEVIEW_WIDTH         = 250
4654 +#---------------------------------------------------------------------------
4655 +# configuration options related to the LaTeX output
4656 +#---------------------------------------------------------------------------
4657 +GENERATE_LATEX         = NO
4658 +LATEX_OUTPUT           = latex
4659 +LATEX_CMD_NAME         = latex
4660 +MAKEINDEX_CMD_NAME     = makeindex
4661 +COMPACT_LATEX          = NO
4662 +PAPER_TYPE             = a4wide
4663 +EXTRA_PACKAGES         =
4664 +LATEX_HEADER           =
4665 +PDF_HYPERLINKS         = NO
4666 +USE_PDFLATEX           = NO
4667 +LATEX_BATCHMODE        = NO
4668 +LATEX_HIDE_INDICES     = NO
4669 +#---------------------------------------------------------------------------
4670 +# configuration options related to the RTF output
4671 +#---------------------------------------------------------------------------
4672 +GENERATE_RTF           = NO
4673 +RTF_OUTPUT             = rtf
4674 +COMPACT_RTF            = NO
4675 +RTF_HYPERLINKS         = NO
4676 +RTF_STYLESHEET_FILE    =
4677 +RTF_EXTENSIONS_FILE    =
4678 +#---------------------------------------------------------------------------
4679 +# configuration options related to the man page output
4680 +#---------------------------------------------------------------------------
4681 +GENERATE_MAN           = NO
4682 +MAN_OUTPUT             = man
4683 +MAN_EXTENSION          = .3
4684 +MAN_LINKS              = NO
4685 +#---------------------------------------------------------------------------
4686 +# configuration options related to the XML output
4687 +#---------------------------------------------------------------------------
4688 +GENERATE_XML           = NO
4689 +XML_OUTPUT             = xml
4690 +XML_SCHEMA             =
4691 +XML_DTD                =
4692 +XML_PROGRAMLISTING     = YES
4693 +#---------------------------------------------------------------------------
4694 +# configuration options for the AutoGen Definitions output
4695 +#---------------------------------------------------------------------------
4696 +GENERATE_AUTOGEN_DEF   = NO
4697 +#---------------------------------------------------------------------------
4698 +# configuration options related to the Perl module output
4699 +#---------------------------------------------------------------------------
4700 +GENERATE_PERLMOD       = NO
4701 +PERLMOD_LATEX          = NO
4702 +PERLMOD_PRETTY         = YES
4703 +PERLMOD_MAKEVAR_PREFIX =
4704 +#---------------------------------------------------------------------------
4705 +# Configuration options related to the preprocessor
4706 +#---------------------------------------------------------------------------
4707 +ENABLE_PREPROCESSING   = YES
4708 +MACRO_EXPANSION        = NO
4709 +EXPAND_ONLY_PREDEF     = NO
4710 +SEARCH_INCLUDES        = YES
4711 +INCLUDE_PATH           =
4712 +INCLUDE_FILE_PATTERNS  =
4713 +PREDEFINED             = DEBUG DEBUG_MEMORY
4714 +EXPAND_AS_DEFINED      =
4715 +SKIP_FUNCTION_MACROS   = YES
4716 +#---------------------------------------------------------------------------
4717 +# Configuration::additions related to external references
4718 +#---------------------------------------------------------------------------
4719 +TAGFILES               =
4720 +GENERATE_TAGFILE       =
4721 +ALLEXTERNALS           = NO
4722 +EXTERNAL_GROUPS        = YES
4723 +PERL_PATH              = /usr/bin/perl
4724 +#---------------------------------------------------------------------------
4725 +# Configuration options related to the dot tool
4726 +#---------------------------------------------------------------------------
4727 +CLASS_DIAGRAMS         = YES
4728 +HIDE_UNDOC_RELATIONS   = YES
4729 +HAVE_DOT               = NO
4730 +CLASS_GRAPH            = YES
4731 +COLLABORATION_GRAPH    = YES
4732 +GROUP_GRAPHS           = YES
4733 +UML_LOOK               = NO
4734 +TEMPLATE_RELATIONS     = NO
4735 +INCLUDE_GRAPH          = NO
4736 +INCLUDED_BY_GRAPH      = YES
4737 +CALL_GRAPH             = NO
4738 +GRAPHICAL_HIERARCHY    = YES
4739 +DIRECTORY_GRAPH        = YES
4740 +DOT_IMAGE_FORMAT       = png
4741 +DOT_PATH               =
4742 +DOTFILE_DIRS           =
4743 +MAX_DOT_GRAPH_DEPTH    = 1000
4744 +DOT_TRANSPARENT        = NO
4745 +DOT_MULTI_TARGETS      = NO
4746 +GENERATE_LEGEND        = YES
4747 +DOT_CLEANUP            = YES
4748 +#---------------------------------------------------------------------------
4749 +# Configuration::additions related to the search engine
4750 +#---------------------------------------------------------------------------
4751 +SEARCHENGINE           = NO
4752 --- /dev/null
4753 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
4754 @@ -0,0 +1,532 @@
4755 +/* =========================================================================
4756 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
4757 + * $Revision: #4 $
4758 + * $Date: 2010/11/04 $
4759 + * $Change: 1621692 $
4760 + *
4761 + * Synopsys Portability Library Software and documentation
4762 + * (hereinafter, "Software") is an Unsupported proprietary work of
4763 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
4764 + * between Synopsys and you.
4765 + *
4766 + * The Software IS NOT an item of Licensed Software or Licensed Product
4767 + * under any End User Software License Agreement or Agreement for
4768 + * Licensed Product with Synopsys or any supplement thereto. You are
4769 + * permitted to use and redistribute this Software in source and binary
4770 + * forms, with or without modification, provided that redistributions
4771 + * of source code must retain this notice. You may not view, use,
4772 + * disclose, copy or distribute this file or any information contained
4773 + * herein except pursuant to this license grant from Synopsys. If you
4774 + * do not agree with this notice, including the disclaimer below, then
4775 + * you are not authorized to use the Software.
4776 + *
4777 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4778 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4779 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
4780 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
4781 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4782 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4783 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4784 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
4785 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4786 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
4787 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
4788 + * DAMAGE.
4789 + * ========================================================================= */
4790 +#ifdef DWC_CCLIB
4791 +
4792 +#include "dwc_cc.h"
4793 +
4794 +typedef struct dwc_cc
4795 +{
4796 +       uint32_t uid;
4797 +       uint8_t chid[16];
4798 +       uint8_t cdid[16];
4799 +       uint8_t ck[16];
4800 +       uint8_t *name;
4801 +       uint8_t length;
4802 +        DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
4803 +} dwc_cc_t;
4804 +
4805 +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
4806 +
4807 +/** The main structure for CC management.  */
4808 +struct dwc_cc_if
4809 +{
4810 +       dwc_mutex_t *mutex;
4811 +       char *filename;
4812 +
4813 +       unsigned is_host:1;
4814 +
4815 +       dwc_notifier_t *notifier;
4816 +
4817 +       struct context_list list;
4818 +};
4819 +
4820 +#ifdef DEBUG
4821 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
4822 +{
4823 +       int i;
4824 +       DWC_PRINTF("%s: ", name);
4825 +       for (i=0; i<len; i++) {
4826 +               DWC_PRINTF("%02x ", bytes[i]);
4827 +       }
4828 +       DWC_PRINTF("\n");
4829 +}
4830 +#else
4831 +#define dump_bytes(x...)
4832 +#endif
4833 +
4834 +static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
4835 +{
4836 +       dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
4837 +       if (!cc) {
4838 +               return NULL;
4839 +       }
4840 +       DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
4841 +
4842 +       if (name) {
4843 +               cc->length = length;
4844 +               cc->name = dwc_alloc(mem_ctx, length);
4845 +               if (!cc->name) {
4846 +                       dwc_free(mem_ctx, cc);
4847 +                       return NULL;
4848 +               }
4849 +
4850 +               DWC_MEMCPY(cc->name, name, length);
4851 +       }
4852 +
4853 +       return cc;
4854 +}
4855 +
4856 +static void free_cc(void *mem_ctx, dwc_cc_t *cc)
4857 +{
4858 +       if (cc->name) {
4859 +               dwc_free(mem_ctx, cc->name);
4860 +       }
4861 +       dwc_free(mem_ctx, cc);
4862 +}
4863 +
4864 +static uint32_t next_uid(dwc_cc_if_t *cc_if)
4865 +{
4866 +       uint32_t uid = 0;
4867 +       dwc_cc_t *cc;
4868 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4869 +               if (cc->uid > uid) {
4870 +                       uid = cc->uid;
4871 +               }
4872 +       }
4873 +
4874 +       if (uid == 0) {
4875 +               uid = 255;
4876 +       }
4877 +
4878 +       return uid + 1;
4879 +}
4880 +
4881 +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
4882 +{
4883 +       dwc_cc_t *cc;
4884 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4885 +               if (cc->uid == uid) {
4886 +                       return cc;
4887 +               }
4888 +       }
4889 +       return NULL;
4890 +}
4891 +
4892 +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
4893 +{
4894 +       unsigned int size = 0;
4895 +       dwc_cc_t *cc;
4896 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4897 +               size += (48 + 1);
4898 +               if (cc->name) {
4899 +                       size += cc->length;
4900 +               }
4901 +       }
4902 +       return size;
4903 +}
4904 +
4905 +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
4906 +{
4907 +       uint32_t uid = 0;
4908 +       dwc_cc_t *cc;
4909 +
4910 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4911 +               if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
4912 +                       uid = cc->uid;
4913 +                       break;
4914 +               }
4915 +       }
4916 +       return uid;
4917 +}
4918 +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
4919 +{
4920 +       uint32_t uid = 0;
4921 +       dwc_cc_t *cc;
4922 +
4923 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
4924 +               if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
4925 +                       uid = cc->uid;
4926 +                       break;
4927 +               }
4928 +       }
4929 +       return uid;
4930 +}
4931 +
4932 +/* Internal cc_add */
4933 +static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
4934 +                     uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
4935 +{
4936 +       dwc_cc_t *cc;
4937 +       uint32_t uid;
4938 +
4939 +       if (cc_if->is_host) {
4940 +               uid = cc_match_cdid(cc_if, cdid);
4941 +       }
4942 +       else {
4943 +               uid = cc_match_chid(cc_if, chid);
4944 +       }
4945 +
4946 +       if (uid) {
4947 +               DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
4948 +               cc = cc_find(cc_if, uid);
4949 +       }
4950 +       else {
4951 +               cc = alloc_cc(mem_ctx, name, length);
4952 +               cc->uid = next_uid(cc_if);
4953 +               DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
4954 +       }
4955 +
4956 +       DWC_MEMCPY(&(cc->chid[0]), chid, 16);
4957 +       DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
4958 +       DWC_MEMCPY(&(cc->ck[0]), ck, 16);
4959 +
4960 +       DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
4961 +       dump_bytes("CHID", cc->chid, 16);
4962 +       dump_bytes("CDID", cc->cdid, 16);
4963 +       dump_bytes("CK", cc->ck, 16);
4964 +       return cc->uid;
4965 +}
4966 +
4967 +/* Internal cc_clear */
4968 +static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
4969 +{
4970 +       while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
4971 +               dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
4972 +               DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
4973 +               free_cc(mem_ctx, cc);
4974 +       }
4975 +}
4976 +
4977 +dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
4978 +                            dwc_notifier_t *notifier, unsigned is_host)
4979 +{
4980 +       dwc_cc_if_t *cc_if = NULL;
4981 +
4982 +       /* Allocate a common_cc_if structure */
4983 +       cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
4984 +
4985 +       if (!cc_if)
4986 +               return NULL;
4987 +
4988 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
4989 +       DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
4990 +#else
4991 +       cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
4992 +#endif
4993 +       if (!cc_if->mutex) {
4994 +               dwc_free(mem_ctx, cc_if);
4995 +               return NULL;
4996 +       }
4997 +
4998 +       DWC_CIRCLEQ_INIT(&cc_if->list);
4999 +       cc_if->is_host = is_host;
5000 +       cc_if->notifier = notifier;
5001 +       return cc_if;
5002 +}
5003 +
5004 +void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
5005 +{
5006 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
5007 +       DWC_MUTEX_FREE(cc_if->mutex);
5008 +#else
5009 +       dwc_mutex_free(mtx_ctx, cc_if->mutex);
5010 +#endif
5011 +       cc_clear(mem_ctx, cc_if);
5012 +       dwc_free(mem_ctx, cc_if);
5013 +}
5014 +
5015 +static void cc_changed(dwc_cc_if_t *cc_if)
5016 +{
5017 +       if (cc_if->notifier) {
5018 +               dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
5019 +       }
5020 +}
5021 +
5022 +void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
5023 +{
5024 +       DWC_MUTEX_LOCK(cc_if->mutex);
5025 +       cc_clear(mem_ctx, cc_if);
5026 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5027 +       cc_changed(cc_if);
5028 +}
5029 +
5030 +int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5031 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
5032 +{
5033 +       uint32_t uid;
5034 +
5035 +       DWC_MUTEX_LOCK(cc_if->mutex);
5036 +       uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
5037 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5038 +       cc_changed(cc_if);
5039 +
5040 +       return uid;
5041 +}
5042 +
5043 +void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
5044 +                  uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
5045 +{
5046 +       dwc_cc_t* cc;
5047 +
5048 +       DWC_DEBUGC("Change connection context %d", id);
5049 +
5050 +       DWC_MUTEX_LOCK(cc_if->mutex);
5051 +       cc = cc_find(cc_if, id);
5052 +       if (!cc) {
5053 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5054 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5055 +               return;
5056 +       }
5057 +
5058 +       if (chid) {
5059 +               DWC_MEMCPY(&(cc->chid[0]), chid, 16);
5060 +       }
5061 +       if (cdid) {
5062 +               DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
5063 +       }
5064 +       if (ck) {
5065 +               DWC_MEMCPY(&(cc->ck[0]), ck, 16);
5066 +       }
5067 +
5068 +       if (name) {
5069 +               if (cc->name) {
5070 +                       dwc_free(mem_ctx, cc->name);
5071 +               }
5072 +               cc->name = dwc_alloc(mem_ctx, length);
5073 +               if (!cc->name) {
5074 +                       DWC_ERROR("Out of memory in dwc_cc_change()\n");
5075 +                       DWC_MUTEX_UNLOCK(cc_if->mutex);
5076 +                       return;
5077 +               }
5078 +               cc->length = length;
5079 +               DWC_MEMCPY(cc->name, name, length);
5080 +       }
5081 +
5082 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5083 +
5084 +       cc_changed(cc_if);
5085 +
5086 +       DWC_DEBUGC("Changed connection context id=%d\n", id);
5087 +       dump_bytes("New CHID", cc->chid, 16);
5088 +       dump_bytes("New CDID", cc->cdid, 16);
5089 +       dump_bytes("New CK", cc->ck, 16);
5090 +}
5091 +
5092 +void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
5093 +{
5094 +       dwc_cc_t *cc;
5095 +
5096 +       DWC_DEBUGC("Removing connection context %d", id);
5097 +
5098 +       DWC_MUTEX_LOCK(cc_if->mutex);
5099 +       cc = cc_find(cc_if, id);
5100 +       if (!cc) {
5101 +               DWC_ERROR("Uid %d not found in cc list\n", id);
5102 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5103 +               return;
5104 +       }
5105 +
5106 +       DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
5107 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5108 +       free_cc(mem_ctx, cc);
5109 +
5110 +       cc_changed(cc_if);
5111 +}
5112 +
5113 +uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
5114 +{
5115 +       uint8_t *buf, *x;
5116 +       uint8_t zero = 0;
5117 +       dwc_cc_t *cc;
5118 +
5119 +       DWC_MUTEX_LOCK(cc_if->mutex);
5120 +       *length = cc_data_size(cc_if);
5121 +       if (!(*length)) {
5122 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5123 +               return NULL;
5124 +       }
5125 +
5126 +       DWC_DEBUGC("Creating data for saving (length=%d)", *length);
5127 +
5128 +       buf = dwc_alloc(mem_ctx, *length);
5129 +       if (!buf) {
5130 +               *length = 0;
5131 +               DWC_MUTEX_UNLOCK(cc_if->mutex);
5132 +               return NULL;
5133 +       }
5134 +
5135 +       x = buf;
5136 +       DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
5137 +               DWC_MEMCPY(x, cc->chid, 16);
5138 +               x += 16;
5139 +               DWC_MEMCPY(x, cc->cdid, 16);
5140 +               x += 16;
5141 +               DWC_MEMCPY(x, cc->ck, 16);
5142 +               x += 16;
5143 +               if (cc->name) {
5144 +                       DWC_MEMCPY(x, &cc->length, 1);
5145 +                       x += 1;
5146 +                       DWC_MEMCPY(x, cc->name, cc->length);
5147 +                       x += cc->length;
5148 +               }
5149 +               else {
5150 +                       DWC_MEMCPY(x, &zero, 1);
5151 +                       x += 1;
5152 +               }
5153 +       }
5154 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5155 +
5156 +       return buf;
5157 +}
5158 +
5159 +void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
5160 +{
5161 +       uint8_t name_length;
5162 +       uint8_t *name;
5163 +       uint8_t *chid;
5164 +       uint8_t *cdid;
5165 +       uint8_t *ck;
5166 +       uint32_t i = 0;
5167 +
5168 +       DWC_MUTEX_LOCK(cc_if->mutex);
5169 +       cc_clear(mem_ctx, cc_if);
5170 +
5171 +       while (i < length) {
5172 +               chid = &data[i];
5173 +               i += 16;
5174 +               cdid = &data[i];
5175 +               i += 16;
5176 +               ck = &data[i];
5177 +               i += 16;
5178 +
5179 +               name_length = data[i];
5180 +               i ++;
5181 +
5182 +               if (name_length) {
5183 +                       name = &data[i];
5184 +                       i += name_length;
5185 +               }
5186 +               else {
5187 +                       name = NULL;
5188 +               }
5189 +
5190 +               /* check to see if we haven't overflown the buffer */
5191 +               if (i > length) {
5192 +                       DWC_ERROR("Data format error while attempting to load CCs "
5193 +                                 "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
5194 +                       break;
5195 +               }
5196 +
5197 +               cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
5198 +       }
5199 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5200 +
5201 +       cc_changed(cc_if);
5202 +}
5203 +
5204 +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
5205 +{
5206 +       uint32_t uid = 0;
5207 +
5208 +       DWC_MUTEX_LOCK(cc_if->mutex);
5209 +       uid = cc_match_chid(cc_if, chid);
5210 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5211 +       return uid;
5212 +}
5213 +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
5214 +{
5215 +       uint32_t uid = 0;
5216 +
5217 +       DWC_MUTEX_LOCK(cc_if->mutex);
5218 +       uid = cc_match_cdid(cc_if, cdid);
5219 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5220 +       return uid;
5221 +}
5222 +
5223 +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
5224 +{
5225 +       uint8_t *ck = NULL;
5226 +       dwc_cc_t *cc;
5227 +
5228 +       DWC_MUTEX_LOCK(cc_if->mutex);
5229 +       cc = cc_find(cc_if, id);
5230 +       if (cc) {
5231 +               ck = cc->ck;
5232 +       }
5233 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5234 +
5235 +       return ck;
5236 +
5237 +}
5238 +
5239 +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
5240 +{
5241 +       uint8_t *retval = NULL;
5242 +       dwc_cc_t *cc;
5243 +
5244 +       DWC_MUTEX_LOCK(cc_if->mutex);
5245 +       cc = cc_find(cc_if, id);
5246 +       if (cc) {
5247 +               retval = cc->chid;
5248 +       }
5249 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5250 +
5251 +       return retval;
5252 +}
5253 +
5254 +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
5255 +{
5256 +       uint8_t *retval = NULL;
5257 +       dwc_cc_t *cc;
5258 +
5259 +       DWC_MUTEX_LOCK(cc_if->mutex);
5260 +       cc = cc_find(cc_if, id);
5261 +       if (cc) {
5262 +               retval = cc->cdid;
5263 +       }
5264 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5265 +
5266 +       return retval;
5267 +}
5268 +
5269 +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
5270 +{
5271 +       uint8_t *retval = NULL;
5272 +       dwc_cc_t *cc;
5273 +
5274 +       DWC_MUTEX_LOCK(cc_if->mutex);
5275 +       *length = 0;
5276 +       cc = cc_find(cc_if, id);
5277 +       if (cc) {
5278 +               *length = cc->length;
5279 +               retval = cc->name;
5280 +       }
5281 +       DWC_MUTEX_UNLOCK(cc_if->mutex);
5282 +
5283 +       return retval;
5284 +}
5285 +
5286 +#endif /* DWC_CCLIB */
5287 --- /dev/null
5288 +++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
5289 @@ -0,0 +1,224 @@
5290 +/* =========================================================================
5291 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
5292 + * $Revision: #4 $
5293 + * $Date: 2010/09/28 $
5294 + * $Change: 1596182 $
5295 + *
5296 + * Synopsys Portability Library Software and documentation
5297 + * (hereinafter, "Software") is an Unsupported proprietary work of
5298 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
5299 + * between Synopsys and you.
5300 + *
5301 + * The Software IS NOT an item of Licensed Software or Licensed Product
5302 + * under any End User Software License Agreement or Agreement for
5303 + * Licensed Product with Synopsys or any supplement thereto. You are
5304 + * permitted to use and redistribute this Software in source and binary
5305 + * forms, with or without modification, provided that redistributions
5306 + * of source code must retain this notice. You may not view, use,
5307 + * disclose, copy or distribute this file or any information contained
5308 + * herein except pursuant to this license grant from Synopsys. If you
5309 + * do not agree with this notice, including the disclaimer below, then
5310 + * you are not authorized to use the Software.
5311 + *
5312 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
5313 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5314 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
5315 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
5316 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5317 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5318 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5319 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
5320 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5321 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
5322 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
5323 + * DAMAGE.
5324 + * ========================================================================= */
5325 +#ifndef _DWC_CC_H_
5326 +#define _DWC_CC_H_
5327 +
5328 +#ifdef __cplusplus
5329 +extern "C" {
5330 +#endif
5331 +
5332 +/** @file
5333 + *
5334 + * This file defines the Context Context library.
5335 + *
5336 + * The main data structure is dwc_cc_if_t which is returned by either the
5337 + * dwc_cc_if_alloc function or returned by the module to the user via a provided
5338 + * function. The data structure is opaque and should only be manipulated via the
5339 + * functions provied in this API.
5340 + *
5341 + * It manages a list of connection contexts and operations can be performed to
5342 + * add, remove, query, search, and change, those contexts.  Additionally,
5343 + * a dwc_notifier_t object can be requested from the manager so that
5344 + * the user can be notified whenever the context list has changed.
5345 + */
5346 +
5347 +#include "dwc_os.h"
5348 +#include "dwc_list.h"
5349 +#include "dwc_notifier.h"
5350 +
5351 +
5352 +/* Notifications */
5353 +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
5354 +
5355 +struct dwc_cc_if;
5356 +typedef struct dwc_cc_if dwc_cc_if_t;
5357 +
5358 +
5359 +/** @name Connection Context Operations */
5360 +/** @{ */
5361 +
5362 +/** This function allocates memory for a dwc_cc_if_t structure, initializes
5363 + * fields to default values, and returns a pointer to the structure or NULL on
5364 + * error. */
5365 +extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
5366 +                                   dwc_notifier_t *notifier, unsigned is_host);
5367 +
5368 +/** Frees the memory for the specified CC structure allocated from
5369 + * dwc_cc_if_alloc(). */
5370 +extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);
5371 +
5372 +/** Removes all contexts from the connection context list */
5373 +extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);
5374 +
5375 +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
5376 + * If a CHID already exists, the CK and name are overwritten.  Statistics are
5377 + * not overwritten.
5378 + *
5379 + * @param cc_if The cc_if structure.
5380 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.
5381 + * @param ck A pointer to the 16-byte CK.  This value will be copied.
5382 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.
5383 + * @param name An optional host friendly name as defined in the association model
5384 + * spec.  Must be a UTF16-LE unicode string.  Can be NULL to indicated no name.
5385 + * @param length The length othe unicode string.
5386 + * @return A unique identifier used to refer to this context that is valid for
5387 + * as long as this context is still in the list. */
5388 +extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
5389 +                         uint8_t *cdid, uint8_t *ck, uint8_t *name,
5390 +                         uint8_t length);
5391 +
5392 +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
5393 + * list, preserving any accumulated statistics.  This would typically be called
5394 + * if the host decideds to change the context with a SET_CONNECTION request.
5395 + *
5396 + * @param cc_if The cc_if structure.
5397 + * @param id The identifier of the connection context.
5398 + * @param chid A pointer to the 16-byte CHID.  This value will be copied.  NULL
5399 + * indicates no change.
5400 + * @param cdid A pointer to the 16-byte CDID.  This value will be copied.  NULL
5401 + * indicates no change.
5402 + * @param ck A pointer to the 16-byte CK.  This value will be copied.  NULL
5403 + * indicates no change.
5404 + * @param name Host friendly name UTF16-LE.  NULL indicates no change.
5405 + * @param length Length of name. */
5406 +extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,
5407 +                         uint8_t *chid, uint8_t *cdid, uint8_t *ck,
5408 +                         uint8_t *name, uint8_t length);
5409 +
5410 +/** Remove the specified connection context.
5411 + * @param cc_if The cc_if structure.
5412 + * @param id The identifier of the connection context to remove. */
5413 +extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);
5414 +
5415 +/** Get a binary block of data for the connection context list and attributes.
5416 + * This data can be used by the OS specific driver to save the connection
5417 + * context list into non-volatile memory.
5418 + *
5419 + * @param cc_if The cc_if structure.
5420 + * @param length Return the length of the data buffer.
5421 + * @return A pointer to the data buffer.  The memory for this buffer should be
5422 + * freed with DWC_FREE() after use. */
5423 +extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,
5424 +                                    unsigned int *length);
5425 +
5426 +/** Restore the connection context list from the binary data that was previously
5427 + * returned from a call to dwc_cc_data_for_save.  This can be used by the OS specific
5428 + * driver to load a connection context list from non-volatile memory.
5429 + *
5430 + * @param cc_if The cc_if structure.
5431 + * @param data The data bytes as returned from dwc_cc_data_for_save.
5432 + * @param length The length of the data. */
5433 +extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,
5434 +                                    uint8_t *data, unsigned int length);
5435 +
5436 +/** Find the connection context from the specified CHID.
5437 + *
5438 + * @param cc_if The cc_if structure.
5439 + * @param chid A pointer to the CHID data.
5440 + * @return A non-zero identifier of the connection context if the CHID matches.
5441 + * Otherwise returns 0. */
5442 +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
5443 +
5444 +/** Find the connection context from the specified CDID.
5445 + *
5446 + * @param cc_if The cc_if structure.
5447 + * @param cdid A pointer to the CDID data.
5448 + * @return A non-zero identifier of the connection context if the CHID matches.
5449 + * Otherwise returns 0. */
5450 +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
5451 +
5452 +/** Retrieve the CK from the specified connection context.
5453 + *
5454 + * @param cc_if The cc_if structure.
5455 + * @param id The identifier of the connection context.
5456 + * @return A pointer to the CK data.  The memory does not need to be freed. */
5457 +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
5458 +
5459 +/** Retrieve the CHID from the specified connection context.
5460 + *
5461 + * @param cc_if The cc_if structure.
5462 + * @param id The identifier of the connection context.
5463 + * @return A pointer to the CHID data.  The memory does not need to be freed. */
5464 +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
5465 +
5466 +/** Retrieve the CDID from the specified connection context.
5467 + *
5468 + * @param cc_if The cc_if structure.
5469 + * @param id The identifier of the connection context.
5470 + * @return A pointer to the CDID data.  The memory does not need to be freed. */
5471 +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
5472 +
5473 +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
5474 +
5475 +/** Checks a buffer for non-zero.
5476 + * @param id A pointer to a 16 byte buffer.
5477 + * @return true if the 16 byte value is non-zero. */
5478 +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
5479 +       int i;
5480 +       for (i=0; i<16; i++) {
5481 +               if (id[i]) return 1;
5482 +       }
5483 +       return 0;
5484 +}
5485 +
5486 +/** Checks a buffer for zero.
5487 + * @param id A pointer to a 16 byte buffer.
5488 + * @return true if the 16 byte value is zero. */
5489 +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
5490 +       return !dwc_assoc_is_not_zero_id(id);
5491 +}
5492 +
5493 +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
5494 + * buffer. */
5495 +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
5496 +       char *ptr = buffer;
5497 +       int i;
5498 +       for (i=0; i<16; i++) {
5499 +               ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
5500 +               if (i < 15) {
5501 +                       ptr += DWC_SPRINTF(ptr, " ");
5502 +               }
5503 +       }
5504 +       return ptr - buffer;
5505 +}
5506 +
5507 +/** @} */
5508 +
5509 +#ifdef __cplusplus
5510 +}
5511 +#endif
5512 +
5513 +#endif /* _DWC_CC_H_ */
5514 --- /dev/null
5515 +++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
5516 @@ -0,0 +1,1308 @@
5517 +#include "dwc_os.h"
5518 +#include "dwc_list.h"
5519 +
5520 +#ifdef DWC_CCLIB
5521 +# include "dwc_cc.h"
5522 +#endif
5523 +
5524 +#ifdef DWC_CRYPTOLIB
5525 +# include "dwc_modpow.h"
5526 +# include "dwc_dh.h"
5527 +# include "dwc_crypto.h"
5528 +#endif
5529 +
5530 +#ifdef DWC_NOTIFYLIB
5531 +# include "dwc_notifier.h"
5532 +#endif
5533 +
5534 +/* OS-Level Implementations */
5535 +
5536 +/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */
5537 +
5538 +
5539 +/* MISC */
5540 +
5541 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
5542 +{
5543 +       return memset(dest, byte, size);
5544 +}
5545 +
5546 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
5547 +{
5548 +       return memcpy(dest, src, size);
5549 +}
5550 +
5551 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
5552 +{
5553 +       bcopy(src, dest, size);
5554 +       return dest;
5555 +}
5556 +
5557 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
5558 +{
5559 +       return memcmp(m1, m2, size);
5560 +}
5561 +
5562 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
5563 +{
5564 +       return strncmp(s1, s2, size);
5565 +}
5566 +
5567 +int DWC_STRCMP(void *s1, void *s2)
5568 +{
5569 +       return strcmp(s1, s2);
5570 +}
5571 +
5572 +int DWC_STRLEN(char const *str)
5573 +{
5574 +       return strlen(str);
5575 +}
5576 +
5577 +char *DWC_STRCPY(char *to, char const *from)
5578 +{
5579 +       return strcpy(to, from);
5580 +}
5581 +
5582 +char *DWC_STRDUP(char const *str)
5583 +{
5584 +       int len = DWC_STRLEN(str) + 1;
5585 +       char *new = DWC_ALLOC_ATOMIC(len);
5586 +
5587 +       if (!new) {
5588 +               return NULL;
5589 +       }
5590 +
5591 +       DWC_MEMCPY(new, str, len);
5592 +       return new;
5593 +}
5594 +
5595 +int DWC_ATOI(char *str, int32_t *value)
5596 +{
5597 +       char *end = NULL;
5598 +
5599 +       *value = strtol(str, &end, 0);
5600 +       if (*end == '\0') {
5601 +               return 0;
5602 +       }
5603 +
5604 +       return -1;
5605 +}
5606 +
5607 +int DWC_ATOUI(char *str, uint32_t *value)
5608 +{
5609 +       char *end = NULL;
5610 +
5611 +       *value = strtoul(str, &end, 0);
5612 +       if (*end == '\0') {
5613 +               return 0;
5614 +       }
5615 +
5616 +       return -1;
5617 +}
5618 +
5619 +
5620 +#ifdef DWC_UTFLIB
5621 +/* From usbstring.c */
5622 +
5623 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
5624 +{
5625 +       int     count = 0;
5626 +       u8      c;
5627 +       u16     uchar;
5628 +
5629 +       /* this insists on correct encodings, though not minimal ones.
5630 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
5631 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
5632 +        */
5633 +       while (len != 0 && (c = (u8) *s++) != 0) {
5634 +               if (unlikely(c & 0x80)) {
5635 +                       // 2-byte sequence:
5636 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
5637 +                       if ((c & 0xe0) == 0xc0) {
5638 +                               uchar = (c & 0x1f) << 6;
5639 +
5640 +                               c = (u8) *s++;
5641 +                               if ((c & 0xc0) != 0xc0)
5642 +                                       goto fail;
5643 +                               c &= 0x3f;
5644 +                               uchar |= c;
5645 +
5646 +                       // 3-byte sequence (most CJKV characters):
5647 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
5648 +                       } else if ((c & 0xf0) == 0xe0) {
5649 +                               uchar = (c & 0x0f) << 12;
5650 +
5651 +                               c = (u8) *s++;
5652 +                               if ((c & 0xc0) != 0xc0)
5653 +                                       goto fail;
5654 +                               c &= 0x3f;
5655 +                               uchar |= c << 6;
5656 +
5657 +                               c = (u8) *s++;
5658 +                               if ((c & 0xc0) != 0xc0)
5659 +                                       goto fail;
5660 +                               c &= 0x3f;
5661 +                               uchar |= c;
5662 +
5663 +                               /* no bogus surrogates */
5664 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
5665 +                                       goto fail;
5666 +
5667 +                       // 4-byte sequence (surrogate pairs, currently rare):
5668 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
5669 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
5670 +                       // (uuuuu = wwww + 1)
5671 +                       // FIXME accept the surrogate code points (only)
5672 +                       } else
5673 +                               goto fail;
5674 +               } else
5675 +                       uchar = c;
5676 +               put_unaligned (cpu_to_le16 (uchar), cp++);
5677 +               count++;
5678 +               len--;
5679 +       }
5680 +       return count;
5681 +fail:
5682 +       return -1;
5683 +}
5684 +
5685 +#endif /* DWC_UTFLIB */
5686 +
5687 +
5688 +/* dwc_debug.h */
5689 +
5690 +dwc_bool_t DWC_IN_IRQ(void)
5691 +{
5692 +//     return in_irq();
5693 +       return 0;
5694 +}
5695 +
5696 +dwc_bool_t DWC_IN_BH(void)
5697 +{
5698 +//     return in_softirq();
5699 +       return 0;
5700 +}
5701 +
5702 +void DWC_VPRINTF(char *format, va_list args)
5703 +{
5704 +       vprintf(format, args);
5705 +}
5706 +
5707 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
5708 +{
5709 +       return vsnprintf(str, size, format, args);
5710 +}
5711 +
5712 +void DWC_PRINTF(char *format, ...)
5713 +{
5714 +       va_list args;
5715 +
5716 +       va_start(args, format);
5717 +       DWC_VPRINTF(format, args);
5718 +       va_end(args);
5719 +}
5720 +
5721 +int DWC_SPRINTF(char *buffer, char *format, ...)
5722 +{
5723 +       int retval;
5724 +       va_list args;
5725 +
5726 +       va_start(args, format);
5727 +       retval = vsprintf(buffer, format, args);
5728 +       va_end(args);
5729 +       return retval;
5730 +}
5731 +
5732 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
5733 +{
5734 +       int retval;
5735 +       va_list args;
5736 +
5737 +       va_start(args, format);
5738 +       retval = vsnprintf(buffer, size, format, args);
5739 +       va_end(args);
5740 +       return retval;
5741 +}
5742 +
5743 +void __DWC_WARN(char *format, ...)
5744 +{
5745 +       va_list args;
5746 +
5747 +       va_start(args, format);
5748 +       DWC_VPRINTF(format, args);
5749 +       va_end(args);
5750 +}
5751 +
5752 +void __DWC_ERROR(char *format, ...)
5753 +{
5754 +       va_list args;
5755 +
5756 +       va_start(args, format);
5757 +       DWC_VPRINTF(format, args);
5758 +       va_end(args);
5759 +}
5760 +
5761 +void DWC_EXCEPTION(char *format, ...)
5762 +{
5763 +       va_list args;
5764 +
5765 +       va_start(args, format);
5766 +       DWC_VPRINTF(format, args);
5767 +       va_end(args);
5768 +//     BUG_ON(1);      ???
5769 +}
5770 +
5771 +#ifdef DEBUG
5772 +void __DWC_DEBUG(char *format, ...)
5773 +{
5774 +       va_list args;
5775 +
5776 +       va_start(args, format);
5777 +       DWC_VPRINTF(format, args);
5778 +       va_end(args);
5779 +}
5780 +#endif
5781 +
5782 +
5783 +/* dwc_mem.h */
5784 +
5785 +#if 0
5786 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
5787 +                               uint32_t align,
5788 +                               uint32_t alloc)
5789 +{
5790 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
5791 +                                               size, align, alloc);
5792 +       return (dwc_pool_t *)pool;
5793 +}
5794 +
5795 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
5796 +{
5797 +       dma_pool_destroy((struct dma_pool *)pool);
5798 +}
5799 +
5800 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5801 +{
5802 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
5803 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
5804 +}
5805 +
5806 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
5807 +{
5808 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
5809 +       memset(..);
5810 +}
5811 +
5812 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
5813 +{
5814 +       dma_pool_free(pool, vaddr, daddr);
5815 +}
5816 +#endif
5817 +
5818 +static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5819 +{
5820 +       if (error)
5821 +               return;
5822 +       *(bus_addr_t *)arg = segs[0].ds_addr;
5823 +}
5824 +
5825 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
5826 +{
5827 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5828 +       int error;
5829 +
5830 +       error = bus_dma_tag_create(
5831 +#if __FreeBSD_version >= 700000
5832 +                       bus_get_dma_tag(dma->dev),      /* parent */
5833 +#else
5834 +                       NULL,                           /* parent */
5835 +#endif
5836 +                       4, 0,                           /* alignment, bounds */
5837 +                       BUS_SPACE_MAXADDR_32BIT,        /* lowaddr */
5838 +                       BUS_SPACE_MAXADDR,              /* highaddr */
5839 +                       NULL, NULL,                     /* filter, filterarg */
5840 +                       size,                           /* maxsize */
5841 +                       1,                              /* nsegments */
5842 +                       size,                           /* maxsegsize */
5843 +                       0,                              /* flags */
5844 +                       NULL,                           /* lockfunc */
5845 +                       NULL,                           /* lockarg */
5846 +                       &dma->dma_tag);
5847 +       if (error) {
5848 +               device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",
5849 +                             __func__, error);
5850 +               goto fail_0;
5851 +       }
5852 +
5853 +       error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,
5854 +                                BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
5855 +       if (error) {
5856 +               device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
5857 +                             __func__, (uintmax_t)size, error);
5858 +               goto fail_1;
5859 +       }
5860 +
5861 +       dma->dma_paddr = 0;
5862 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,
5863 +                               dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);
5864 +       if (error || dma->dma_paddr == 0) {
5865 +               device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",
5866 +                             __func__, error);
5867 +               goto fail_2;
5868 +       }
5869 +
5870 +       *dma_addr = dma->dma_paddr;
5871 +       return dma->dma_vaddr;
5872 +
5873 +fail_2:
5874 +       bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5875 +fail_1:
5876 +       bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5877 +       bus_dma_tag_destroy(dma->dma_tag);
5878 +fail_0:
5879 +       dma->dma_map = NULL;
5880 +       dma->dma_tag = NULL;
5881 +
5882 +       return NULL;
5883 +}
5884 +
5885 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
5886 +{
5887 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
5888 +
5889 +       if (dma->dma_tag == NULL)
5890 +               return;
5891 +       if (dma->dma_map != NULL) {
5892 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map,
5893 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
5894 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
5895 +               bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
5896 +               dma->dma_map = NULL;
5897 +       }
5898 +
5899 +       bus_dma_tag_destroy(dma->dma_tag);
5900 +       dma->dma_tag = NULL;
5901 +}
5902 +
5903 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
5904 +{
5905 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
5906 +}
5907 +
5908 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
5909 +{
5910 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
5911 +}
5912 +
5913 +void __DWC_FREE(void *mem_ctx, void *addr)
5914 +{
5915 +       free(addr, M_DEVBUF);
5916 +}
5917 +
5918 +
5919 +#ifdef DWC_CRYPTOLIB
5920 +/* dwc_crypto.h */
5921 +
5922 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
5923 +{
5924 +       get_random_bytes(buffer, length);
5925 +}
5926 +
5927 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
5928 +{
5929 +       struct crypto_blkcipher *tfm;
5930 +       struct blkcipher_desc desc;
5931 +       struct scatterlist sgd;
5932 +       struct scatterlist sgs;
5933 +
5934 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
5935 +       if (tfm == NULL) {
5936 +               printk("failed to load transform for aes CBC\n");
5937 +               return -1;
5938 +       }
5939 +
5940 +       crypto_blkcipher_setkey(tfm, key, keylen);
5941 +       crypto_blkcipher_set_iv(tfm, iv, 16);
5942 +
5943 +       sg_init_one(&sgd, out, messagelen);
5944 +       sg_init_one(&sgs, message, messagelen);
5945 +
5946 +       desc.tfm = tfm;
5947 +       desc.flags = 0;
5948 +
5949 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
5950 +               crypto_free_blkcipher(tfm);
5951 +               DWC_ERROR("AES CBC encryption failed");
5952 +               return -1;
5953 +       }
5954 +
5955 +       crypto_free_blkcipher(tfm);
5956 +       return 0;
5957 +}
5958 +
5959 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
5960 +{
5961 +       struct crypto_hash *tfm;
5962 +       struct hash_desc desc;
5963 +       struct scatterlist sg;
5964 +
5965 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
5966 +       if (IS_ERR(tfm)) {
5967 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
5968 +               return 0;
5969 +       }
5970 +       desc.tfm = tfm;
5971 +       desc.flags = 0;
5972 +
5973 +       sg_init_one(&sg, message, len);
5974 +       crypto_hash_digest(&desc, &sg, len, out);
5975 +       crypto_free_hash(tfm);
5976 +
5977 +       return 1;
5978 +}
5979 +
5980 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
5981 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
5982 +{
5983 +       struct crypto_hash *tfm;
5984 +       struct hash_desc desc;
5985 +       struct scatterlist sg;
5986 +
5987 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
5988 +       if (IS_ERR(tfm)) {
5989 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
5990 +               return 0;
5991 +       }
5992 +       desc.tfm = tfm;
5993 +       desc.flags = 0;
5994 +
5995 +       sg_init_one(&sg, message, messagelen);
5996 +       crypto_hash_setkey(tfm, key, keylen);
5997 +       crypto_hash_digest(&desc, &sg, messagelen, out);
5998 +       crypto_free_hash(tfm);
5999 +
6000 +       return 1;
6001 +}
6002 +
6003 +#endif /* DWC_CRYPTOLIB */
6004 +
6005 +
6006 +/* Byte Ordering Conversions */
6007 +
6008 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
6009 +{
6010 +#ifdef __LITTLE_ENDIAN
6011 +       return *p;
6012 +#else
6013 +       uint8_t *u_p = (uint8_t *)p;
6014 +
6015 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6016 +#endif
6017 +}
6018 +
6019 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
6020 +{
6021 +#ifdef __BIG_ENDIAN
6022 +       return *p;
6023 +#else
6024 +       uint8_t *u_p = (uint8_t *)p;
6025 +
6026 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6027 +#endif
6028 +}
6029 +
6030 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
6031 +{
6032 +#ifdef __LITTLE_ENDIAN
6033 +       return *p;
6034 +#else
6035 +       uint8_t *u_p = (uint8_t *)p;
6036 +
6037 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6038 +#endif
6039 +}
6040 +
6041 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
6042 +{
6043 +#ifdef __BIG_ENDIAN
6044 +       return *p;
6045 +#else
6046 +       uint8_t *u_p = (uint8_t *)p;
6047 +
6048 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
6049 +#endif
6050 +}
6051 +
6052 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
6053 +{
6054 +#ifdef __LITTLE_ENDIAN
6055 +       return *p;
6056 +#else
6057 +       uint8_t *u_p = (uint8_t *)p;
6058 +       return (u_p[1] | (u_p[0] << 8));
6059 +#endif
6060 +}
6061 +
6062 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
6063 +{
6064 +#ifdef __BIG_ENDIAN
6065 +       return *p;
6066 +#else
6067 +       uint8_t *u_p = (uint8_t *)p;
6068 +       return (u_p[1] | (u_p[0] << 8));
6069 +#endif
6070 +}
6071 +
6072 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
6073 +{
6074 +#ifdef __LITTLE_ENDIAN
6075 +       return *p;
6076 +#else
6077 +       uint8_t *u_p = (uint8_t *)p;
6078 +       return (u_p[1] | (u_p[0] << 8));
6079 +#endif
6080 +}
6081 +
6082 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
6083 +{
6084 +#ifdef __BIG_ENDIAN
6085 +       return *p;
6086 +#else
6087 +       uint8_t *u_p = (uint8_t *)p;
6088 +       return (u_p[1] | (u_p[0] << 8));
6089 +#endif
6090 +}
6091 +
6092 +
6093 +/* Registers */
6094 +
6095 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
6096 +{
6097 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6098 +       bus_size_t ior = (bus_size_t)reg;
6099 +
6100 +       return bus_space_read_4(io->iot, io->ioh, ior);
6101 +}
6102 +
6103 +#if 0
6104 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
6105 +{
6106 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6107 +       bus_size_t ior = (bus_size_t)reg;
6108 +
6109 +       return bus_space_read_8(io->iot, io->ioh, ior);
6110 +}
6111 +#endif
6112 +
6113 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
6114 +{
6115 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6116 +       bus_size_t ior = (bus_size_t)reg;
6117 +
6118 +       bus_space_write_4(io->iot, io->ioh, ior, value);
6119 +}
6120 +
6121 +#if 0
6122 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
6123 +{
6124 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6125 +       bus_size_t ior = (bus_size_t)reg;
6126 +
6127 +       bus_space_write_8(io->iot, io->ioh, ior, value);
6128 +}
6129 +#endif
6130 +
6131 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
6132 +                     uint32_t set_mask)
6133 +{
6134 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6135 +       bus_size_t ior = (bus_size_t)reg;
6136 +
6137 +       bus_space_write_4(io->iot, io->ioh, ior,
6138 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
6139 +                          ~clear_mask) | set_mask);
6140 +}
6141 +
6142 +#if 0
6143 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
6144 +                     uint64_t set_mask)
6145 +{
6146 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
6147 +       bus_size_t ior = (bus_size_t)reg;
6148 +
6149 +       bus_space_write_8(io->iot, io->ioh, ior,
6150 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
6151 +                          ~clear_mask) | set_mask);
6152 +}
6153 +#endif
6154 +
6155 +
6156 +/* Locking */
6157 +
6158 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
6159 +{
6160 +       struct mtx *sl = DWC_ALLOC(sizeof(*sl));
6161 +
6162 +       if (!sl) {
6163 +               DWC_ERROR("Cannot allocate memory for spinlock");
6164 +               return NULL;
6165 +       }
6166 +
6167 +       mtx_init(sl, "dw3spn", NULL, MTX_SPIN);
6168 +       return (dwc_spinlock_t *)sl;
6169 +}
6170 +
6171 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
6172 +{
6173 +       struct mtx *sl = (struct mtx *)lock;
6174 +
6175 +       mtx_destroy(sl);
6176 +       DWC_FREE(sl);
6177 +}
6178 +
6179 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
6180 +{
6181 +       mtx_lock_spin((struct mtx *)lock);      // ???
6182 +}
6183 +
6184 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
6185 +{
6186 +       mtx_unlock_spin((struct mtx *)lock);    // ???
6187 +}
6188 +
6189 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
6190 +{
6191 +       mtx_lock_spin((struct mtx *)lock);
6192 +}
6193 +
6194 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
6195 +{
6196 +       mtx_unlock_spin((struct mtx *)lock);
6197 +}
6198 +
6199 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
6200 +{
6201 +       struct mtx *m;
6202 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));
6203 +
6204 +       if (!mutex) {
6205 +               DWC_ERROR("Cannot allocate memory for mutex");
6206 +               return NULL;
6207 +       }
6208 +
6209 +       m = (struct mtx *)mutex;
6210 +       mtx_init(m, "dw3mtx", NULL, MTX_DEF);
6211 +       return mutex;
6212 +}
6213 +
6214 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
6215 +#else
6216 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
6217 +{
6218 +       mtx_destroy((struct mtx *)mutex);
6219 +       DWC_FREE(mutex);
6220 +}
6221 +#endif
6222 +
6223 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
6224 +{
6225 +       struct mtx *m = (struct mtx *)mutex;
6226 +
6227 +       mtx_lock(m);
6228 +}
6229 +
6230 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
6231 +{
6232 +       struct mtx *m = (struct mtx *)mutex;
6233 +
6234 +       return mtx_trylock(m);
6235 +}
6236 +
6237 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
6238 +{
6239 +       struct mtx *m = (struct mtx *)mutex;
6240 +
6241 +       mtx_unlock(m);
6242 +}
6243 +
6244 +
6245 +/* Timing */
6246 +
6247 +void DWC_UDELAY(uint32_t usecs)
6248 +{
6249 +       DELAY(usecs);
6250 +}
6251 +
6252 +void DWC_MDELAY(uint32_t msecs)
6253 +{
6254 +       do {
6255 +               DELAY(1000);
6256 +       } while (--msecs);
6257 +}
6258 +
6259 +void DWC_MSLEEP(uint32_t msecs)
6260 +{
6261 +       struct timeval tv;
6262 +
6263 +       tv.tv_sec = msecs / 1000;
6264 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6265 +       pause("dw3slp", tvtohz(&tv));
6266 +}
6267 +
6268 +uint32_t DWC_TIME(void)
6269 +{
6270 +       struct timeval tv;
6271 +
6272 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
6273 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
6274 +}
6275 +
6276 +
6277 +/* Timers */
6278 +
6279 +struct dwc_timer {
6280 +       struct callout t;
6281 +       char *name;
6282 +       dwc_spinlock_t *lock;
6283 +       dwc_timer_callback_t cb;
6284 +       void *data;
6285 +};
6286 +
6287 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
6288 +{
6289 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
6290 +
6291 +       if (!t) {
6292 +               DWC_ERROR("Cannot allocate memory for timer");
6293 +               return NULL;
6294 +       }
6295 +
6296 +       callout_init(&t->t, 1);
6297 +
6298 +       t->name = DWC_STRDUP(name);
6299 +       if (!t->name) {
6300 +               DWC_ERROR("Cannot allocate memory for timer->name");
6301 +               goto no_name;
6302 +       }
6303 +
6304 +       t->lock = DWC_SPINLOCK_ALLOC();
6305 +       if (!t->lock) {
6306 +               DWC_ERROR("Cannot allocate memory for lock");
6307 +               goto no_lock;
6308 +       }
6309 +
6310 +       t->cb = cb;
6311 +       t->data = data;
6312 +
6313 +       return t;
6314 +
6315 + no_lock:
6316 +       DWC_FREE(t->name);
6317 + no_name:
6318 +       DWC_FREE(t);
6319 +
6320 +       return NULL;
6321 +}
6322 +
6323 +void DWC_TIMER_FREE(dwc_timer_t *timer)
6324 +{
6325 +       callout_stop(&timer->t);
6326 +       DWC_SPINLOCK_FREE(timer->lock);
6327 +       DWC_FREE(timer->name);
6328 +       DWC_FREE(timer);
6329 +}
6330 +
6331 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
6332 +{
6333 +       struct timeval tv;
6334 +
6335 +       tv.tv_sec = time / 1000;
6336 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6337 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
6338 +}
6339 +
6340 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
6341 +{
6342 +       callout_stop(&timer->t);
6343 +}
6344 +
6345 +
6346 +/* Wait Queues */
6347 +
6348 +struct dwc_waitq {
6349 +       struct mtx lock;
6350 +       int abort;
6351 +};
6352 +
6353 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
6354 +{
6355 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
6356 +
6357 +       if (!wq) {
6358 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6359 +               return NULL;
6360 +       }
6361 +
6362 +       mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);
6363 +       wq->abort = 0;
6364 +
6365 +       return wq;
6366 +}
6367 +
6368 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
6369 +{
6370 +       mtx_destroy(&wq->lock);
6371 +       DWC_FREE(wq);
6372 +}
6373 +
6374 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
6375 +{
6376 +//     intrmask_t ipl;
6377 +       int result = 0;
6378 +
6379 +       mtx_lock(&wq->lock);
6380 +//     ipl = splbio();
6381 +
6382 +       /* Skip the sleep if already aborted or triggered */
6383 +       if (!wq->abort && !cond(data)) {
6384 +//             splx(ipl);
6385 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout
6386 +//             ipl = splbio();
6387 +       }
6388 +
6389 +       if (result == ERESTART) {       // signaled - restart
6390 +               result = -DWC_E_RESTART;
6391 +
6392 +       } else if (result == EINTR) {   // signaled - interrupt
6393 +               result = -DWC_E_ABORT;
6394 +
6395 +       } else if (wq->abort) {
6396 +               result = -DWC_E_ABORT;
6397 +
6398 +       } else {
6399 +               result = 0;
6400 +       }
6401 +
6402 +       wq->abort = 0;
6403 +//     splx(ipl);
6404 +       mtx_unlock(&wq->lock);
6405 +       return result;
6406 +}
6407 +
6408 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
6409 +                              void *data, int32_t msecs)
6410 +{
6411 +       struct timeval tv, tv1, tv2;
6412 +//     intrmask_t ipl;
6413 +       int result = 0;
6414 +
6415 +       tv.tv_sec = msecs / 1000;
6416 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
6417 +
6418 +       mtx_lock(&wq->lock);
6419 +//     ipl = splbio();
6420 +
6421 +       /* Skip the sleep if already aborted or triggered */
6422 +       if (!wq->abort && !cond(data)) {
6423 +//             splx(ipl);
6424 +               getmicrouptime(&tv1);
6425 +               result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));
6426 +               getmicrouptime(&tv2);
6427 +//             ipl = splbio();
6428 +       }
6429 +
6430 +       if (result == 0) {                      // awoken
6431 +               if (wq->abort) {
6432 +                       result = -DWC_E_ABORT;
6433 +               } else {
6434 +                       tv2.tv_usec -= tv1.tv_usec;
6435 +                       if (tv2.tv_usec < 0) {
6436 +                               tv2.tv_usec += 1000000;
6437 +                               tv2.tv_sec--;
6438 +                       }
6439 +
6440 +                       tv2.tv_sec -= tv1.tv_sec;
6441 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
6442 +                       result = msecs - result;
6443 +                       if (result <= 0)
6444 +                               result = 1;
6445 +               }
6446 +       } else if (result == ERESTART) {        // signaled - restart
6447 +               result = -DWC_E_RESTART;
6448 +
6449 +       } else if (result == EINTR) {           // signaled - interrupt
6450 +               result = -DWC_E_ABORT;
6451 +
6452 +       } else {                                // timed out
6453 +               result = -DWC_E_TIMEOUT;
6454 +       }
6455 +
6456 +       wq->abort = 0;
6457 +//     splx(ipl);
6458 +       mtx_unlock(&wq->lock);
6459 +       return result;
6460 +}
6461 +
6462 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
6463 +{
6464 +       wakeup(wq);
6465 +}
6466 +
6467 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
6468 +{
6469 +//     intrmask_t ipl;
6470 +
6471 +       mtx_lock(&wq->lock);
6472 +//     ipl = splbio();
6473 +       wq->abort = 1;
6474 +       wakeup(wq);
6475 +//     splx(ipl);
6476 +       mtx_unlock(&wq->lock);
6477 +}
6478 +
6479 +
6480 +/* Threading */
6481 +
6482 +struct dwc_thread {
6483 +       struct proc *proc;
6484 +       int abort;
6485 +};
6486 +
6487 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
6488 +{
6489 +       int retval;
6490 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
6491 +
6492 +       if (!thread) {
6493 +               return NULL;
6494 +       }
6495 +
6496 +       thread->abort = 0;
6497 +       retval = kthread_create((void (*)(void *))func, data, &thread->proc,
6498 +                               RFPROC | RFNOWAIT, 0, "%s", name);
6499 +       if (retval) {
6500 +               DWC_FREE(thread);
6501 +               return NULL;
6502 +       }
6503 +
6504 +       return thread;
6505 +}
6506 +
6507 +int DWC_THREAD_STOP(dwc_thread_t *thread)
6508 +{
6509 +       int retval;
6510 +
6511 +       thread->abort = 1;
6512 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
6513 +
6514 +       if (retval == 0) {
6515 +               /* DWC_THREAD_EXIT() will free the thread struct */
6516 +               return 0;
6517 +       }
6518 +
6519 +       /* NOTE: We leak the thread struct if thread doesn't die */
6520 +
6521 +       if (retval == EWOULDBLOCK) {
6522 +               return -DWC_E_TIMEOUT;
6523 +       }
6524 +
6525 +       return -DWC_E_UNKNOWN;
6526 +}
6527 +
6528 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
6529 +{
6530 +       return thread->abort;
6531 +}
6532 +
6533 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
6534 +{
6535 +       wakeup(&thread->abort);
6536 +       DWC_FREE(thread);
6537 +       kthread_exit(0);
6538 +}
6539 +
6540 +
6541 +/* tasklets
6542 + - Runs in interrupt context (cannot sleep)
6543 + - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]
6544 + - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]
6545 + */
6546 +struct dwc_tasklet {
6547 +       struct task t;
6548 +       dwc_tasklet_callback_t cb;
6549 +       void *data;
6550 +};
6551 +
6552 +static void tasklet_callback(void *data, int pending)  // what to do with pending ???
6553 +{
6554 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
6555 +
6556 +       task->cb(task->data);
6557 +}
6558 +
6559 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
6560 +{
6561 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
6562 +
6563 +       if (task) {
6564 +               task->cb = cb;
6565 +               task->data = data;
6566 +               TASK_INIT(&task->t, 0, tasklet_callback, task);
6567 +       } else {
6568 +               DWC_ERROR("Cannot allocate memory for tasklet");
6569 +       }
6570 +
6571 +       return task;
6572 +}
6573 +
6574 +void DWC_TASK_FREE(dwc_tasklet_t *task)
6575 +{
6576 +       taskqueue_drain(taskqueue_fast, &task->t);      // ???
6577 +       DWC_FREE(task);
6578 +}
6579 +
6580 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
6581 +{
6582 +       /* Uses predefined system queue */
6583 +       taskqueue_enqueue_fast(taskqueue_fast, &task->t);
6584 +}
6585 +
6586 +
6587 +/* workqueues
6588 + - Runs in process context (can sleep)
6589 + */
6590 +typedef struct work_container {
6591 +       dwc_work_callback_t cb;
6592 +       void *data;
6593 +       dwc_workq_t *wq;
6594 +       char *name;
6595 +       int hz;
6596 +
6597 +#ifdef DEBUG
6598 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
6599 +#endif
6600 +       struct task task;
6601 +} work_container_t;
6602 +
6603 +#ifdef DEBUG
6604 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
6605 +#endif
6606 +
6607 +struct dwc_workq {
6608 +       struct taskqueue *taskq;
6609 +       dwc_spinlock_t *lock;
6610 +       dwc_waitq_t *waitq;
6611 +       int pending;
6612 +
6613 +#ifdef DEBUG
6614 +       struct work_container_queue entries;
6615 +#endif
6616 +};
6617 +
6618 +static void do_work(void *data, int pending)   // what to do with pending ???
6619 +{
6620 +       work_container_t *container = (work_container_t *)data;
6621 +       dwc_workq_t *wq = container->wq;
6622 +       dwc_irqflags_t flags;
6623 +
6624 +       if (container->hz) {
6625 +               pause("dw3wrk", container->hz);
6626 +       }
6627 +
6628 +       container->cb(container->data);
6629 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
6630 +
6631 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6632 +
6633 +#ifdef DEBUG
6634 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
6635 +#endif
6636 +       if (container->name)
6637 +               DWC_FREE(container->name);
6638 +       DWC_FREE(container);
6639 +       wq->pending--;
6640 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6641 +       DWC_WAITQ_TRIGGER(wq->waitq);
6642 +}
6643 +
6644 +static int work_done(void *data)
6645 +{
6646 +       dwc_workq_t *workq = (dwc_workq_t *)data;
6647 +
6648 +       return workq->pending == 0;
6649 +}
6650 +
6651 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
6652 +{
6653 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
6654 +}
6655 +
6656 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
6657 +{
6658 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
6659 +
6660 +       if (!wq) {
6661 +               DWC_ERROR("Cannot allocate memory for workqueue");
6662 +               return NULL;
6663 +       }
6664 +
6665 +       wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);
6666 +       if (!wq->taskq) {
6667 +               DWC_ERROR("Cannot allocate memory for taskqueue");
6668 +               goto no_taskq;
6669 +       }
6670 +
6671 +       wq->pending = 0;
6672 +
6673 +       wq->lock = DWC_SPINLOCK_ALLOC();
6674 +       if (!wq->lock) {
6675 +               DWC_ERROR("Cannot allocate memory for spinlock");
6676 +               goto no_lock;
6677 +       }
6678 +
6679 +       wq->waitq = DWC_WAITQ_ALLOC();
6680 +       if (!wq->waitq) {
6681 +               DWC_ERROR("Cannot allocate memory for waitqueue");
6682 +               goto no_waitq;
6683 +       }
6684 +
6685 +       taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");
6686 +
6687 +#ifdef DEBUG
6688 +       DWC_CIRCLEQ_INIT(&wq->entries);
6689 +#endif
6690 +       return wq;
6691 +
6692 + no_waitq:
6693 +       DWC_SPINLOCK_FREE(wq->lock);
6694 + no_lock:
6695 +       taskqueue_free(wq->taskq);
6696 + no_taskq:
6697 +       DWC_FREE(wq);
6698 +
6699 +       return NULL;
6700 +}
6701 +
6702 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
6703 +{
6704 +#ifdef DEBUG
6705 +       dwc_irqflags_t flags;
6706 +
6707 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6708 +
6709 +       if (wq->pending != 0) {
6710 +               struct work_container *container;
6711 +
6712 +               DWC_ERROR("Destroying work queue with pending work");
6713 +
6714 +               DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {
6715 +                       DWC_ERROR("Work %s still pending", container->name);
6716 +               }
6717 +       }
6718 +
6719 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6720 +#endif
6721 +       DWC_WAITQ_FREE(wq->waitq);
6722 +       DWC_SPINLOCK_FREE(wq->lock);
6723 +       taskqueue_free(wq->taskq);
6724 +       DWC_FREE(wq);
6725 +}
6726 +
6727 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
6728 +                       char *format, ...)
6729 +{
6730 +       dwc_irqflags_t flags;
6731 +       work_container_t *container;
6732 +       static char name[128];
6733 +       va_list args;
6734 +
6735 +       va_start(args, format);
6736 +       DWC_VSNPRINTF(name, 128, format, args);
6737 +       va_end(args);
6738 +
6739 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6740 +       wq->pending++;
6741 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6742 +       DWC_WAITQ_TRIGGER(wq->waitq);
6743 +
6744 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6745 +       if (!container) {
6746 +               DWC_ERROR("Cannot allocate memory for container");
6747 +               return;
6748 +       }
6749 +
6750 +       container->name = DWC_STRDUP(name);
6751 +       if (!container->name) {
6752 +               DWC_ERROR("Cannot allocate memory for container->name");
6753 +               DWC_FREE(container);
6754 +               return;
6755 +       }
6756 +
6757 +       container->cb = cb;
6758 +       container->data = data;
6759 +       container->wq = wq;
6760 +       container->hz = 0;
6761 +
6762 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6763 +
6764 +       TASK_INIT(&container->task, 0, do_work, container);
6765 +
6766 +#ifdef DEBUG
6767 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6768 +#endif
6769 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6770 +}
6771 +
6772 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
6773 +                               void *data, uint32_t time, char *format, ...)
6774 +{
6775 +       dwc_irqflags_t flags;
6776 +       work_container_t *container;
6777 +       static char name[128];
6778 +       struct timeval tv;
6779 +       va_list args;
6780 +
6781 +       va_start(args, format);
6782 +       DWC_VSNPRINTF(name, 128, format, args);
6783 +       va_end(args);
6784 +
6785 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
6786 +       wq->pending++;
6787 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
6788 +       DWC_WAITQ_TRIGGER(wq->waitq);
6789 +
6790 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
6791 +       if (!container) {
6792 +               DWC_ERROR("Cannot allocate memory for container");
6793 +               return;
6794 +       }
6795 +
6796 +       container->name = DWC_STRDUP(name);
6797 +       if (!container->name) {
6798 +               DWC_ERROR("Cannot allocate memory for container->name");
6799 +               DWC_FREE(container);
6800 +               return;
6801 +       }
6802 +
6803 +       container->cb = cb;
6804 +       container->data = data;
6805 +       container->wq = wq;
6806 +
6807 +       tv.tv_sec = time / 1000;
6808 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
6809 +       container->hz = tvtohz(&tv);
6810 +
6811 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
6812 +
6813 +       TASK_INIT(&container->task, 0, do_work, container);
6814 +
6815 +#ifdef DEBUG
6816 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
6817 +#endif
6818 +       taskqueue_enqueue_fast(wq->taskq, &container->task);
6819 +}
6820 +
6821 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
6822 +{
6823 +       return wq->pending;
6824 +}
6825 --- /dev/null
6826 +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
6827 @@ -0,0 +1,1421 @@
6828 +#include <linux/kernel.h>
6829 +#include <linux/init.h>
6830 +#include <linux/module.h>
6831 +#include <linux/kthread.h>
6832 +
6833 +#ifdef DWC_CCLIB
6834 +# include "dwc_cc.h"
6835 +#endif
6836 +
6837 +#ifdef DWC_CRYPTOLIB
6838 +# include "dwc_modpow.h"
6839 +# include "dwc_dh.h"
6840 +# include "dwc_crypto.h"
6841 +#endif
6842 +
6843 +#ifdef DWC_NOTIFYLIB
6844 +# include "dwc_notifier.h"
6845 +#endif
6846 +
6847 +/* OS-Level Implementations */
6848 +
6849 +/* This is the Linux kernel implementation of the DWC platform library. */
6850 +#include <linux/moduleparam.h>
6851 +#include <linux/ctype.h>
6852 +#include <linux/crypto.h>
6853 +#include <linux/delay.h>
6854 +#include <linux/device.h>
6855 +#include <linux/dma-mapping.h>
6856 +#include <linux/cdev.h>
6857 +#include <linux/errno.h>
6858 +#include <linux/interrupt.h>
6859 +#include <linux/jiffies.h>
6860 +#include <linux/list.h>
6861 +#include <linux/pci.h>
6862 +#include <linux/random.h>
6863 +#include <linux/scatterlist.h>
6864 +#include <linux/slab.h>
6865 +#include <linux/stat.h>
6866 +#include <linux/string.h>
6867 +#include <linux/timer.h>
6868 +#include <linux/usb.h>
6869 +
6870 +#include <linux/version.h>
6871 +
6872 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
6873 +# include <linux/usb/gadget.h>
6874 +#else
6875 +# include <linux/usb_gadget.h>
6876 +#endif
6877 +
6878 +#include <asm/io.h>
6879 +#include <asm/page.h>
6880 +#include <asm/uaccess.h>
6881 +#include <asm/unaligned.h>
6882 +
6883 +#include "dwc_os.h"
6884 +#include "dwc_list.h"
6885 +
6886 +
6887 +/* MISC */
6888 +
6889 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
6890 +{
6891 +       return memset(dest, byte, size);
6892 +}
6893 +
6894 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
6895 +{
6896 +       return memcpy(dest, src, size);
6897 +}
6898 +
6899 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
6900 +{
6901 +       return memmove(dest, src, size);
6902 +}
6903 +
6904 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
6905 +{
6906 +       return memcmp(m1, m2, size);
6907 +}
6908 +
6909 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
6910 +{
6911 +       return strncmp(s1, s2, size);
6912 +}
6913 +
6914 +int DWC_STRCMP(void *s1, void *s2)
6915 +{
6916 +       return strcmp(s1, s2);
6917 +}
6918 +
6919 +int DWC_STRLEN(char const *str)
6920 +{
6921 +       return strlen(str);
6922 +}
6923 +
6924 +char *DWC_STRCPY(char *to, char const *from)
6925 +{
6926 +       return strcpy(to, from);
6927 +}
6928 +
6929 +char *DWC_STRDUP(char const *str)
6930 +{
6931 +       int len = DWC_STRLEN(str) + 1;
6932 +       char *new = DWC_ALLOC_ATOMIC(len);
6933 +
6934 +       if (!new) {
6935 +               return NULL;
6936 +       }
6937 +
6938 +       DWC_MEMCPY(new, str, len);
6939 +       return new;
6940 +}
6941 +
6942 +int DWC_ATOI(const char *str, int32_t *value)
6943 +{
6944 +       char *end = NULL;
6945 +
6946 +       *value = simple_strtol(str, &end, 0);
6947 +       if (*end == '\0') {
6948 +               return 0;
6949 +       }
6950 +
6951 +       return -1;
6952 +}
6953 +
6954 +int DWC_ATOUI(const char *str, uint32_t *value)
6955 +{
6956 +       char *end = NULL;
6957 +
6958 +       *value = simple_strtoul(str, &end, 0);
6959 +       if (*end == '\0') {
6960 +               return 0;
6961 +       }
6962 +
6963 +       return -1;
6964 +}
6965 +
6966 +
6967 +#ifdef DWC_UTFLIB
6968 +/* From usbstring.c */
6969 +
6970 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
6971 +{
6972 +       int     count = 0;
6973 +       u8      c;
6974 +       u16     uchar;
6975 +
6976 +       /* this insists on correct encodings, though not minimal ones.
6977 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
6978 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
6979 +        */
6980 +       while (len != 0 && (c = (u8) *s++) != 0) {
6981 +               if (unlikely(c & 0x80)) {
6982 +                       // 2-byte sequence:
6983 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
6984 +                       if ((c & 0xe0) == 0xc0) {
6985 +                               uchar = (c & 0x1f) << 6;
6986 +
6987 +                               c = (u8) *s++;
6988 +                               if ((c & 0xc0) != 0xc0)
6989 +                                       goto fail;
6990 +                               c &= 0x3f;
6991 +                               uchar |= c;
6992 +
6993 +                       // 3-byte sequence (most CJKV characters):
6994 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
6995 +                       } else if ((c & 0xf0) == 0xe0) {
6996 +                               uchar = (c & 0x0f) << 12;
6997 +
6998 +                               c = (u8) *s++;
6999 +                               if ((c & 0xc0) != 0xc0)
7000 +                                       goto fail;
7001 +                               c &= 0x3f;
7002 +                               uchar |= c << 6;
7003 +
7004 +                               c = (u8) *s++;
7005 +                               if ((c & 0xc0) != 0xc0)
7006 +                                       goto fail;
7007 +                               c &= 0x3f;
7008 +                               uchar |= c;
7009 +
7010 +                               /* no bogus surrogates */
7011 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
7012 +                                       goto fail;
7013 +
7014 +                       // 4-byte sequence (surrogate pairs, currently rare):
7015 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
7016 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
7017 +                       // (uuuuu = wwww + 1)
7018 +                       // FIXME accept the surrogate code points (only)
7019 +                       } else
7020 +                               goto fail;
7021 +               } else
7022 +                       uchar = c;
7023 +               put_unaligned (cpu_to_le16 (uchar), cp++);
7024 +               count++;
7025 +               len--;
7026 +       }
7027 +       return count;
7028 +fail:
7029 +       return -1;
7030 +}
7031 +#endif /* DWC_UTFLIB */
7032 +
7033 +
7034 +/* dwc_debug.h */
7035 +
7036 +dwc_bool_t DWC_IN_IRQ(void)
7037 +{
7038 +       return in_irq();
7039 +}
7040 +
7041 +dwc_bool_t DWC_IN_BH(void)
7042 +{
7043 +       return in_softirq();
7044 +}
7045 +
7046 +void DWC_VPRINTF(char *format, va_list args)
7047 +{
7048 +       vprintk(format, args);
7049 +}
7050 +
7051 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
7052 +{
7053 +       return vsnprintf(str, size, format, args);
7054 +}
7055 +
7056 +void DWC_PRINTF(char *format, ...)
7057 +{
7058 +       va_list args;
7059 +
7060 +       va_start(args, format);
7061 +       DWC_VPRINTF(format, args);
7062 +       va_end(args);
7063 +}
7064 +
7065 +int DWC_SPRINTF(char *buffer, char *format, ...)
7066 +{
7067 +       int retval;
7068 +       va_list args;
7069 +
7070 +       va_start(args, format);
7071 +       retval = vsprintf(buffer, format, args);
7072 +       va_end(args);
7073 +       return retval;
7074 +}
7075 +
7076 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
7077 +{
7078 +       int retval;
7079 +       va_list args;
7080 +
7081 +       va_start(args, format);
7082 +       retval = vsnprintf(buffer, size, format, args);
7083 +       va_end(args);
7084 +       return retval;
7085 +}
7086 +
7087 +void __DWC_WARN(char *format, ...)
7088 +{
7089 +       va_list args;
7090 +
7091 +       va_start(args, format);
7092 +       DWC_PRINTF(KERN_WARNING);
7093 +       DWC_VPRINTF(format, args);
7094 +       va_end(args);
7095 +}
7096 +
7097 +void __DWC_ERROR(char *format, ...)
7098 +{
7099 +       va_list args;
7100 +
7101 +       va_start(args, format);
7102 +       DWC_PRINTF(KERN_ERR);
7103 +       DWC_VPRINTF(format, args);
7104 +       va_end(args);
7105 +}
7106 +
7107 +void DWC_EXCEPTION(char *format, ...)
7108 +{
7109 +       va_list args;
7110 +
7111 +       va_start(args, format);
7112 +       DWC_PRINTF(KERN_ERR);
7113 +       DWC_VPRINTF(format, args);
7114 +       va_end(args);
7115 +       BUG_ON(1);
7116 +}
7117 +
7118 +#ifdef DEBUG
7119 +void __DWC_DEBUG(char *format, ...)
7120 +{
7121 +       va_list args;
7122 +
7123 +       va_start(args, format);
7124 +       DWC_PRINTF(KERN_DEBUG);
7125 +       DWC_VPRINTF(format, args);
7126 +       va_end(args);
7127 +}
7128 +#endif
7129 +
7130 +
7131 +/* dwc_mem.h */
7132 +
7133 +#if 0
7134 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
7135 +                               uint32_t align,
7136 +                               uint32_t alloc)
7137 +{
7138 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
7139 +                                               size, align, alloc);
7140 +       return (dwc_pool_t *)pool;
7141 +}
7142 +
7143 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
7144 +{
7145 +       dma_pool_destroy((struct dma_pool *)pool);
7146 +}
7147 +
7148 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7149 +{
7150 +       return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
7151 +}
7152 +
7153 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
7154 +{
7155 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
7156 +       memset(..);
7157 +}
7158 +
7159 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
7160 +{
7161 +       dma_pool_free(pool, vaddr, daddr);
7162 +}
7163 +#endif
7164 +
7165 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7166 +{
7167 +#ifdef xxCOSIM /* Only works for 32-bit cosim */
7168 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);
7169 +#else
7170 +       void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);
7171 +#endif
7172 +       if (!buf) {
7173 +               return NULL;
7174 +       }
7175 +
7176 +       memset(buf, 0, (size_t)size);
7177 +       return buf;
7178 +}
7179 +
7180 +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
7181 +{
7182 +       void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
7183 +       if (!buf) {
7184 +               return NULL;
7185 +       }
7186 +       memset(buf, 0, (size_t)size);
7187 +       return buf;
7188 +}
7189 +
7190 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
7191 +{
7192 +       dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);
7193 +}
7194 +
7195 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
7196 +{
7197 +       return kzalloc(size, GFP_KERNEL);
7198 +}
7199 +
7200 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
7201 +{
7202 +       return kzalloc(size, GFP_ATOMIC);
7203 +}
7204 +
7205 +void __DWC_FREE(void *mem_ctx, void *addr)
7206 +{
7207 +       kfree(addr);
7208 +}
7209 +
7210 +
7211 +#ifdef DWC_CRYPTOLIB
7212 +/* dwc_crypto.h */
7213 +
7214 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
7215 +{
7216 +       get_random_bytes(buffer, length);
7217 +}
7218 +
7219 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
7220 +{
7221 +       struct crypto_blkcipher *tfm;
7222 +       struct blkcipher_desc desc;
7223 +       struct scatterlist sgd;
7224 +       struct scatterlist sgs;
7225 +
7226 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
7227 +       if (tfm == NULL) {
7228 +               printk("failed to load transform for aes CBC\n");
7229 +               return -1;
7230 +       }
7231 +
7232 +       crypto_blkcipher_setkey(tfm, key, keylen);
7233 +       crypto_blkcipher_set_iv(tfm, iv, 16);
7234 +
7235 +       sg_init_one(&sgd, out, messagelen);
7236 +       sg_init_one(&sgs, message, messagelen);
7237 +
7238 +       desc.tfm = tfm;
7239 +       desc.flags = 0;
7240 +
7241 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
7242 +               crypto_free_blkcipher(tfm);
7243 +               DWC_ERROR("AES CBC encryption failed");
7244 +               return -1;
7245 +       }
7246 +
7247 +       crypto_free_blkcipher(tfm);
7248 +       return 0;
7249 +}
7250 +
7251 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
7252 +{
7253 +       struct crypto_hash *tfm;
7254 +       struct hash_desc desc;
7255 +       struct scatterlist sg;
7256 +
7257 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
7258 +       if (IS_ERR(tfm)) {
7259 +               DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
7260 +               return 0;
7261 +       }
7262 +       desc.tfm = tfm;
7263 +       desc.flags = 0;
7264 +
7265 +       sg_init_one(&sg, message, len);
7266 +       crypto_hash_digest(&desc, &sg, len, out);
7267 +       crypto_free_hash(tfm);
7268 +
7269 +       return 1;
7270 +}
7271 +
7272 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
7273 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
7274 +{
7275 +       struct crypto_hash *tfm;
7276 +       struct hash_desc desc;
7277 +       struct scatterlist sg;
7278 +
7279 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
7280 +       if (IS_ERR(tfm)) {
7281 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
7282 +               return 0;
7283 +       }
7284 +       desc.tfm = tfm;
7285 +       desc.flags = 0;
7286 +
7287 +       sg_init_one(&sg, message, messagelen);
7288 +       crypto_hash_setkey(tfm, key, keylen);
7289 +       crypto_hash_digest(&desc, &sg, messagelen, out);
7290 +       crypto_free_hash(tfm);
7291 +
7292 +       return 1;
7293 +}
7294 +#endif /* DWC_CRYPTOLIB */
7295 +
7296 +
7297 +/* Byte Ordering Conversions */
7298 +
7299 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
7300 +{
7301 +#ifdef __LITTLE_ENDIAN
7302 +       return *p;
7303 +#else
7304 +       uint8_t *u_p = (uint8_t *)p;
7305 +
7306 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7307 +#endif
7308 +}
7309 +
7310 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
7311 +{
7312 +#ifdef __BIG_ENDIAN
7313 +       return *p;
7314 +#else
7315 +       uint8_t *u_p = (uint8_t *)p;
7316 +
7317 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7318 +#endif
7319 +}
7320 +
7321 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
7322 +{
7323 +#ifdef __LITTLE_ENDIAN
7324 +       return *p;
7325 +#else
7326 +       uint8_t *u_p = (uint8_t *)p;
7327 +
7328 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7329 +#endif
7330 +}
7331 +
7332 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
7333 +{
7334 +#ifdef __BIG_ENDIAN
7335 +       return *p;
7336 +#else
7337 +       uint8_t *u_p = (uint8_t *)p;
7338 +
7339 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
7340 +#endif
7341 +}
7342 +
7343 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
7344 +{
7345 +#ifdef __LITTLE_ENDIAN
7346 +       return *p;
7347 +#else
7348 +       uint8_t *u_p = (uint8_t *)p;
7349 +       return (u_p[1] | (u_p[0] << 8));
7350 +#endif
7351 +}
7352 +
7353 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
7354 +{
7355 +#ifdef __BIG_ENDIAN
7356 +       return *p;
7357 +#else
7358 +       uint8_t *u_p = (uint8_t *)p;
7359 +       return (u_p[1] | (u_p[0] << 8));
7360 +#endif
7361 +}
7362 +
7363 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
7364 +{
7365 +#ifdef __LITTLE_ENDIAN
7366 +       return *p;
7367 +#else
7368 +       uint8_t *u_p = (uint8_t *)p;
7369 +       return (u_p[1] | (u_p[0] << 8));
7370 +#endif
7371 +}
7372 +
7373 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
7374 +{
7375 +#ifdef __BIG_ENDIAN
7376 +       return *p;
7377 +#else
7378 +       uint8_t *u_p = (uint8_t *)p;
7379 +       return (u_p[1] | (u_p[0] << 8));
7380 +#endif
7381 +}
7382 +
7383 +
7384 +/* Registers */
7385 +
7386 +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
7387 +{
7388 +       return readl(reg);
7389 +}
7390 +
7391 +#if 0
7392 +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
7393 +{
7394 +}
7395 +#endif
7396 +
7397 +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
7398 +{
7399 +       writel(value, reg);
7400 +}
7401 +
7402 +#if 0
7403 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
7404 +{
7405 +}
7406 +#endif
7407 +
7408 +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
7409 +{
7410 +       writel((readl(reg) & ~clear_mask) | set_mask, reg);
7411 +}
7412 +
7413 +#if 0
7414 +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)
7415 +{
7416 +}
7417 +#endif
7418 +
7419 +
7420 +/* Locking */
7421 +
7422 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
7423 +{
7424 +       spinlock_t *sl = (spinlock_t *)1;
7425 +
7426 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7427 +       sl = DWC_ALLOC(sizeof(*sl));
7428 +       if (!sl) {
7429 +               DWC_ERROR("Cannot allocate memory for spinlock\n");
7430 +               return NULL;
7431 +       }
7432 +
7433 +       spin_lock_init(sl);
7434 +#endif
7435 +       return (dwc_spinlock_t *)sl;
7436 +}
7437 +
7438 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
7439 +{
7440 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7441 +       DWC_FREE(lock);
7442 +#endif
7443 +}
7444 +
7445 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
7446 +{
7447 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7448 +       spin_lock((spinlock_t *)lock);
7449 +#endif
7450 +}
7451 +
7452 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
7453 +{
7454 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7455 +       spin_unlock((spinlock_t *)lock);
7456 +#endif
7457 +}
7458 +
7459 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
7460 +{
7461 +       dwc_irqflags_t f;
7462 +
7463 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7464 +       spin_lock_irqsave((spinlock_t *)lock, f);
7465 +#else
7466 +       local_irq_save(f);
7467 +#endif
7468 +       *flags = f;
7469 +}
7470 +
7471 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
7472 +{
7473 +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
7474 +       spin_unlock_irqrestore((spinlock_t *)lock, flags);
7475 +#else
7476 +       local_irq_restore(flags);
7477 +#endif
7478 +}
7479 +
7480 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
7481 +{
7482 +       struct mutex *m;
7483 +       dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));
7484 +
7485 +       if (!mutex) {
7486 +               DWC_ERROR("Cannot allocate memory for mutex\n");
7487 +               return NULL;
7488 +       }
7489 +
7490 +       m = (struct mutex *)mutex;
7491 +       mutex_init(m);
7492 +       return mutex;
7493 +}
7494 +
7495 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
7496 +#else
7497 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
7498 +{
7499 +       mutex_destroy((struct mutex *)mutex);
7500 +       DWC_FREE(mutex);
7501 +}
7502 +#endif
7503 +
7504 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
7505 +{
7506 +       struct mutex *m = (struct mutex *)mutex;
7507 +       mutex_lock(m);
7508 +}
7509 +
7510 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
7511 +{
7512 +       struct mutex *m = (struct mutex *)mutex;
7513 +       return mutex_trylock(m);
7514 +}
7515 +
7516 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
7517 +{
7518 +       struct mutex *m = (struct mutex *)mutex;
7519 +       mutex_unlock(m);
7520 +}
7521 +
7522 +
7523 +/* Timing */
7524 +
7525 +void DWC_UDELAY(uint32_t usecs)
7526 +{
7527 +       udelay(usecs);
7528 +}
7529 +
7530 +void DWC_MDELAY(uint32_t msecs)
7531 +{
7532 +       mdelay(msecs);
7533 +}
7534 +
7535 +void DWC_MSLEEP(uint32_t msecs)
7536 +{
7537 +       msleep(msecs);
7538 +}
7539 +
7540 +uint32_t DWC_TIME(void)
7541 +{
7542 +       return jiffies_to_msecs(jiffies);
7543 +}
7544 +
7545 +
7546 +/* Timers */
7547 +
7548 +struct dwc_timer {
7549 +       struct timer_list *t;
7550 +       char *name;
7551 +       dwc_timer_callback_t cb;
7552 +       void *data;
7553 +       uint8_t scheduled;
7554 +       dwc_spinlock_t *lock;
7555 +};
7556 +
7557 +static void timer_callback(unsigned long data)
7558 +{
7559 +       dwc_timer_t *timer = (dwc_timer_t *)data;
7560 +       dwc_irqflags_t flags;
7561 +
7562 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7563 +       timer->scheduled = 0;
7564 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7565 +       DWC_DEBUGC("Timer %s callback", timer->name);
7566 +       timer->cb(timer->data);
7567 +}
7568 +
7569 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
7570 +{
7571 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
7572 +
7573 +       if (!t) {
7574 +               DWC_ERROR("Cannot allocate memory for timer");
7575 +               return NULL;
7576 +       }
7577 +
7578 +       t->t = DWC_ALLOC(sizeof(*t->t));
7579 +       if (!t->t) {
7580 +               DWC_ERROR("Cannot allocate memory for timer->t");
7581 +               goto no_timer;
7582 +       }
7583 +
7584 +       t->name = DWC_STRDUP(name);
7585 +       if (!t->name) {
7586 +               DWC_ERROR("Cannot allocate memory for timer->name");
7587 +               goto no_name;
7588 +       }
7589 +
7590 +       t->lock = DWC_SPINLOCK_ALLOC();
7591 +       if (!t->lock) {
7592 +               DWC_ERROR("Cannot allocate memory for lock");
7593 +               goto no_lock;
7594 +       }
7595 +
7596 +       t->scheduled = 0;
7597 +       t->t->base = &boot_tvec_bases;
7598 +       t->t->expires = jiffies;
7599 +       setup_timer(t->t, timer_callback, (unsigned long)t);
7600 +
7601 +       t->cb = cb;
7602 +       t->data = data;
7603 +
7604 +       return t;
7605 +
7606 + no_lock:
7607 +       DWC_FREE(t->name);
7608 + no_name:
7609 +       DWC_FREE(t->t);
7610 + no_timer:
7611 +       DWC_FREE(t);
7612 +       return NULL;
7613 +}
7614 +
7615 +void DWC_TIMER_FREE(dwc_timer_t *timer)
7616 +{
7617 +       dwc_irqflags_t flags;
7618 +
7619 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7620 +
7621 +       if (timer->scheduled) {
7622 +               del_timer(timer->t);
7623 +               timer->scheduled = 0;
7624 +       }
7625 +
7626 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7627 +       DWC_SPINLOCK_FREE(timer->lock);
7628 +       DWC_FREE(timer->t);
7629 +       DWC_FREE(timer->name);
7630 +       DWC_FREE(timer);
7631 +}
7632 +
7633 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
7634 +{
7635 +       dwc_irqflags_t flags;
7636 +
7637 +       DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
7638 +
7639 +       if (!timer->scheduled) {
7640 +               timer->scheduled = 1;
7641 +               DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);
7642 +               timer->t->expires = jiffies + msecs_to_jiffies(time);
7643 +               add_timer(timer->t);
7644 +       } else {
7645 +               DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);
7646 +               mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
7647 +       }
7648 +
7649 +       DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
7650 +}
7651 +
7652 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
7653 +{
7654 +       del_timer(timer->t);
7655 +}
7656 +
7657 +
7658 +/* Wait Queues */
7659 +
7660 +struct dwc_waitq {
7661 +       wait_queue_head_t queue;
7662 +       int abort;
7663 +};
7664 +
7665 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
7666 +{
7667 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
7668 +
7669 +       if (!wq) {
7670 +               DWC_ERROR("Cannot allocate memory for waitqueue\n");
7671 +               return NULL;
7672 +       }
7673 +
7674 +       init_waitqueue_head(&wq->queue);
7675 +       wq->abort = 0;
7676 +       return wq;
7677 +}
7678 +
7679 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
7680 +{
7681 +       DWC_FREE(wq);
7682 +}
7683 +
7684 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
7685 +{
7686 +       int result = wait_event_interruptible(wq->queue,
7687 +                                             cond(data) || wq->abort);
7688 +       if (result == -ERESTARTSYS) {
7689 +               wq->abort = 0;
7690 +               return -DWC_E_RESTART;
7691 +       }
7692 +
7693 +       if (wq->abort == 1) {
7694 +               wq->abort = 0;
7695 +               return -DWC_E_ABORT;
7696 +       }
7697 +
7698 +       wq->abort = 0;
7699 +
7700 +       if (result == 0) {
7701 +               return 0;
7702 +       }
7703 +
7704 +       return -DWC_E_UNKNOWN;
7705 +}
7706 +
7707 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
7708 +                              void *data, int32_t msecs)
7709 +{
7710 +       int32_t tmsecs;
7711 +       int result = wait_event_interruptible_timeout(wq->queue,
7712 +                                                     cond(data) || wq->abort,
7713 +                                                     msecs_to_jiffies(msecs));
7714 +       if (result == -ERESTARTSYS) {
7715 +               wq->abort = 0;
7716 +               return -DWC_E_RESTART;
7717 +       }
7718 +
7719 +       if (wq->abort == 1) {
7720 +               wq->abort = 0;
7721 +               return -DWC_E_ABORT;
7722 +       }
7723 +
7724 +       wq->abort = 0;
7725 +
7726 +       if (result > 0) {
7727 +               tmsecs = jiffies_to_msecs(result);
7728 +               if (!tmsecs) {
7729 +                       return 1;
7730 +               }
7731 +
7732 +               return tmsecs;
7733 +       }
7734 +
7735 +       if (result == 0) {
7736 +               return -DWC_E_TIMEOUT;
7737 +       }
7738 +
7739 +       return -DWC_E_UNKNOWN;
7740 +}
7741 +
7742 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
7743 +{
7744 +       wq->abort = 0;
7745 +       wake_up_interruptible(&wq->queue);
7746 +}
7747 +
7748 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
7749 +{
7750 +       wq->abort = 1;
7751 +       wake_up_interruptible(&wq->queue);
7752 +}
7753 +
7754 +
7755 +/* Threading */
7756 +
7757 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
7758 +{
7759 +       struct task_struct *thread = kthread_run(func, data, name);
7760 +
7761 +       if (thread == ERR_PTR(-ENOMEM)) {
7762 +               return NULL;
7763 +       }
7764 +
7765 +       return (dwc_thread_t *)thread;
7766 +}
7767 +
7768 +int DWC_THREAD_STOP(dwc_thread_t *thread)
7769 +{
7770 +       return kthread_stop((struct task_struct *)thread);
7771 +}
7772 +
7773 +dwc_bool_t DWC_THREAD_SHOULD_STOP(void)
7774 +{
7775 +       return kthread_should_stop();
7776 +}
7777 +
7778 +
7779 +/* tasklets
7780 + - run in interrupt context (cannot sleep)
7781 + - each tasklet runs on a single CPU
7782 + - different tasklets can be running simultaneously on different CPUs
7783 + */
7784 +struct dwc_tasklet {
7785 +       struct tasklet_struct t;
7786 +       dwc_tasklet_callback_t cb;
7787 +       void *data;
7788 +};
7789 +
7790 +static void tasklet_callback(unsigned long data)
7791 +{
7792 +       dwc_tasklet_t *t = (dwc_tasklet_t *)data;
7793 +       t->cb(t->data);
7794 +}
7795 +
7796 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
7797 +{
7798 +       dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
7799 +
7800 +       if (t) {
7801 +               t->cb = cb;
7802 +               t->data = data;
7803 +               tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
7804 +       } else {
7805 +               DWC_ERROR("Cannot allocate memory for tasklet\n");
7806 +       }
7807 +
7808 +       return t;
7809 +}
7810 +
7811 +void DWC_TASK_FREE(dwc_tasklet_t *task)
7812 +{
7813 +       DWC_FREE(task);
7814 +}
7815 +
7816 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
7817 +{
7818 +       tasklet_schedule(&task->t);
7819 +}
7820 +
7821 +
7822 +/* workqueues
7823 + - run in process context (can sleep)
7824 + */
7825 +typedef struct work_container {
7826 +       dwc_work_callback_t cb;
7827 +       void *data;
7828 +       dwc_workq_t *wq;
7829 +       char *name;
7830 +
7831 +#ifdef DEBUG
7832 +       DWC_CIRCLEQ_ENTRY(work_container) entry;
7833 +#endif
7834 +       struct delayed_work work;
7835 +} work_container_t;
7836 +
7837 +#ifdef DEBUG
7838 +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
7839 +#endif
7840 +
7841 +struct dwc_workq {
7842 +       struct workqueue_struct *wq;
7843 +       dwc_spinlock_t *lock;
7844 +       dwc_waitq_t *waitq;
7845 +       int pending;
7846 +
7847 +#ifdef DEBUG
7848 +       struct work_container_queue entries;
7849 +#endif
7850 +};
7851 +
7852 +static void do_work(struct work_struct *work)
7853 +{
7854 +       dwc_irqflags_t flags;
7855 +       struct delayed_work *dw = container_of(work, struct delayed_work, work);
7856 +       work_container_t *container = container_of(dw, struct work_container, work);
7857 +       dwc_workq_t *wq = container->wq;
7858 +
7859 +       container->cb(container->data);
7860 +
7861 +#ifdef DEBUG
7862 +       DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
7863 +#endif
7864 +       DWC_DEBUGC("Work done: %s, container=%p", container->name, container);
7865 +       if (container->name) {
7866 +               DWC_FREE(container->name);
7867 +       }
7868 +       DWC_FREE(container);
7869 +
7870 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7871 +       wq->pending--;
7872 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7873 +       DWC_WAITQ_TRIGGER(wq->waitq);
7874 +}
7875 +
7876 +static int work_done(void *data)
7877 +{
7878 +       dwc_workq_t *workq = (dwc_workq_t *)data;
7879 +       return workq->pending == 0;
7880 +}
7881 +
7882 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
7883 +{
7884 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
7885 +}
7886 +
7887 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
7888 +{
7889 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
7890 +
7891 +       if (!wq) {
7892 +               return NULL;
7893 +       }
7894 +
7895 +       wq->wq = create_singlethread_workqueue(name);
7896 +       if (!wq->wq) {
7897 +               goto no_wq;
7898 +       }
7899 +
7900 +       wq->pending = 0;
7901 +
7902 +       wq->lock = DWC_SPINLOCK_ALLOC();
7903 +       if (!wq->lock) {
7904 +               goto no_lock;
7905 +       }
7906 +
7907 +       wq->waitq = DWC_WAITQ_ALLOC();
7908 +       if (!wq->waitq) {
7909 +               goto no_waitq;
7910 +       }
7911 +
7912 +#ifdef DEBUG
7913 +       DWC_CIRCLEQ_INIT(&wq->entries);
7914 +#endif
7915 +       return wq;
7916 +
7917 + no_waitq:
7918 +       DWC_SPINLOCK_FREE(wq->lock);
7919 + no_lock:
7920 +       destroy_workqueue(wq->wq);
7921 + no_wq:
7922 +       DWC_FREE(wq);
7923 +
7924 +       return NULL;
7925 +}
7926 +
7927 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
7928 +{
7929 +#ifdef DEBUG
7930 +       if (wq->pending != 0) {
7931 +               struct work_container *wc;
7932 +               DWC_ERROR("Destroying work queue with pending work");
7933 +               DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
7934 +                       DWC_ERROR("Work %s still pending", wc->name);
7935 +               }
7936 +       }
7937 +#endif
7938 +       destroy_workqueue(wq->wq);
7939 +       DWC_SPINLOCK_FREE(wq->lock);
7940 +       DWC_WAITQ_FREE(wq->waitq);
7941 +       DWC_FREE(wq);
7942 +}
7943 +
7944 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
7945 +                       char *format, ...)
7946 +{
7947 +       dwc_irqflags_t flags;
7948 +       work_container_t *container;
7949 +       static char name[128];
7950 +       va_list args;
7951 +
7952 +       va_start(args, format);
7953 +       DWC_VSNPRINTF(name, 128, format, args);
7954 +       va_end(args);
7955 +
7956 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7957 +       wq->pending++;
7958 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
7959 +       DWC_WAITQ_TRIGGER(wq->waitq);
7960 +
7961 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
7962 +       if (!container) {
7963 +               DWC_ERROR("Cannot allocate memory for container\n");
7964 +               return;
7965 +       }
7966 +
7967 +       container->name = DWC_STRDUP(name);
7968 +       if (!container->name) {
7969 +               DWC_ERROR("Cannot allocate memory for container->name\n");
7970 +               DWC_FREE(container);
7971 +               return;
7972 +       }
7973 +
7974 +       container->cb = cb;
7975 +       container->data = data;
7976 +       container->wq = wq;
7977 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
7978 +       INIT_WORK(&container->work.work, do_work);
7979 +
7980 +#ifdef DEBUG
7981 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
7982 +#endif
7983 +       queue_work(wq->wq, &container->work.work);
7984 +}
7985 +
7986 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
7987 +                               void *data, uint32_t time, char *format, ...)
7988 +{
7989 +       dwc_irqflags_t flags;
7990 +       work_container_t *container;
7991 +       static char name[128];
7992 +       va_list args;
7993 +
7994 +       va_start(args, format);
7995 +       DWC_VSNPRINTF(name, 128, format, args);
7996 +       va_end(args);
7997 +
7998 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
7999 +       wq->pending++;
8000 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
8001 +       DWC_WAITQ_TRIGGER(wq->waitq);
8002 +
8003 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
8004 +       if (!container) {
8005 +               DWC_ERROR("Cannot allocate memory for container\n");
8006 +               return;
8007 +       }
8008 +
8009 +       container->name = DWC_STRDUP(name);
8010 +       if (!container->name) {
8011 +               DWC_ERROR("Cannot allocate memory for container->name\n");
8012 +               DWC_FREE(container);
8013 +               return;
8014 +       }
8015 +
8016 +       container->cb = cb;
8017 +       container->data = data;
8018 +       container->wq = wq;
8019 +       DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
8020 +       INIT_DELAYED_WORK(&container->work, do_work);
8021 +
8022 +#ifdef DEBUG
8023 +       DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
8024 +#endif
8025 +       queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
8026 +}
8027 +
8028 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
8029 +{
8030 +       return wq->pending;
8031 +}
8032 +
8033 +
8034 +#ifdef DWC_LIBMODULE
8035 +
8036 +#ifdef DWC_CCLIB
8037 +/* CC */
8038 +EXPORT_SYMBOL(dwc_cc_if_alloc);
8039 +EXPORT_SYMBOL(dwc_cc_if_free);
8040 +EXPORT_SYMBOL(dwc_cc_clear);
8041 +EXPORT_SYMBOL(dwc_cc_add);
8042 +EXPORT_SYMBOL(dwc_cc_remove);
8043 +EXPORT_SYMBOL(dwc_cc_change);
8044 +EXPORT_SYMBOL(dwc_cc_data_for_save);
8045 +EXPORT_SYMBOL(dwc_cc_restore_from_data);
8046 +EXPORT_SYMBOL(dwc_cc_match_chid);
8047 +EXPORT_SYMBOL(dwc_cc_match_cdid);
8048 +EXPORT_SYMBOL(dwc_cc_ck);
8049 +EXPORT_SYMBOL(dwc_cc_chid);
8050 +EXPORT_SYMBOL(dwc_cc_cdid);
8051 +EXPORT_SYMBOL(dwc_cc_name);
8052 +#endif /* DWC_CCLIB */
8053 +
8054 +#ifdef DWC_CRYPTOLIB
8055 +# ifndef CONFIG_MACH_IPMATE
8056 +/* Modpow */
8057 +EXPORT_SYMBOL(dwc_modpow);
8058 +
8059 +/* DH */
8060 +EXPORT_SYMBOL(dwc_dh_modpow);
8061 +EXPORT_SYMBOL(dwc_dh_derive_keys);
8062 +EXPORT_SYMBOL(dwc_dh_pk);
8063 +# endif        /* CONFIG_MACH_IPMATE */
8064 +
8065 +/* Crypto */
8066 +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
8067 +EXPORT_SYMBOL(dwc_wusb_cmf);
8068 +EXPORT_SYMBOL(dwc_wusb_prf);
8069 +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
8070 +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
8071 +EXPORT_SYMBOL(dwc_wusb_gen_key);
8072 +EXPORT_SYMBOL(dwc_wusb_gen_mic);
8073 +#endif /* DWC_CRYPTOLIB */
8074 +
8075 +/* Notification */
8076 +#ifdef DWC_NOTIFYLIB
8077 +EXPORT_SYMBOL(dwc_alloc_notification_manager);
8078 +EXPORT_SYMBOL(dwc_free_notification_manager);
8079 +EXPORT_SYMBOL(dwc_register_notifier);
8080 +EXPORT_SYMBOL(dwc_unregister_notifier);
8081 +EXPORT_SYMBOL(dwc_add_observer);
8082 +EXPORT_SYMBOL(dwc_remove_observer);
8083 +EXPORT_SYMBOL(dwc_notify);
8084 +#endif
8085 +
8086 +/* Memory Debugging Routines */
8087 +#ifdef DWC_DEBUG_MEMORY
8088 +EXPORT_SYMBOL(dwc_alloc_debug);
8089 +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
8090 +EXPORT_SYMBOL(dwc_free_debug);
8091 +EXPORT_SYMBOL(dwc_dma_alloc_debug);
8092 +EXPORT_SYMBOL(dwc_dma_free_debug);
8093 +#endif
8094 +
8095 +EXPORT_SYMBOL(DWC_MEMSET);
8096 +EXPORT_SYMBOL(DWC_MEMCPY);
8097 +EXPORT_SYMBOL(DWC_MEMMOVE);
8098 +EXPORT_SYMBOL(DWC_MEMCMP);
8099 +EXPORT_SYMBOL(DWC_STRNCMP);
8100 +EXPORT_SYMBOL(DWC_STRCMP);
8101 +EXPORT_SYMBOL(DWC_STRLEN);
8102 +EXPORT_SYMBOL(DWC_STRCPY);
8103 +EXPORT_SYMBOL(DWC_STRDUP);
8104 +EXPORT_SYMBOL(DWC_ATOI);
8105 +EXPORT_SYMBOL(DWC_ATOUI);
8106 +
8107 +#ifdef DWC_UTFLIB
8108 +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
8109 +#endif /* DWC_UTFLIB */
8110 +
8111 +EXPORT_SYMBOL(DWC_IN_IRQ);
8112 +EXPORT_SYMBOL(DWC_IN_BH);
8113 +EXPORT_SYMBOL(DWC_VPRINTF);
8114 +EXPORT_SYMBOL(DWC_VSNPRINTF);
8115 +EXPORT_SYMBOL(DWC_PRINTF);
8116 +EXPORT_SYMBOL(DWC_SPRINTF);
8117 +EXPORT_SYMBOL(DWC_SNPRINTF);
8118 +EXPORT_SYMBOL(__DWC_WARN);
8119 +EXPORT_SYMBOL(__DWC_ERROR);
8120 +EXPORT_SYMBOL(DWC_EXCEPTION);
8121 +
8122 +#ifdef DEBUG
8123 +EXPORT_SYMBOL(__DWC_DEBUG);
8124 +#endif
8125 +
8126 +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
8127 +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
8128 +EXPORT_SYMBOL(__DWC_DMA_FREE);
8129 +EXPORT_SYMBOL(__DWC_ALLOC);
8130 +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
8131 +EXPORT_SYMBOL(__DWC_FREE);
8132 +
8133 +#ifdef DWC_CRYPTOLIB
8134 +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
8135 +EXPORT_SYMBOL(DWC_AES_CBC);
8136 +EXPORT_SYMBOL(DWC_SHA256);
8137 +EXPORT_SYMBOL(DWC_HMAC_SHA256);
8138 +#endif
8139 +
8140 +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
8141 +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
8142 +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
8143 +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
8144 +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
8145 +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
8146 +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
8147 +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
8148 +EXPORT_SYMBOL(DWC_READ_REG32);
8149 +EXPORT_SYMBOL(DWC_WRITE_REG32);
8150 +EXPORT_SYMBOL(DWC_MODIFY_REG32);
8151 +
8152 +#if 0
8153 +EXPORT_SYMBOL(DWC_READ_REG64);
8154 +EXPORT_SYMBOL(DWC_WRITE_REG64);
8155 +EXPORT_SYMBOL(DWC_MODIFY_REG64);
8156 +#endif
8157 +
8158 +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
8159 +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
8160 +EXPORT_SYMBOL(DWC_SPINLOCK);
8161 +EXPORT_SYMBOL(DWC_SPINUNLOCK);
8162 +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
8163 +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
8164 +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
8165 +
8166 +#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))
8167 +EXPORT_SYMBOL(DWC_MUTEX_FREE);
8168 +#endif
8169 +
8170 +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
8171 +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
8172 +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
8173 +EXPORT_SYMBOL(DWC_UDELAY);
8174 +EXPORT_SYMBOL(DWC_MDELAY);
8175 +EXPORT_SYMBOL(DWC_MSLEEP);
8176 +EXPORT_SYMBOL(DWC_TIME);
8177 +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
8178 +EXPORT_SYMBOL(DWC_TIMER_FREE);
8179 +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
8180 +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
8181 +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
8182 +EXPORT_SYMBOL(DWC_WAITQ_FREE);
8183 +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
8184 +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
8185 +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
8186 +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
8187 +EXPORT_SYMBOL(DWC_THREAD_RUN);
8188 +EXPORT_SYMBOL(DWC_THREAD_STOP);
8189 +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
8190 +EXPORT_SYMBOL(DWC_TASK_ALLOC);
8191 +EXPORT_SYMBOL(DWC_TASK_FREE);
8192 +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
8193 +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
8194 +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
8195 +EXPORT_SYMBOL(DWC_WORKQ_FREE);
8196 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
8197 +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
8198 +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
8199 +
8200 +static int dwc_common_port_init_module(void)
8201 +{
8202 +       int result = 0;
8203 +
8204 +       printk(KERN_DEBUG "Module dwc_common_port init\n" );
8205 +
8206 +#ifdef DWC_DEBUG_MEMORY
8207 +       result = dwc_memory_debug_start(NULL);
8208 +       if (result) {
8209 +               printk(KERN_ERR
8210 +                      "dwc_memory_debug_start() failed with error %d\n",
8211 +                      result);
8212 +               return result;
8213 +       }
8214 +#endif
8215 +
8216 +#ifdef DWC_NOTIFYLIB
8217 +       result = dwc_alloc_notification_manager(NULL, NULL);
8218 +       if (result) {
8219 +               printk(KERN_ERR
8220 +                      "dwc_alloc_notification_manager() failed with error %d\n",
8221 +                      result);
8222 +               return result;
8223 +       }
8224 +#endif
8225 +       return result;
8226 +}
8227 +
8228 +static void dwc_common_port_exit_module(void)
8229 +{
8230 +       printk(KERN_DEBUG "Module dwc_common_port exit\n" );
8231 +
8232 +#ifdef DWC_NOTIFYLIB
8233 +       dwc_free_notification_manager();
8234 +#endif
8235 +
8236 +#ifdef DWC_DEBUG_MEMORY
8237 +       dwc_memory_debug_stop();
8238 +#endif
8239 +}
8240 +
8241 +module_init(dwc_common_port_init_module);
8242 +module_exit(dwc_common_port_exit_module);
8243 +
8244 +MODULE_DESCRIPTION("DWC Common Library - Portable version");
8245 +MODULE_AUTHOR("Synopsys Inc.");
8246 +MODULE_LICENSE ("GPL");
8247 +
8248 +#endif /* DWC_LIBMODULE */
8249 --- /dev/null
8250 +++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
8251 @@ -0,0 +1,1275 @@
8252 +#include "dwc_os.h"
8253 +#include "dwc_list.h"
8254 +
8255 +#ifdef DWC_CCLIB
8256 +# include "dwc_cc.h"
8257 +#endif
8258 +
8259 +#ifdef DWC_CRYPTOLIB
8260 +# include "dwc_modpow.h"
8261 +# include "dwc_dh.h"
8262 +# include "dwc_crypto.h"
8263 +#endif
8264 +
8265 +#ifdef DWC_NOTIFYLIB
8266 +# include "dwc_notifier.h"
8267 +#endif
8268 +
8269 +/* OS-Level Implementations */
8270 +
8271 +/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */
8272 +
8273 +
8274 +/* MISC */
8275 +
8276 +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
8277 +{
8278 +       return memset(dest, byte, size);
8279 +}
8280 +
8281 +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
8282 +{
8283 +       return memcpy(dest, src, size);
8284 +}
8285 +
8286 +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
8287 +{
8288 +       bcopy(src, dest, size);
8289 +       return dest;
8290 +}
8291 +
8292 +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
8293 +{
8294 +       return memcmp(m1, m2, size);
8295 +}
8296 +
8297 +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
8298 +{
8299 +       return strncmp(s1, s2, size);
8300 +}
8301 +
8302 +int DWC_STRCMP(void *s1, void *s2)
8303 +{
8304 +       return strcmp(s1, s2);
8305 +}
8306 +
8307 +int DWC_STRLEN(char const *str)
8308 +{
8309 +       return strlen(str);
8310 +}
8311 +
8312 +char *DWC_STRCPY(char *to, char const *from)
8313 +{
8314 +       return strcpy(to, from);
8315 +}
8316 +
8317 +char *DWC_STRDUP(char const *str)
8318 +{
8319 +       int len = DWC_STRLEN(str) + 1;
8320 +       char *new = DWC_ALLOC_ATOMIC(len);
8321 +
8322 +       if (!new) {
8323 +               return NULL;
8324 +       }
8325 +
8326 +       DWC_MEMCPY(new, str, len);
8327 +       return new;
8328 +}
8329 +
8330 +int DWC_ATOI(char *str, int32_t *value)
8331 +{
8332 +       char *end = NULL;
8333 +
8334 +       /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'
8335 +        * should be equivalent on 2's complement machines
8336 +        */
8337 +       *value = strtoul(str, &end, 0);
8338 +       if (*end == '\0') {
8339 +               return 0;
8340 +       }
8341 +
8342 +       return -1;
8343 +}
8344 +
8345 +int DWC_ATOUI(char *str, uint32_t *value)
8346 +{
8347 +       char *end = NULL;
8348 +
8349 +       *value = strtoul(str, &end, 0);
8350 +       if (*end == '\0') {
8351 +               return 0;
8352 +       }
8353 +
8354 +       return -1;
8355 +}
8356 +
8357 +
8358 +#ifdef DWC_UTFLIB
8359 +/* From usbstring.c */
8360 +
8361 +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
8362 +{
8363 +       int     count = 0;
8364 +       u8      c;
8365 +       u16     uchar;
8366 +
8367 +       /* this insists on correct encodings, though not minimal ones.
8368 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
8369 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
8370 +        */
8371 +       while (len != 0 && (c = (u8) *s++) != 0) {
8372 +               if (unlikely(c & 0x80)) {
8373 +                       // 2-byte sequence:
8374 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
8375 +                       if ((c & 0xe0) == 0xc0) {
8376 +                               uchar = (c & 0x1f) << 6;
8377 +
8378 +                               c = (u8) *s++;
8379 +                               if ((c & 0xc0) != 0xc0)
8380 +                                       goto fail;
8381 +                               c &= 0x3f;
8382 +                               uchar |= c;
8383 +
8384 +                       // 3-byte sequence (most CJKV characters):
8385 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
8386 +                       } else if ((c & 0xf0) == 0xe0) {
8387 +                               uchar = (c & 0x0f) << 12;
8388 +
8389 +                               c = (u8) *s++;
8390 +                               if ((c & 0xc0) != 0xc0)
8391 +                                       goto fail;
8392 +                               c &= 0x3f;
8393 +                               uchar |= c << 6;
8394 +
8395 +                               c = (u8) *s++;
8396 +                               if ((c & 0xc0) != 0xc0)
8397 +                                       goto fail;
8398 +                               c &= 0x3f;
8399 +                               uchar |= c;
8400 +
8401 +                               /* no bogus surrogates */
8402 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
8403 +                                       goto fail;
8404 +
8405 +                       // 4-byte sequence (surrogate pairs, currently rare):
8406 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
8407 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
8408 +                       // (uuuuu = wwww + 1)
8409 +                       // FIXME accept the surrogate code points (only)
8410 +                       } else
8411 +                               goto fail;
8412 +               } else
8413 +                       uchar = c;
8414 +               put_unaligned (cpu_to_le16 (uchar), cp++);
8415 +               count++;
8416 +               len--;
8417 +       }
8418 +       return count;
8419 +fail:
8420 +       return -1;
8421 +}
8422 +
8423 +#endif /* DWC_UTFLIB */
8424 +
8425 +
8426 +/* dwc_debug.h */
8427 +
8428 +dwc_bool_t DWC_IN_IRQ(void)
8429 +{
8430 +//     return in_irq();
8431 +       return 0;
8432 +}
8433 +
8434 +dwc_bool_t DWC_IN_BH(void)
8435 +{
8436 +//     return in_softirq();
8437 +       return 0;
8438 +}
8439 +
8440 +void DWC_VPRINTF(char *format, va_list args)
8441 +{
8442 +       vprintf(format, args);
8443 +}
8444 +
8445 +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
8446 +{
8447 +       return vsnprintf(str, size, format, args);
8448 +}
8449 +
8450 +void DWC_PRINTF(char *format, ...)
8451 +{
8452 +       va_list args;
8453 +
8454 +       va_start(args, format);
8455 +       DWC_VPRINTF(format, args);
8456 +       va_end(args);
8457 +}
8458 +
8459 +int DWC_SPRINTF(char *buffer, char *format, ...)
8460 +{
8461 +       int retval;
8462 +       va_list args;
8463 +
8464 +       va_start(args, format);
8465 +       retval = vsprintf(buffer, format, args);
8466 +       va_end(args);
8467 +       return retval;
8468 +}
8469 +
8470 +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
8471 +{
8472 +       int retval;
8473 +       va_list args;
8474 +
8475 +       va_start(args, format);
8476 +       retval = vsnprintf(buffer, size, format, args);
8477 +       va_end(args);
8478 +       return retval;
8479 +}
8480 +
8481 +void __DWC_WARN(char *format, ...)
8482 +{
8483 +       va_list args;
8484 +
8485 +       va_start(args, format);
8486 +       DWC_VPRINTF(format, args);
8487 +       va_end(args);
8488 +}
8489 +
8490 +void __DWC_ERROR(char *format, ...)
8491 +{
8492 +       va_list args;
8493 +
8494 +       va_start(args, format);
8495 +       DWC_VPRINTF(format, args);
8496 +       va_end(args);
8497 +}
8498 +
8499 +void DWC_EXCEPTION(char *format, ...)
8500 +{
8501 +       va_list args;
8502 +
8503 +       va_start(args, format);
8504 +       DWC_VPRINTF(format, args);
8505 +       va_end(args);
8506 +//     BUG_ON(1);      ???
8507 +}
8508 +
8509 +#ifdef DEBUG
8510 +void __DWC_DEBUG(char *format, ...)
8511 +{
8512 +       va_list args;
8513 +
8514 +       va_start(args, format);
8515 +       DWC_VPRINTF(format, args);
8516 +       va_end(args);
8517 +}
8518 +#endif
8519 +
8520 +
8521 +/* dwc_mem.h */
8522 +
8523 +#if 0
8524 +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
8525 +                               uint32_t align,
8526 +                               uint32_t alloc)
8527 +{
8528 +       struct dma_pool *pool = dma_pool_create("Pool", NULL,
8529 +                                               size, align, alloc);
8530 +       return (dwc_pool_t *)pool;
8531 +}
8532 +
8533 +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
8534 +{
8535 +       dma_pool_destroy((struct dma_pool *)pool);
8536 +}
8537 +
8538 +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8539 +{
8540 +//     return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
8541 +       return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
8542 +}
8543 +
8544 +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
8545 +{
8546 +       void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
8547 +       memset(..);
8548 +}
8549 +
8550 +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
8551 +{
8552 +       dma_pool_free(pool, vaddr, daddr);
8553 +}
8554 +#endif
8555 +
8556 +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
8557 +{
8558 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8559 +       int error;
8560 +
8561 +       error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,
8562 +                                sizeof(dma->segs) / sizeof(dma->segs[0]),
8563 +                                &dma->nsegs, BUS_DMA_NOWAIT);
8564 +       if (error) {
8565 +               printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,
8566 +                      (uintmax_t)size, error);
8567 +               goto fail_0;
8568 +       }
8569 +
8570 +       error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,
8571 +                              (caddr_t *)&dma->dma_vaddr,
8572 +                              BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
8573 +       if (error) {
8574 +               printf("%s: bus_dmamem_map failed: %d\n", __func__, error);
8575 +               goto fail_1;
8576 +       }
8577 +
8578 +       error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
8579 +                                 BUS_DMA_NOWAIT, &dma->dma_map);
8580 +       if (error) {
8581 +               printf("%s: bus_dmamap_create failed: %d\n", __func__, error);
8582 +               goto fail_2;
8583 +       }
8584 +
8585 +       error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
8586 +                               size, NULL, BUS_DMA_NOWAIT);
8587 +       if (error) {
8588 +               printf("%s: bus_dmamap_load failed: %d\n", __func__, error);
8589 +               goto fail_3;
8590 +       }
8591 +
8592 +       dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;
8593 +       *dma_addr = dma->dma_paddr;
8594 +       return dma->dma_vaddr;
8595 +
8596 +fail_3:
8597 +       bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8598 +fail_2:
8599 +       bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8600 +fail_1:
8601 +       bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8602 +fail_0:
8603 +       dma->dma_map = NULL;
8604 +       dma->dma_vaddr = NULL;
8605 +       dma->nsegs = 0;
8606 +
8607 +       return NULL;
8608 +}
8609 +
8610 +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
8611 +{
8612 +       dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
8613 +
8614 +       if (dma->dma_map != NULL) {
8615 +               bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,
8616 +                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
8617 +               bus_dmamap_unload(dma->dma_tag, dma->dma_map);
8618 +               bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
8619 +               bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
8620 +               bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
8621 +               dma->dma_paddr = 0;
8622 +               dma->dma_map = NULL;
8623 +               dma->dma_vaddr = NULL;
8624 +               dma->nsegs = 0;
8625 +       }
8626 +}
8627 +
8628 +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
8629 +{
8630 +       return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
8631 +}
8632 +
8633 +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
8634 +{
8635 +       return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
8636 +}
8637 +
8638 +void __DWC_FREE(void *mem_ctx, void *addr)
8639 +{
8640 +       free(addr, M_DEVBUF);
8641 +}
8642 +
8643 +
8644 +#ifdef DWC_CRYPTOLIB
8645 +/* dwc_crypto.h */
8646 +
8647 +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
8648 +{
8649 +       get_random_bytes(buffer, length);
8650 +}
8651 +
8652 +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
8653 +{
8654 +       struct crypto_blkcipher *tfm;
8655 +       struct blkcipher_desc desc;
8656 +       struct scatterlist sgd;
8657 +       struct scatterlist sgs;
8658 +
8659 +       tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
8660 +       if (tfm == NULL) {
8661 +               printk("failed to load transform for aes CBC\n");
8662 +               return -1;
8663 +       }
8664 +
8665 +       crypto_blkcipher_setkey(tfm, key, keylen);
8666 +       crypto_blkcipher_set_iv(tfm, iv, 16);
8667 +
8668 +       sg_init_one(&sgd, out, messagelen);
8669 +       sg_init_one(&sgs, message, messagelen);
8670 +
8671 +       desc.tfm = tfm;
8672 +       desc.flags = 0;
8673 +
8674 +       if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
8675 +               crypto_free_blkcipher(tfm);
8676 +               DWC_ERROR("AES CBC encryption failed");
8677 +               return -1;
8678 +       }
8679 +
8680 +       crypto_free_blkcipher(tfm);
8681 +       return 0;
8682 +}
8683 +
8684 +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
8685 +{
8686 +       struct crypto_hash *tfm;
8687 +       struct hash_desc desc;
8688 +       struct scatterlist sg;
8689 +
8690 +       tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
8691 +       if (IS_ERR(tfm)) {
8692 +               DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
8693 +               return 0;
8694 +       }
8695 +       desc.tfm = tfm;
8696 +       desc.flags = 0;
8697 +
8698 +       sg_init_one(&sg, message, len);
8699 +       crypto_hash_digest(&desc, &sg, len, out);
8700 +       crypto_free_hash(tfm);
8701 +
8702 +       return 1;
8703 +}
8704 +
8705 +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
8706 +                   uint8_t *key, uint32_t keylen, uint8_t *out)
8707 +{
8708 +       struct crypto_hash *tfm;
8709 +       struct hash_desc desc;
8710 +       struct scatterlist sg;
8711 +
8712 +       tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
8713 +       if (IS_ERR(tfm)) {
8714 +               DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
8715 +               return 0;
8716 +       }
8717 +       desc.tfm = tfm;
8718 +       desc.flags = 0;
8719 +
8720 +       sg_init_one(&sg, message, messagelen);
8721 +       crypto_hash_setkey(tfm, key, keylen);
8722 +       crypto_hash_digest(&desc, &sg, messagelen, out);
8723 +       crypto_free_hash(tfm);
8724 +
8725 +       return 1;
8726 +}
8727 +
8728 +#endif /* DWC_CRYPTOLIB */
8729 +
8730 +
8731 +/* Byte Ordering Conversions */
8732 +
8733 +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
8734 +{
8735 +#ifdef __LITTLE_ENDIAN
8736 +       return *p;
8737 +#else
8738 +       uint8_t *u_p = (uint8_t *)p;
8739 +
8740 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8741 +#endif
8742 +}
8743 +
8744 +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
8745 +{
8746 +#ifdef __BIG_ENDIAN
8747 +       return *p;
8748 +#else
8749 +       uint8_t *u_p = (uint8_t *)p;
8750 +
8751 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8752 +#endif
8753 +}
8754 +
8755 +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
8756 +{
8757 +#ifdef __LITTLE_ENDIAN
8758 +       return *p;
8759 +#else
8760 +       uint8_t *u_p = (uint8_t *)p;
8761 +
8762 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8763 +#endif
8764 +}
8765 +
8766 +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
8767 +{
8768 +#ifdef __BIG_ENDIAN
8769 +       return *p;
8770 +#else
8771 +       uint8_t *u_p = (uint8_t *)p;
8772 +
8773 +       return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
8774 +#endif
8775 +}
8776 +
8777 +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
8778 +{
8779 +#ifdef __LITTLE_ENDIAN
8780 +       return *p;
8781 +#else
8782 +       uint8_t *u_p = (uint8_t *)p;
8783 +       return (u_p[1] | (u_p[0] << 8));
8784 +#endif
8785 +}
8786 +
8787 +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
8788 +{
8789 +#ifdef __BIG_ENDIAN
8790 +       return *p;
8791 +#else
8792 +       uint8_t *u_p = (uint8_t *)p;
8793 +       return (u_p[1] | (u_p[0] << 8));
8794 +#endif
8795 +}
8796 +
8797 +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
8798 +{
8799 +#ifdef __LITTLE_ENDIAN
8800 +       return *p;
8801 +#else
8802 +       uint8_t *u_p = (uint8_t *)p;
8803 +       return (u_p[1] | (u_p[0] << 8));
8804 +#endif
8805 +}
8806 +
8807 +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
8808 +{
8809 +#ifdef __BIG_ENDIAN
8810 +       return *p;
8811 +#else
8812 +       uint8_t *u_p = (uint8_t *)p;
8813 +       return (u_p[1] | (u_p[0] << 8));
8814 +#endif
8815 +}
8816 +
8817 +
8818 +/* Registers */
8819 +
8820 +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
8821 +{
8822 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8823 +       bus_size_t ior = (bus_size_t)reg;
8824 +
8825 +       return bus_space_read_4(io->iot, io->ioh, ior);
8826 +}
8827 +
8828 +#if 0
8829 +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
8830 +{
8831 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8832 +       bus_size_t ior = (bus_size_t)reg;
8833 +
8834 +       return bus_space_read_8(io->iot, io->ioh, ior);
8835 +}
8836 +#endif
8837 +
8838 +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
8839 +{
8840 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8841 +       bus_size_t ior = (bus_size_t)reg;
8842 +
8843 +       bus_space_write_4(io->iot, io->ioh, ior, value);
8844 +}
8845 +
8846 +#if 0
8847 +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
8848 +{
8849 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8850 +       bus_size_t ior = (bus_size_t)reg;
8851 +
8852 +       bus_space_write_8(io->iot, io->ioh, ior, value);
8853 +}
8854 +#endif
8855 +
8856 +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
8857 +                     uint32_t set_mask)
8858 +{
8859 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8860 +       bus_size_t ior = (bus_size_t)reg;
8861 +
8862 +       bus_space_write_4(io->iot, io->ioh, ior,
8863 +                         (bus_space_read_4(io->iot, io->ioh, ior) &
8864 +                          ~clear_mask) | set_mask);
8865 +}
8866 +
8867 +#if 0
8868 +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
8869 +                     uint64_t set_mask)
8870 +{
8871 +       dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
8872 +       bus_size_t ior = (bus_size_t)reg;
8873 +
8874 +       bus_space_write_8(io->iot, io->ioh, ior,
8875 +                         (bus_space_read_8(io->iot, io->ioh, ior) &
8876 +                          ~clear_mask) | set_mask);
8877 +}
8878 +#endif
8879 +
8880 +
8881 +/* Locking */
8882 +
8883 +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
8884 +{
8885 +       struct simplelock *sl = DWC_ALLOC(sizeof(*sl));
8886 +
8887 +       if (!sl) {
8888 +               DWC_ERROR("Cannot allocate memory for spinlock");
8889 +               return NULL;
8890 +       }
8891 +
8892 +       simple_lock_init(sl);
8893 +       return (dwc_spinlock_t *)sl;
8894 +}
8895 +
8896 +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
8897 +{
8898 +       struct simplelock *sl = (struct simplelock *)lock;
8899 +
8900 +       DWC_FREE(sl);
8901 +}
8902 +
8903 +void DWC_SPINLOCK(dwc_spinlock_t *lock)
8904 +{
8905 +       simple_lock((struct simplelock *)lock);
8906 +}
8907 +
8908 +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
8909 +{
8910 +       simple_unlock((struct simplelock *)lock);
8911 +}
8912 +
8913 +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
8914 +{
8915 +       simple_lock((struct simplelock *)lock);
8916 +       *flags = splbio();
8917 +}
8918 +
8919 +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
8920 +{
8921 +       splx(flags);
8922 +       simple_unlock((struct simplelock *)lock);
8923 +}
8924 +
8925 +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
8926 +{
8927 +       dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));
8928 +
8929 +       if (!mutex) {
8930 +               DWC_ERROR("Cannot allocate memory for mutex");
8931 +               return NULL;
8932 +       }
8933 +
8934 +       lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);
8935 +       return mutex;
8936 +}
8937 +
8938 +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
8939 +#else
8940 +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
8941 +{
8942 +       DWC_FREE(mutex);
8943 +}
8944 +#endif
8945 +
8946 +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
8947 +{
8948 +       lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);
8949 +}
8950 +
8951 +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
8952 +{
8953 +       int status;
8954 +
8955 +       status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);
8956 +       return status == 0;
8957 +}
8958 +
8959 +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
8960 +{
8961 +       lockmgr((struct lock *)mutex, LK_RELEASE, NULL);
8962 +}
8963 +
8964 +
8965 +/* Timing */
8966 +
8967 +void DWC_UDELAY(uint32_t usecs)
8968 +{
8969 +       DELAY(usecs);
8970 +}
8971 +
8972 +void DWC_MDELAY(uint32_t msecs)
8973 +{
8974 +       do {
8975 +               DELAY(1000);
8976 +       } while (--msecs);
8977 +}
8978 +
8979 +void DWC_MSLEEP(uint32_t msecs)
8980 +{
8981 +       struct timeval tv;
8982 +
8983 +       tv.tv_sec = msecs / 1000;
8984 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
8985 +       tsleep(&tv, 0, "dw3slp", tvtohz(&tv));
8986 +}
8987 +
8988 +uint32_t DWC_TIME(void)
8989 +{
8990 +       struct timeval tv;
8991 +
8992 +       microuptime(&tv);       // or getmicrouptime? (less precise, but faster)
8993 +       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
8994 +}
8995 +
8996 +
8997 +/* Timers */
8998 +
8999 +struct dwc_timer {
9000 +       struct callout t;
9001 +       char *name;
9002 +       dwc_spinlock_t *lock;
9003 +       dwc_timer_callback_t cb;
9004 +       void *data;
9005 +};
9006 +
9007 +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
9008 +{
9009 +       dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
9010 +
9011 +       if (!t) {
9012 +               DWC_ERROR("Cannot allocate memory for timer");
9013 +               return NULL;
9014 +       }
9015 +
9016 +       callout_init(&t->t);
9017 +
9018 +       t->name = DWC_STRDUP(name);
9019 +       if (!t->name) {
9020 +               DWC_ERROR("Cannot allocate memory for timer->name");
9021 +               goto no_name;
9022 +       }
9023 +
9024 +       t->lock = DWC_SPINLOCK_ALLOC();
9025 +       if (!t->lock) {
9026 +               DWC_ERROR("Cannot allocate memory for timer->lock");
9027 +               goto no_lock;
9028 +       }
9029 +
9030 +       t->cb = cb;
9031 +       t->data = data;
9032 +
9033 +       return t;
9034 +
9035 + no_lock:
9036 +       DWC_FREE(t->name);
9037 + no_name:
9038 +       DWC_FREE(t);
9039 +
9040 +       return NULL;
9041 +}
9042 +
9043 +void DWC_TIMER_FREE(dwc_timer_t *timer)
9044 +{
9045 +       callout_stop(&timer->t);
9046 +       DWC_SPINLOCK_FREE(timer->lock);
9047 +       DWC_FREE(timer->name);
9048 +       DWC_FREE(timer);
9049 +}
9050 +
9051 +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
9052 +{
9053 +       struct timeval tv;
9054 +
9055 +       tv.tv_sec = time / 1000;
9056 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9057 +       callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
9058 +}
9059 +
9060 +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
9061 +{
9062 +       callout_stop(&timer->t);
9063 +}
9064 +
9065 +
9066 +/* Wait Queues */
9067 +
9068 +struct dwc_waitq {
9069 +       struct simplelock lock;
9070 +       int abort;
9071 +};
9072 +
9073 +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
9074 +{
9075 +       dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
9076 +
9077 +       if (!wq) {
9078 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9079 +               return NULL;
9080 +       }
9081 +
9082 +       simple_lock_init(&wq->lock);
9083 +       wq->abort = 0;
9084 +
9085 +       return wq;
9086 +}
9087 +
9088 +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
9089 +{
9090 +       DWC_FREE(wq);
9091 +}
9092 +
9093 +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
9094 +{
9095 +       int ipl;
9096 +       int result = 0;
9097 +
9098 +       simple_lock(&wq->lock);
9099 +       ipl = splbio();
9100 +
9101 +       /* Skip the sleep if already aborted or triggered */
9102 +       if (!wq->abort && !cond(data)) {
9103 +               splx(ipl);
9104 +               result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout
9105 +               ipl = splbio();
9106 +       }
9107 +
9108 +       if (result == 0) {                      // awoken
9109 +               if (wq->abort) {
9110 +                       wq->abort = 0;
9111 +                       result = -DWC_E_ABORT;
9112 +               } else {
9113 +                       result = 0;
9114 +               }
9115 +
9116 +               splx(ipl);
9117 +               simple_unlock(&wq->lock);
9118 +       } else {
9119 +               wq->abort = 0;
9120 +               splx(ipl);
9121 +               simple_unlock(&wq->lock);
9122 +
9123 +               if (result == ERESTART) {       // signaled - restart
9124 +                       result = -DWC_E_RESTART;
9125 +               } else {                        // signaled - must be EINTR
9126 +                       result = -DWC_E_ABORT;
9127 +               }
9128 +       }
9129 +
9130 +       return result;
9131 +}
9132 +
9133 +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
9134 +                              void *data, int32_t msecs)
9135 +{
9136 +       struct timeval tv, tv1, tv2;
9137 +       int ipl;
9138 +       int result = 0;
9139 +
9140 +       tv.tv_sec = msecs / 1000;
9141 +       tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
9142 +
9143 +       simple_lock(&wq->lock);
9144 +       ipl = splbio();
9145 +
9146 +       /* Skip the sleep if already aborted or triggered */
9147 +       if (!wq->abort && !cond(data)) {
9148 +               splx(ipl);
9149 +               getmicrouptime(&tv1);
9150 +               result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);
9151 +               getmicrouptime(&tv2);
9152 +               ipl = splbio();
9153 +       }
9154 +
9155 +       if (result == 0) {                      // awoken
9156 +               if (wq->abort) {
9157 +                       wq->abort = 0;
9158 +                       splx(ipl);
9159 +                       simple_unlock(&wq->lock);
9160 +                       result = -DWC_E_ABORT;
9161 +               } else {
9162 +                       splx(ipl);
9163 +                       simple_unlock(&wq->lock);
9164 +
9165 +                       tv2.tv_usec -= tv1.tv_usec;
9166 +                       if (tv2.tv_usec < 0) {
9167 +                               tv2.tv_usec += 1000000;
9168 +                               tv2.tv_sec--;
9169 +                       }
9170 +
9171 +                       tv2.tv_sec -= tv1.tv_sec;
9172 +                       result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
9173 +                       result = msecs - result;
9174 +                       if (result <= 0)
9175 +                               result = 1;
9176 +               }
9177 +       } else {
9178 +               wq->abort = 0;
9179 +               splx(ipl);
9180 +               simple_unlock(&wq->lock);
9181 +
9182 +               if (result == ERESTART) {       // signaled - restart
9183 +                       result = -DWC_E_RESTART;
9184 +
9185 +               } else if (result == EINTR) {           // signaled - interrupt
9186 +                       result = -DWC_E_ABORT;
9187 +
9188 +               } else {                                // timed out
9189 +                       result = -DWC_E_TIMEOUT;
9190 +               }
9191 +       }
9192 +
9193 +       return result;
9194 +}
9195 +
9196 +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
9197 +{
9198 +       wakeup(wq);
9199 +}
9200 +
9201 +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
9202 +{
9203 +       int ipl;
9204 +
9205 +       simple_lock(&wq->lock);
9206 +       ipl = splbio();
9207 +       wq->abort = 1;
9208 +       wakeup(wq);
9209 +       splx(ipl);
9210 +       simple_unlock(&wq->lock);
9211 +}
9212 +
9213 +
9214 +/* Threading */
9215 +
9216 +struct dwc_thread {
9217 +       struct proc *proc;
9218 +       int abort;
9219 +};
9220 +
9221 +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
9222 +{
9223 +       int retval;
9224 +       dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
9225 +
9226 +       if (!thread) {
9227 +               return NULL;
9228 +       }
9229 +
9230 +       thread->abort = 0;
9231 +       retval = kthread_create1((void (*)(void *))func, data, &thread->proc,
9232 +                                "%s", name);
9233 +       if (retval) {
9234 +               DWC_FREE(thread);
9235 +               return NULL;
9236 +       }
9237 +
9238 +       return thread;
9239 +}
9240 +
9241 +int DWC_THREAD_STOP(dwc_thread_t *thread)
9242 +{
9243 +       int retval;
9244 +
9245 +       thread->abort = 1;
9246 +       retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
9247 +
9248 +       if (retval == 0) {
9249 +               /* DWC_THREAD_EXIT() will free the thread struct */
9250 +               return 0;
9251 +       }
9252 +
9253 +       /* NOTE: We leak the thread struct if thread doesn't die */
9254 +
9255 +       if (retval == EWOULDBLOCK) {
9256 +               return -DWC_E_TIMEOUT;
9257 +       }
9258 +
9259 +       return -DWC_E_UNKNOWN;
9260 +}
9261 +
9262 +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
9263 +{
9264 +       return thread->abort;
9265 +}
9266 +
9267 +void DWC_THREAD_EXIT(dwc_thread_t *thread)
9268 +{
9269 +       wakeup(&thread->abort);
9270 +       DWC_FREE(thread);
9271 +       kthread_exit(0);
9272 +}
9273 +
9274 +/* tasklets
9275 + - Runs in interrupt context (cannot sleep)
9276 + - Each tasklet runs on a single CPU
9277 + - Different tasklets can be running simultaneously on different CPUs
9278 + [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-
9279 +   halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]
9280 + */
9281 +struct dwc_tasklet {
9282 +       dwc_tasklet_callback_t cb;
9283 +       void *data;
9284 +};
9285 +
9286 +static void tasklet_callback(void *data)
9287 +{
9288 +       dwc_tasklet_t *task = (dwc_tasklet_t *)data;
9289 +
9290 +       task->cb(task->data);
9291 +}
9292 +
9293 +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
9294 +{
9295 +       dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
9296 +
9297 +       if (task) {
9298 +               task->cb = cb;
9299 +               task->data = data;
9300 +       } else {
9301 +               DWC_ERROR("Cannot allocate memory for tasklet");
9302 +       }
9303 +
9304 +       return task;
9305 +}
9306 +
9307 +void DWC_TASK_FREE(dwc_tasklet_t *task)
9308 +{
9309 +       DWC_FREE(task);
9310 +}
9311 +
9312 +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
9313 +{
9314 +       tasklet_callback(task);
9315 +}
9316 +
9317 +
9318 +/* workqueues
9319 + - Runs in process context (can sleep)
9320 + */
9321 +typedef struct work_container {
9322 +       dwc_work_callback_t cb;
9323 +       void *data;
9324 +       dwc_workq_t *wq;
9325 +       char *name;
9326 +       int hz;
9327 +       struct work task;
9328 +} work_container_t;
9329 +
9330 +struct dwc_workq {
9331 +       struct workqueue *taskq;
9332 +       dwc_spinlock_t *lock;
9333 +       dwc_waitq_t *waitq;
9334 +       int pending;
9335 +       struct work_container *container;
9336 +};
9337 +
9338 +static void do_work(struct work *task, void *data)
9339 +{
9340 +       dwc_workq_t *wq = (dwc_workq_t *)data;
9341 +       work_container_t *container = wq->container;
9342 +       dwc_irqflags_t flags;
9343 +
9344 +       if (container->hz) {
9345 +               tsleep(container, 0, "dw3wrk", container->hz);
9346 +       }
9347 +
9348 +       container->cb(container->data);
9349 +       DWC_DEBUG("Work done: %s, container=%p", container->name, container);
9350 +
9351 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9352 +       if (container->name)
9353 +               DWC_FREE(container->name);
9354 +       DWC_FREE(container);
9355 +       wq->pending--;
9356 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9357 +       DWC_WAITQ_TRIGGER(wq->waitq);
9358 +}
9359 +
9360 +static int work_done(void *data)
9361 +{
9362 +       dwc_workq_t *workq = (dwc_workq_t *)data;
9363 +
9364 +       return workq->pending == 0;
9365 +}
9366 +
9367 +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
9368 +{
9369 +       return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
9370 +}
9371 +
9372 +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
9373 +{
9374 +       int result;
9375 +       dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
9376 +
9377 +       if (!wq) {
9378 +               DWC_ERROR("Cannot allocate memory for workqueue");
9379 +               return NULL;
9380 +       }
9381 +
9382 +       result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,
9383 +                                 IPL_BIO, 0);
9384 +       if (result) {
9385 +               DWC_ERROR("Cannot create workqueue");
9386 +               goto no_taskq;
9387 +       }
9388 +
9389 +       wq->pending = 0;
9390 +
9391 +       wq->lock = DWC_SPINLOCK_ALLOC();
9392 +       if (!wq->lock) {
9393 +               DWC_ERROR("Cannot allocate memory for spinlock");
9394 +               goto no_lock;
9395 +       }
9396 +
9397 +       wq->waitq = DWC_WAITQ_ALLOC();
9398 +       if (!wq->waitq) {
9399 +               DWC_ERROR("Cannot allocate memory for waitqueue");
9400 +               goto no_waitq;
9401 +       }
9402 +
9403 +       return wq;
9404 +
9405 + no_waitq:
9406 +       DWC_SPINLOCK_FREE(wq->lock);
9407 + no_lock:
9408 +       workqueue_destroy(wq->taskq);
9409 + no_taskq:
9410 +       DWC_FREE(wq);
9411 +
9412 +       return NULL;
9413 +}
9414 +
9415 +void DWC_WORKQ_FREE(dwc_workq_t *wq)
9416 +{
9417 +#ifdef DEBUG
9418 +       dwc_irqflags_t flags;
9419 +
9420 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9421 +
9422 +       if (wq->pending != 0) {
9423 +               struct work_container *container = wq->container;
9424 +
9425 +               DWC_ERROR("Destroying work queue with pending work");
9426 +
9427 +               if (container && container->name) {
9428 +                       DWC_ERROR("Work %s still pending", container->name);
9429 +               }
9430 +       }
9431 +
9432 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9433 +#endif
9434 +       DWC_WAITQ_FREE(wq->waitq);
9435 +       DWC_SPINLOCK_FREE(wq->lock);
9436 +       workqueue_destroy(wq->taskq);
9437 +       DWC_FREE(wq);
9438 +}
9439 +
9440 +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
9441 +                       char *format, ...)
9442 +{
9443 +       dwc_irqflags_t flags;
9444 +       work_container_t *container;
9445 +       static char name[128];
9446 +       va_list args;
9447 +
9448 +       va_start(args, format);
9449 +       DWC_VSNPRINTF(name, 128, format, args);
9450 +       va_end(args);
9451 +
9452 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9453 +       wq->pending++;
9454 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9455 +       DWC_WAITQ_TRIGGER(wq->waitq);
9456 +
9457 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9458 +       if (!container) {
9459 +               DWC_ERROR("Cannot allocate memory for container");
9460 +               return;
9461 +       }
9462 +
9463 +       container->name = DWC_STRDUP(name);
9464 +       if (!container->name) {
9465 +               DWC_ERROR("Cannot allocate memory for container->name");
9466 +               DWC_FREE(container);
9467 +               return;
9468 +       }
9469 +
9470 +       container->cb = cb;
9471 +       container->data = data;
9472 +       container->wq = wq;
9473 +       container->hz = 0;
9474 +       wq->container = container;
9475 +
9476 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9477 +       workqueue_enqueue(wq->taskq, &container->task);
9478 +}
9479 +
9480 +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
9481 +                               void *data, uint32_t time, char *format, ...)
9482 +{
9483 +       dwc_irqflags_t flags;
9484 +       work_container_t *container;
9485 +       static char name[128];
9486 +       struct timeval tv;
9487 +       va_list args;
9488 +
9489 +       va_start(args, format);
9490 +       DWC_VSNPRINTF(name, 128, format, args);
9491 +       va_end(args);
9492 +
9493 +       DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
9494 +       wq->pending++;
9495 +       DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
9496 +       DWC_WAITQ_TRIGGER(wq->waitq);
9497 +
9498 +       container = DWC_ALLOC_ATOMIC(sizeof(*container));
9499 +       if (!container) {
9500 +               DWC_ERROR("Cannot allocate memory for container");
9501 +               return;
9502 +       }
9503 +
9504 +       container->name = DWC_STRDUP(name);
9505 +       if (!container->name) {
9506 +               DWC_ERROR("Cannot allocate memory for container->name");
9507 +               DWC_FREE(container);
9508 +               return;
9509 +       }
9510 +
9511 +       container->cb = cb;
9512 +       container->data = data;
9513 +       container->wq = wq;
9514 +       tv.tv_sec = time / 1000;
9515 +       tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
9516 +       container->hz = tvtohz(&tv);
9517 +       wq->container = container;
9518 +
9519 +       DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
9520 +       workqueue_enqueue(wq->taskq, &container->task);
9521 +}
9522 +
9523 +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
9524 +{
9525 +       return wq->pending;
9526 +}
9527 --- /dev/null
9528 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
9529 @@ -0,0 +1,308 @@
9530 +/* =========================================================================
9531 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
9532 + * $Revision: #5 $
9533 + * $Date: 2010/09/28 $
9534 + * $Change: 1596182 $
9535 + *
9536 + * Synopsys Portability Library Software and documentation
9537 + * (hereinafter, "Software") is an Unsupported proprietary work of
9538 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9539 + * between Synopsys and you.
9540 + *
9541 + * The Software IS NOT an item of Licensed Software or Licensed Product
9542 + * under any End User Software License Agreement or Agreement for
9543 + * Licensed Product with Synopsys or any supplement thereto. You are
9544 + * permitted to use and redistribute this Software in source and binary
9545 + * forms, with or without modification, provided that redistributions
9546 + * of source code must retain this notice. You may not view, use,
9547 + * disclose, copy or distribute this file or any information contained
9548 + * herein except pursuant to this license grant from Synopsys. If you
9549 + * do not agree with this notice, including the disclaimer below, then
9550 + * you are not authorized to use the Software.
9551 + *
9552 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9553 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9554 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9555 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9556 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9557 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9558 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9559 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9560 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9561 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9562 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9563 + * DAMAGE.
9564 + * ========================================================================= */
9565 +
9566 +/** @file
9567 + * This file contains the WUSB cryptographic routines.
9568 + */
9569 +
9570 +#ifdef DWC_CRYPTOLIB
9571 +
9572 +#include "dwc_crypto.h"
9573 +#include "usb.h"
9574 +
9575 +#ifdef DEBUG
9576 +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
9577 +{
9578 +       int i;
9579 +       DWC_PRINTF("%s: ", name);
9580 +       for (i=0; i<len; i++) {
9581 +               DWC_PRINTF("%02x ", bytes[i]);
9582 +       }
9583 +       DWC_PRINTF("\n");
9584 +}
9585 +#else
9586 +#define dump_bytes(x...)
9587 +#endif
9588 +
9589 +/* Display a block */
9590 +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
9591 +{
9592 +#ifdef DWC_DEBUG_CRYPTO
9593 +       int i, blksize = 16;
9594 +
9595 +       DWC_DEBUG("%s", prefix);
9596 +
9597 +       if (suffix == NULL) {
9598 +               suffix = "\n";
9599 +               blksize = a;
9600 +       }
9601 +
9602 +       for (i = 0; i < blksize; i++)
9603 +               DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
9604 +       DWC_PRINT(suffix);
9605 +#endif
9606 +}
9607 +
9608 +/**
9609 + * Encrypts an array of bytes using the AES encryption engine.
9610 + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
9611 + * in-place.
9612 + *
9613 + * @return  0 on success, negative error code on error.
9614 + */
9615 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
9616 +{
9617 +       u8 block_t[16];
9618 +       DWC_MEMSET(block_t, 0, 16);
9619 +
9620 +       return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
9621 +}
9622 +
9623 +/**
9624 + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
9625 + * This function takes a data string and returns the encrypted CBC
9626 + * Counter-mode MIC.
9627 + *
9628 + * @param key     The 128-bit symmetric key.
9629 + * @param nonce   The CCM nonce.
9630 + * @param label   The unique 14-byte ASCII text label.
9631 + * @param bytes   The byte array to be encrypted.
9632 + * @param len     Length of the byte array.
9633 + * @param result  Byte array to receive the 8-byte encrypted MIC.
9634 + */
9635 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9636 +                 char *label, u8 *bytes, int len, u8 *result)
9637 +{
9638 +       u8 block_m[16];
9639 +       u8 block_x[16];
9640 +       u8 block_t[8];
9641 +       int idx, blkNum;
9642 +       u16 la = (u16)(len + 14);
9643 +
9644 +       /* Set the AES-128 key */
9645 +       //dwc_aes_setkey(tfm, key, 16);
9646 +
9647 +       /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
9648 +       block_m[0] = 0x59;
9649 +       for (idx = 0; idx < 13; idx++)
9650 +               block_m[idx + 1] = nonce[idx];
9651 +       block_m[14] = 0;
9652 +       block_m[15] = 0;
9653 +
9654 +       /* Produce the CBC IV */
9655 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9656 +       show_block(block_m, "CBC IV in: ", "\n", 0);
9657 +       show_block(block_x, "CBC IV out:", "\n", 0);
9658 +
9659 +       /* Fill block B1 from l(a) = Blen + 14, and A */
9660 +       block_x[0] ^= (u8)(la >> 8);
9661 +       block_x[1] ^= (u8)la;
9662 +       for (idx = 0; idx < 14; idx++)
9663 +               block_x[idx + 2] ^= label[idx];
9664 +       show_block(block_x, "After xor: ", "b1\n", 16);
9665 +
9666 +       dwc_wusb_aes_encrypt(block_x, key, block_x);
9667 +       show_block(block_x, "After AES: ", "b1\n", 16);
9668 +
9669 +       idx = 0;
9670 +       blkNum = 0;
9671 +
9672 +       /* Fill remaining blocks with B */
9673 +       while (len-- > 0) {
9674 +               block_x[idx] ^= *bytes++;
9675 +               if (++idx >= 16) {
9676 +                       idx = 0;
9677 +                       show_block(block_x, "After xor: ", "\n", blkNum);
9678 +                       dwc_wusb_aes_encrypt(block_x, key, block_x);
9679 +                       show_block(block_x, "After AES: ", "\n", blkNum);
9680 +                       blkNum++;
9681 +               }
9682 +       }
9683 +
9684 +       /* Handle partial last block */
9685 +       if (idx > 0) {
9686 +               show_block(block_x, "After xor: ", "\n", blkNum);
9687 +               dwc_wusb_aes_encrypt(block_x, key, block_x);
9688 +               show_block(block_x, "After AES: ", "\n", blkNum);
9689 +       }
9690 +
9691 +       /* Save the MIC tag */
9692 +       DWC_MEMCPY(block_t, block_x, 8);
9693 +       show_block(block_t, "MIC tag  : ", NULL, 8);
9694 +
9695 +       /* Fill block A0 from flags = 0x01, N, and counter = 0 */
9696 +       block_m[0] = 0x01;
9697 +       block_m[14] = 0;
9698 +       block_m[15] = 0;
9699 +
9700 +       /* Encrypt the counter */
9701 +       dwc_wusb_aes_encrypt(block_m, key, block_x);
9702 +       show_block(block_x, "CTR[MIC] : ", NULL, 8);
9703 +
9704 +       /* XOR with MIC tag */
9705 +       for (idx = 0; idx < 8; idx++) {
9706 +               block_t[idx] ^= block_x[idx];
9707 +       }
9708 +
9709 +       /* Return result to caller */
9710 +       DWC_MEMCPY(result, block_t, 8);
9711 +       show_block(result, "CCM-MIC  : ", NULL, 8);
9712 +
9713 +}
9714 +
9715 +/**
9716 + * The PRF function described in section 6.5 of the WUSB spec. This function
9717 + * concatenates MIC values returned from dwc_cmf() to create a value of
9718 + * the requested length.
9719 + *
9720 + * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
9721 + * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
9722 + * @param result   Byte array to receive the result.
9723 + */
9724 +void dwc_wusb_prf(int prf_len, u8 *key,
9725 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
9726 +{
9727 +       int i;
9728 +
9729 +       nonce[0] = 0;
9730 +       for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
9731 +               dwc_wusb_cmf(key, nonce, label, bytes, len, result);
9732 +               result += 8;
9733 +       }
9734 +}
9735 +
9736 +/**
9737 + * Fills in CCM Nonce per the WUSB spec.
9738 + *
9739 + * @param[in] haddr Host address.
9740 + * @param[in] daddr Device address.
9741 + * @param[in] tkid Session Key(PTK) identifier.
9742 + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
9743 + */
9744 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9745 +                            uint8_t *nonce)
9746 +{
9747 +
9748 +       DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
9749 +
9750 +       DWC_MEMSET(&nonce[0], 0, 16);
9751 +
9752 +       DWC_MEMCPY(&nonce[6], tkid, 3);
9753 +       nonce[9] = daddr & 0xFF;
9754 +       nonce[10] = (daddr >> 8) & 0xFF;
9755 +       nonce[11] = haddr & 0xFF;
9756 +       nonce[12] = (haddr >> 8) & 0xFF;
9757 +
9758 +       dump_bytes("CCM nonce", nonce, 16);
9759 +}
9760 +
9761 +/**
9762 + * Generates a 16-byte cryptographic-grade random number for the Host/Device
9763 + * Nonce.
9764 + */
9765 +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
9766 +{
9767 +       uint8_t inonce[16];
9768 +       uint32_t temp[4];
9769 +
9770 +       /* Fill in the Nonce */
9771 +       DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
9772 +       inonce[9] = addr & 0xFF;
9773 +       inonce[10] = (addr >> 8) & 0xFF;
9774 +       inonce[11] = inonce[9];
9775 +       inonce[12] = inonce[10];
9776 +
9777 +       /* Collect "randomness samples" */
9778 +       DWC_RANDOM_BYTES((uint8_t *)temp, 16);
9779 +
9780 +       dwc_wusb_prf_128((uint8_t *)temp, nonce,
9781 +                        "Random Numbers", (uint8_t *)temp, sizeof(temp),
9782 +                        nonce);
9783 +}
9784 +
9785 +/**
9786 + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
9787 + * WUSB spec.
9788 + *
9789 + * @param[in] ccm_nonce Pointer to CCM Nonce.
9790 + * @param[in] mk Master Key to derive the session from
9791 + * @param[in] hnonce Pointer to Host Nonce.
9792 + * @param[in] dnonce Pointer to Device Nonce.
9793 + * @param[out] kck Pointer to where the KCK output is to be written.
9794 + * @param[out] ptk Pointer to where the PTK output is to be written.
9795 + */
9796 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
9797 +                     uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
9798 +{
9799 +       uint8_t idata[32];
9800 +       uint8_t odata[32];
9801 +
9802 +       dump_bytes("ck", mk, 16);
9803 +       dump_bytes("hnonce", hnonce, 16);
9804 +       dump_bytes("dnonce", dnonce, 16);
9805 +
9806 +       /* The data is the HNonce and DNonce concatenated */
9807 +       DWC_MEMCPY(&idata[0], hnonce, 16);
9808 +       DWC_MEMCPY(&idata[16], dnonce, 16);
9809 +
9810 +       dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
9811 +
9812 +       /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
9813 +       DWC_MEMCPY(kck, &odata[0], 16);
9814 +       DWC_MEMCPY(ptk, &odata[16], 16);
9815 +
9816 +       dump_bytes("kck", kck, 16);
9817 +       dump_bytes("ptk", ptk, 16);
9818 +}
9819 +
9820 +/**
9821 + * Generates the Message Integrity Code over the Handshake data per the
9822 + * WUSB spec.
9823 + *
9824 + * @param ccm_nonce Pointer to CCM Nonce.
9825 + * @param kck   Pointer to Key Confirmation Key.
9826 + * @param data  Pointer to Handshake data to be checked.
9827 + * @param mic   Pointer to where the MIC output is to be written.
9828 + */
9829 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
9830 +                     uint8_t *data, uint8_t *mic)
9831 +{
9832 +
9833 +       dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
9834 +                       data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
9835 +}
9836 +
9837 +#endif /* DWC_CRYPTOLIB */
9838 --- /dev/null
9839 +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
9840 @@ -0,0 +1,111 @@
9841 +/* =========================================================================
9842 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
9843 + * $Revision: #3 $
9844 + * $Date: 2010/09/28 $
9845 + * $Change: 1596182 $
9846 + *
9847 + * Synopsys Portability Library Software and documentation
9848 + * (hereinafter, "Software") is an Unsupported proprietary work of
9849 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9850 + * between Synopsys and you.
9851 + *
9852 + * The Software IS NOT an item of Licensed Software or Licensed Product
9853 + * under any End User Software License Agreement or Agreement for
9854 + * Licensed Product with Synopsys or any supplement thereto. You are
9855 + * permitted to use and redistribute this Software in source and binary
9856 + * forms, with or without modification, provided that redistributions
9857 + * of source code must retain this notice. You may not view, use,
9858 + * disclose, copy or distribute this file or any information contained
9859 + * herein except pursuant to this license grant from Synopsys. If you
9860 + * do not agree with this notice, including the disclaimer below, then
9861 + * you are not authorized to use the Software.
9862 + *
9863 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9864 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9865 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9866 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9867 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9868 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9869 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9870 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9871 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9872 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9873 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9874 + * DAMAGE.
9875 + * ========================================================================= */
9876 +
9877 +#ifndef _DWC_CRYPTO_H_
9878 +#define _DWC_CRYPTO_H_
9879 +
9880 +#ifdef __cplusplus
9881 +extern "C" {
9882 +#endif
9883 +
9884 +/** @file
9885 + *
9886 + * This file contains declarations for the WUSB Cryptographic routines as
9887 + * defined in the WUSB spec.  They are only to be used internally by the DWC UWB
9888 + * modules.
9889 + */
9890 +
9891 +#include "dwc_os.h"
9892 +
9893 +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
9894 +
9895 +void dwc_wusb_cmf(u8 *key, u8 *nonce,
9896 +                 char *label, u8 *bytes, int len, u8 *result);
9897 +void dwc_wusb_prf(int prf_len, u8 *key,
9898 +                 u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
9899 +
9900 +/**
9901 + * The PRF-64 function described in section 6.5 of the WUSB spec.
9902 + *
9903 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9904 + */
9905 +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
9906 +                                  char *label, u8 *bytes, int len, u8 *result)
9907 +{
9908 +       dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
9909 +}
9910 +
9911 +/**
9912 + * The PRF-128 function described in section 6.5 of the WUSB spec.
9913 + *
9914 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9915 + */
9916 +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
9917 +                                   char *label, u8 *bytes, int len, u8 *result)
9918 +{
9919 +       dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
9920 +}
9921 +
9922 +/**
9923 + * The PRF-256 function described in section 6.5 of the WUSB spec.
9924 + *
9925 + * @param key, nonce, label, bytes, len, result  Same as for dwc_prf().
9926 + */
9927 +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
9928 +                                   char *label, u8 *bytes, int len, u8 *result)
9929 +{
9930 +       dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
9931 +}
9932 +
9933 +
9934 +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
9935 +                              uint8_t *nonce);
9936 +void dwc_wusb_gen_nonce(uint16_t addr,
9937 +                         uint8_t *nonce);
9938 +
9939 +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
9940 +                       uint8_t *hnonce, uint8_t *dnonce,
9941 +                       uint8_t *kck, uint8_t *ptk);
9942 +
9943 +
9944 +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
9945 +                       *kck, uint8_t *data, uint8_t *mic);
9946 +
9947 +#ifdef __cplusplus
9948 +}
9949 +#endif
9950 +
9951 +#endif /* _DWC_CRYPTO_H_ */
9952 --- /dev/null
9953 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
9954 @@ -0,0 +1,291 @@
9955 +/* =========================================================================
9956 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
9957 + * $Revision: #3 $
9958 + * $Date: 2010/09/28 $
9959 + * $Change: 1596182 $
9960 + *
9961 + * Synopsys Portability Library Software and documentation
9962 + * (hereinafter, "Software") is an Unsupported proprietary work of
9963 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
9964 + * between Synopsys and you.
9965 + *
9966 + * The Software IS NOT an item of Licensed Software or Licensed Product
9967 + * under any End User Software License Agreement or Agreement for
9968 + * Licensed Product with Synopsys or any supplement thereto. You are
9969 + * permitted to use and redistribute this Software in source and binary
9970 + * forms, with or without modification, provided that redistributions
9971 + * of source code must retain this notice. You may not view, use,
9972 + * disclose, copy or distribute this file or any information contained
9973 + * herein except pursuant to this license grant from Synopsys. If you
9974 + * do not agree with this notice, including the disclaimer below, then
9975 + * you are not authorized to use the Software.
9976 + *
9977 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
9978 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9979 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
9980 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
9981 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
9982 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
9983 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
9984 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
9985 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9986 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
9987 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
9988 + * DAMAGE.
9989 + * ========================================================================= */
9990 +#ifdef DWC_CRYPTOLIB
9991 +
9992 +#ifndef CONFIG_MACH_IPMATE
9993 +
9994 +#include "dwc_dh.h"
9995 +#include "dwc_modpow.h"
9996 +
9997 +#ifdef DEBUG
9998 +/* This function prints out a buffer in the format described in the Association
9999 + * Model specification. */
10000 +static void dh_dump(char *str, void *_num, int len)
10001 +{
10002 +       uint8_t *num = _num;
10003 +       int i;
10004 +       DWC_PRINTF("%s\n", str);
10005 +       for (i = 0; i < len; i ++) {
10006 +               DWC_PRINTF("%02x", num[i]);
10007 +               if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
10008 +               if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
10009 +       }
10010 +
10011 +       DWC_PRINTF("\n");
10012 +}
10013 +#else
10014 +#define dh_dump(_x...) do {; } while(0)
10015 +#endif
10016 +
10017 +/* Constant g value */
10018 +static __u32 dh_g[] = {
10019 +       0x02000000,
10020 +};
10021 +
10022 +/* Constant p value */
10023 +static __u32 dh_p[] = {
10024 +       0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
10025 +       0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
10026 +       0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
10027 +       0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
10028 +       0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
10029 +       0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
10030 +       0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
10031 +       0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
10032 +       0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
10033 +       0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
10034 +       0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
10035 +       0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
10036 +};
10037 +
10038 +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
10039 +{
10040 +       uint8_t *in = _in;
10041 +       uint8_t *out = _out;
10042 +       int i;
10043 +       for (i=0; i<len; i++) {
10044 +               out[i] = in[len-1-i];
10045 +       }
10046 +}
10047 +
10048 +/* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
10049 + * big endian numbers of size len, in bytes.  Each len value must be a multiple
10050 + * of 4. */
10051 +int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10052 +                 void *exp, uint32_t exp_len,
10053 +                 void *mod, uint32_t mod_len,
10054 +                 void *out)
10055 +{
10056 +       /* modpow() takes little endian numbers.  AM uses big-endian.  This
10057 +        * function swaps bytes of numbers before passing onto modpow. */
10058 +
10059 +       int retval = 0;
10060 +       uint32_t *result;
10061 +
10062 +       uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
10063 +       uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
10064 +       uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
10065 +
10066 +       dh_swap_bytes(num, &bignum_num[1], num_len);
10067 +       bignum_num[0] = num_len / 4;
10068 +
10069 +       dh_swap_bytes(exp, &bignum_exp[1], exp_len);
10070 +       bignum_exp[0] = exp_len / 4;
10071 +
10072 +       dh_swap_bytes(mod, &bignum_mod[1], mod_len);
10073 +       bignum_mod[0] = mod_len / 4;
10074 +
10075 +       result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
10076 +       if (!result) {
10077 +               retval = -1;
10078 +               goto dh_modpow_nomem;
10079 +       }
10080 +
10081 +       dh_swap_bytes(&result[1], out, result[0] * 4);
10082 +       dwc_free(mem_ctx, result);
10083 +
10084 + dh_modpow_nomem:
10085 +       dwc_free(mem_ctx, bignum_num);
10086 +       dwc_free(mem_ctx, bignum_exp);
10087 +       dwc_free(mem_ctx, bignum_mod);
10088 +       return retval;
10089 +}
10090 +
10091 +
10092 +int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
10093 +{
10094 +       int retval;
10095 +       uint8_t m3[385];
10096 +
10097 +#ifndef DH_TEST_VECTORS
10098 +       DWC_RANDOM_BYTES(exp, 32);
10099 +#endif
10100 +
10101 +       /* Compute the pkd */
10102 +       if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
10103 +                                   exp, 32,
10104 +                                   dh_p, 384, pk))) {
10105 +               return retval;
10106 +       }
10107 +
10108 +       m3[384] = nd;
10109 +       DWC_MEMCPY(&m3[0], pk, 384);
10110 +       DWC_SHA256(m3, 385, hash);
10111 +
10112 +       dh_dump("PK", pk, 384);
10113 +       dh_dump("SHA-256(M3)", hash, 32);
10114 +       return 0;
10115 +}
10116 +
10117 +int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10118 +                      uint8_t *exp, int is_host,
10119 +                      char *dd, uint8_t *ck, uint8_t *kdk)
10120 +{
10121 +       int retval;
10122 +       uint8_t mv[784];
10123 +       uint8_t sha_result[32];
10124 +       uint8_t dhkey[384];
10125 +       uint8_t shared_secret[384];
10126 +       char *message;
10127 +       uint32_t vd;
10128 +
10129 +       uint8_t *pk;
10130 +
10131 +       if (is_host) {
10132 +               pk = pkd;
10133 +       }
10134 +       else {
10135 +               pk = pkh;
10136 +       }
10137 +
10138 +       if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
10139 +                                   exp, 32,
10140 +                                   dh_p, 384, shared_secret))) {
10141 +               return retval;
10142 +       }
10143 +       dh_dump("Shared Secret", shared_secret, 384);
10144 +
10145 +       DWC_SHA256(shared_secret, 384, dhkey);
10146 +       dh_dump("DHKEY", dhkey, 384);
10147 +
10148 +       DWC_MEMCPY(&mv[0], pkd, 384);
10149 +       DWC_MEMCPY(&mv[384], pkh, 384);
10150 +       DWC_MEMCPY(&mv[768], "displayed digest", 16);
10151 +       dh_dump("MV", mv, 784);
10152 +
10153 +       DWC_SHA256(mv, 784, sha_result);
10154 +       dh_dump("SHA-256(MV)", sha_result, 32);
10155 +       dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
10156 +
10157 +       dh_swap_bytes(sha_result, &vd, 4);
10158 +#ifdef DEBUG
10159 +       DWC_PRINTF("Vd (decimal) = %d\n", vd);
10160 +#endif
10161 +
10162 +       switch (nd) {
10163 +       case 2:
10164 +               vd = vd % 100;
10165 +               DWC_SPRINTF(dd, "%02d", vd);
10166 +               break;
10167 +       case 3:
10168 +               vd = vd % 1000;
10169 +               DWC_SPRINTF(dd, "%03d", vd);
10170 +               break;
10171 +       case 4:
10172 +               vd = vd % 10000;
10173 +               DWC_SPRINTF(dd, "%04d", vd);
10174 +               break;
10175 +       }
10176 +#ifdef DEBUG
10177 +       DWC_PRINTF("Display Digits: %s\n", dd);
10178 +#endif
10179 +
10180 +       message = "connection key";
10181 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10182 +       dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
10183 +       DWC_MEMCPY(ck, sha_result, 16);
10184 +
10185 +       message = "key derivation key";
10186 +       DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
10187 +       dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
10188 +       DWC_MEMCPY(kdk, sha_result, 32);
10189 +
10190 +       return 0;
10191 +}
10192 +
10193 +
10194 +#ifdef DH_TEST_VECTORS
10195 +
10196 +static __u8 dh_a[] = {
10197 +       0x44, 0x00, 0x51, 0xd6,
10198 +       0xf0, 0xb5, 0x5e, 0xa9,
10199 +       0x67, 0xab, 0x31, 0xc6,
10200 +       0x8a, 0x8b, 0x5e, 0x37,
10201 +       0xd9, 0x10, 0xda, 0xe0,
10202 +       0xe2, 0xd4, 0x59, 0xa4,
10203 +       0x86, 0x45, 0x9c, 0xaa,
10204 +       0xdf, 0x36, 0x75, 0x16,
10205 +};
10206 +
10207 +static __u8 dh_b[] = {
10208 +       0x5d, 0xae, 0xc7, 0x86,
10209 +       0x79, 0x80, 0xa3, 0x24,
10210 +       0x8c, 0xe3, 0x57, 0x8f,
10211 +       0xc7, 0x5f, 0x1b, 0x0f,
10212 +       0x2d, 0xf8, 0x9d, 0x30,
10213 +       0x6f, 0xa4, 0x52, 0xcd,
10214 +       0xe0, 0x7a, 0x04, 0x8a,
10215 +       0xde, 0xd9, 0x26, 0x56,
10216 +};
10217 +
10218 +void dwc_run_dh_test_vectors(void *mem_ctx)
10219 +{
10220 +       uint8_t pkd[384];
10221 +       uint8_t pkh[384];
10222 +       uint8_t hashd[32];
10223 +       uint8_t hashh[32];
10224 +       uint8_t ck[16];
10225 +       uint8_t kdk[32];
10226 +       char dd[5];
10227 +
10228 +       DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
10229 +
10230 +       /* compute the PKd and SHA-256(PKd || Nd) */
10231 +       DWC_PRINTF("Computing PKd\n");
10232 +       dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
10233 +
10234 +       /* compute the PKd and SHA-256(PKh || Nd) */
10235 +       DWC_PRINTF("Computing PKh\n");
10236 +       dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
10237 +
10238 +       /* compute the dhkey */
10239 +       dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
10240 +}
10241 +#endif /* DH_TEST_VECTORS */
10242 +
10243 +#endif /* !CONFIG_MACH_IPMATE */
10244 +
10245 +#endif /* DWC_CRYPTOLIB */
10246 --- /dev/null
10247 +++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
10248 @@ -0,0 +1,106 @@
10249 +/* =========================================================================
10250 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
10251 + * $Revision: #4 $
10252 + * $Date: 2010/09/28 $
10253 + * $Change: 1596182 $
10254 + *
10255 + * Synopsys Portability Library Software and documentation
10256 + * (hereinafter, "Software") is an Unsupported proprietary work of
10257 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
10258 + * between Synopsys and you.
10259 + *
10260 + * The Software IS NOT an item of Licensed Software or Licensed Product
10261 + * under any End User Software License Agreement or Agreement for
10262 + * Licensed Product with Synopsys or any supplement thereto. You are
10263 + * permitted to use and redistribute this Software in source and binary
10264 + * forms, with or without modification, provided that redistributions
10265 + * of source code must retain this notice. You may not view, use,
10266 + * disclose, copy or distribute this file or any information contained
10267 + * herein except pursuant to this license grant from Synopsys. If you
10268 + * do not agree with this notice, including the disclaimer below, then
10269 + * you are not authorized to use the Software.
10270 + *
10271 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
10272 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10273 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
10274 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
10275 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
10276 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
10277 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
10278 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
10279 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
10280 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
10281 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
10282 + * DAMAGE.
10283 + * ========================================================================= */
10284 +#ifndef _DWC_DH_H_
10285 +#define _DWC_DH_H_
10286 +
10287 +#ifdef __cplusplus
10288 +extern "C" {
10289 +#endif
10290 +
10291 +#include "dwc_os.h"
10292 +
10293 +/** @file
10294 + *
10295 + * This file defines the common functions on device and host for performing
10296 + * numeric association as defined in the WUSB spec.  They are only to be
10297 + * used internally by the DWC UWB modules. */
10298 +
10299 +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
10300 +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
10301 +                             uint8_t *key, uint32_t keylen,
10302 +                             uint8_t *out);
10303 +extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
10304 +                        void *exp, uint32_t exp_len,
10305 +                        void *mod, uint32_t mod_len,
10306 +                        void *out);
10307 +
10308 +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
10309 + *
10310 + * PK = g^exp mod p.
10311 + *
10312 + * Input:
10313 + * Nd = Number of digits on the device.
10314 + *
10315 + * Output:
10316 + * exp = A 32-byte buffer to be filled with a randomly generated number.
10317 + *       used as either A or B.
10318 + * pk = A 384-byte buffer to be filled with the PKH or PKD.
10319 + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
10320 + */
10321 +extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
10322 +
10323 +/** Computes the DHKEY, and VD.
10324 + *
10325 + * If called from host, then it will comput DHKEY=PKD^exp % p.
10326 + * If called from device, then it will comput DHKEY=PKH^exp % p.
10327 + *
10328 + * Input:
10329 + * pkd = The PKD value.
10330 + * pkh = The PKH value.
10331 + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
10332 + * is_host = Set to non zero if a WUSB host is calling this function.
10333 + *
10334 + * Output:
10335 +
10336 + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
10337 + *      to the user.  This buffer should be at 5 bytes long to hold 4 digits plus a
10338 + *      null termination character.  This buffer can be used directly for display.
10339 + * ck = A 16-byte buffer to be filled with the CK.
10340 + * kdk = A 32-byte buffer to be filled with the KDK.
10341 + */
10342 +extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
10343 +                             uint8_t *exp, int is_host,
10344 +                             char *dd, uint8_t *ck, uint8_t *kdk);
10345 +
10346 +#ifdef DH_TEST_VECTORS
10347 +extern void dwc_run_dh_test_vectors(void);
10348 +#endif
10349 +
10350 +#ifdef __cplusplus
10351 +}
10352 +#endif
10353 +
10354 +#endif /* _DWC_DH_H_ */
10355 --- /dev/null
10356 +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
10357 @@ -0,0 +1,594 @@
10358 +/*     $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $       */
10359 +/*     $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $       */
10360 +
10361 +/*
10362 + * Copyright (c) 1991, 1993
10363 + *     The Regents of the University of California.  All rights reserved.
10364 + *
10365 + * Redistribution and use in source and binary forms, with or without
10366 + * modification, are permitted provided that the following conditions
10367 + * are met:
10368 + * 1. Redistributions of source code must retain the above copyright
10369 + *    notice, this list of conditions and the following disclaimer.
10370 + * 2. Redistributions in binary form must reproduce the above copyright
10371 + *    notice, this list of conditions and the following disclaimer in the
10372 + *    documentation and/or other materials provided with the distribution.
10373 + * 3. Neither the name of the University nor the names of its contributors
10374 + *    may be used to endorse or promote products derived from this software
10375 + *    without specific prior written permission.
10376 + *
10377 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
10378 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10379 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10380 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
10381 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10382 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10383 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10384 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10385 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10386 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10387 + * SUCH DAMAGE.
10388 + *
10389 + *     @(#)queue.h     8.5 (Berkeley) 8/20/94
10390 + */
10391 +
10392 +#ifndef _DWC_LIST_H_
10393 +#define _DWC_LIST_H_
10394 +
10395 +#ifdef __cplusplus
10396 +extern "C" {
10397 +#endif
10398 +
10399 +/** @file
10400 + *
10401 + * This file defines linked list operations.  It is derived from BSD with
10402 + * only the MACRO names being prefixed with DWC_.  This is because a few of
10403 + * these names conflict with those on Linux.  For documentation on use, see the
10404 + * inline comments in the source code.  The original license for this source
10405 + * code applies and is preserved in the dwc_list.h source file.
10406 + */
10407 +
10408 +/*
10409 + * This file defines five types of data structures: singly-linked lists,
10410 + * lists, simple queues, tail queues, and circular queues.
10411 + *
10412 + *
10413 + * A singly-linked list is headed by a single forward pointer. The elements
10414 + * are singly linked for minimum space and pointer manipulation overhead at
10415 + * the expense of O(n) removal for arbitrary elements. New elements can be
10416 + * added to the list after an existing element or at the head of the list.
10417 + * Elements being removed from the head of the list should use the explicit
10418 + * macro for this purpose for optimum efficiency. A singly-linked list may
10419 + * only be traversed in the forward direction.  Singly-linked lists are ideal
10420 + * for applications with large datasets and few or no removals or for
10421 + * implementing a LIFO queue.
10422 + *
10423 + * A list is headed by a single forward pointer (or an array of forward
10424 + * pointers for a hash table header). The elements are doubly linked
10425 + * so that an arbitrary element can be removed without a need to
10426 + * traverse the list. New elements can be added to the list before
10427 + * or after an existing element or at the head of the list. A list
10428 + * may only be traversed in the forward direction.
10429 + *
10430 + * A simple queue is headed by a pair of pointers, one the head of the
10431 + * list and the other to the tail of the list. The elements are singly
10432 + * linked to save space, so elements can only be removed from the
10433 + * head of the list. New elements can be added to the list before or after
10434 + * an existing element, at the head of the list, or at the end of the
10435 + * list. A simple queue may only be traversed in the forward direction.
10436 + *
10437 + * A tail queue is headed by a pair of pointers, one to the head of the
10438 + * list and the other to the tail of the list. The elements are doubly
10439 + * linked 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 or
10441 + * after an existing element, at the head of the list, or at the end of
10442 + * the list. A tail queue may be traversed in either direction.
10443 + *
10444 + * A circle queue is headed by a pair of pointers, one to the head of the
10445 + * list and the other to the tail of the list. The elements are doubly
10446 + * linked so that an arbitrary element can be removed without a need to
10447 + * traverse 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 list.
10449 + * A circle queue may be traversed in either direction, but has a more
10450 + * complex end of list detection.
10451 + *
10452 + * For details on the use of these macros, see the queue(3) manual page.
10453 + */
10454 +
10455 +/*
10456 + * Double-linked List.
10457 + */
10458 +
10459 +typedef struct dwc_list_link {
10460 +       struct dwc_list_link *next;
10461 +       struct dwc_list_link *prev;
10462 +} dwc_list_link_t;
10463 +
10464 +#define DWC_LIST_INIT(link) do {       \
10465 +       (link)->next = (link);          \
10466 +       (link)->prev = (link);          \
10467 +} while (0)
10468 +
10469 +#define DWC_LIST_FIRST(link)   ((link)->next)
10470 +#define DWC_LIST_LAST(link)    ((link)->prev)
10471 +#define DWC_LIST_END(link)     (link)
10472 +#define DWC_LIST_NEXT(link)    ((link)->next)
10473 +#define DWC_LIST_PREV(link)    ((link)->prev)
10474 +#define DWC_LIST_EMPTY(link)   \
10475 +       (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
10476 +#define DWC_LIST_ENTRY(link, type, field)                      \
10477 +       (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))
10478 +
10479 +#if 0
10480 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10481 +       (link)->next = (list)->next;                            \
10482 +       (link)->prev = (list);                                  \
10483 +       (list)->next->prev = (link);                            \
10484 +       (list)->next = (link);                                  \
10485 +} while (0)
10486 +
10487 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10488 +       (link)->next = (list);                                  \
10489 +       (link)->prev = (list)->prev;                            \
10490 +       (list)->prev->next = (link);                            \
10491 +       (list)->prev = (link);                                  \
10492 +} while (0)
10493 +#else
10494 +#define DWC_LIST_INSERT_HEAD(list, link) do {                  \
10495 +       dwc_list_link_t *__next__ = (list)->next;               \
10496 +       __next__->prev = (link);                                \
10497 +       (link)->next = __next__;                                \
10498 +       (link)->prev = (list);                                  \
10499 +       (list)->next = (link);                                  \
10500 +} while (0)
10501 +
10502 +#define DWC_LIST_INSERT_TAIL(list, link) do {                  \
10503 +       dwc_list_link_t *__prev__ = (list)->prev;               \
10504 +       (list)->prev = (link);                                  \
10505 +       (link)->next = (list);                                  \
10506 +       (link)->prev = __prev__;                                \
10507 +       __prev__->next = (link);                                \
10508 +} while (0)
10509 +#endif
10510 +
10511 +#if 0
10512 +static inline void __list_add(struct list_head *new,
10513 +                              struct list_head *prev,
10514 +                              struct list_head *next)
10515 +{
10516 +        next->prev = new;
10517 +        new->next = next;
10518 +        new->prev = prev;
10519 +        prev->next = new;
10520 +}
10521 +
10522 +static inline void list_add(struct list_head *new, struct list_head *head)
10523 +{
10524 +        __list_add(new, head, head->next);
10525 +}
10526 +
10527 +static inline void list_add_tail(struct list_head *new, struct list_head *head)
10528 +{
10529 +        __list_add(new, head->prev, head);
10530 +}
10531 +
10532 +static inline void __list_del(struct list_head * prev, struct list_head * next)
10533 +{
10534 +        next->prev = prev;
10535 +        prev->next = next;
10536 +}
10537 +
10538 +static inline void list_del(struct list_head *entry)
10539 +{
10540 +        __list_del(entry->prev, entry->next);
10541 +        entry->next = LIST_POISON1;
10542 +        entry->prev = LIST_POISON2;
10543 +}
10544 +#endif
10545 +
10546 +#define DWC_LIST_REMOVE(link) do {                             \
10547 +       (link)->next->prev = (link)->prev;                      \
10548 +       (link)->prev->next = (link)->next;                      \
10549 +} while (0)
10550 +
10551 +#define DWC_LIST_REMOVE_INIT(link) do {                                \
10552 +       DWC_LIST_REMOVE(link);                                  \
10553 +       DWC_LIST_INIT(link);                                    \
10554 +} while (0)
10555 +
10556 +#define DWC_LIST_MOVE_HEAD(list, link) do {                    \
10557 +       DWC_LIST_REMOVE(link);                                  \
10558 +       DWC_LIST_INSERT_HEAD(list, link);                       \
10559 +} while (0)
10560 +
10561 +#define DWC_LIST_MOVE_TAIL(list, link) do {                    \
10562 +       DWC_LIST_REMOVE(link);                                  \
10563 +       DWC_LIST_INSERT_TAIL(list, link);                       \
10564 +} while (0)
10565 +
10566 +#define DWC_LIST_FOREACH(var, list)                            \
10567 +       for((var) = DWC_LIST_FIRST(list);                       \
10568 +           (var) != DWC_LIST_END(list);                        \
10569 +           (var) = DWC_LIST_NEXT(var))
10570 +
10571 +#define DWC_LIST_FOREACH_SAFE(var, var2, list)                 \
10572 +       for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var);  \
10573 +           (var) != DWC_LIST_END(list);                        \
10574 +           (var) = (var2), (var2) = DWC_LIST_NEXT(var2))
10575 +
10576 +#define DWC_LIST_FOREACH_REVERSE(var, list)                    \
10577 +       for((var) = DWC_LIST_LAST(list);                        \
10578 +           (var) != DWC_LIST_END(list);                        \
10579 +           (var) = DWC_LIST_PREV(var))
10580 +
10581 +/*
10582 + * Singly-linked List definitions.
10583 + */
10584 +#define DWC_SLIST_HEAD(name, type)                                     \
10585 +struct name {                                                          \
10586 +       struct type *slh_first; /* first element */                     \
10587 +}
10588 +
10589 +#define DWC_SLIST_HEAD_INITIALIZER(head)                               \
10590 +       { NULL }
10591 +
10592 +#define DWC_SLIST_ENTRY(type)                                          \
10593 +struct {                                                               \
10594 +       struct type *sle_next;  /* next element */                      \
10595 +}
10596 +
10597 +/*
10598 + * Singly-linked List access methods.
10599 + */
10600 +#define DWC_SLIST_FIRST(head)  ((head)->slh_first)
10601 +#define DWC_SLIST_END(head)            NULL
10602 +#define DWC_SLIST_EMPTY(head)  (SLIST_FIRST(head) == SLIST_END(head))
10603 +#define DWC_SLIST_NEXT(elm, field)     ((elm)->field.sle_next)
10604 +
10605 +#define DWC_SLIST_FOREACH(var, head, field)                            \
10606 +       for((var) = SLIST_FIRST(head);                                  \
10607 +           (var) != SLIST_END(head);                                   \
10608 +           (var) = SLIST_NEXT(var, field))
10609 +
10610 +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field)              \
10611 +       for((varp) = &SLIST_FIRST((head));                              \
10612 +           ((var) = *(varp)) != SLIST_END(head);                       \
10613 +           (varp) = &SLIST_NEXT((var), field))
10614 +
10615 +/*
10616 + * Singly-linked List functions.
10617 + */
10618 +#define DWC_SLIST_INIT(head) {                                         \
10619 +       SLIST_FIRST(head) = SLIST_END(head);                            \
10620 +}
10621 +
10622 +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do {              \
10623 +       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
10624 +       (slistelm)->field.sle_next = (elm);                             \
10625 +} while (0)
10626 +
10627 +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do {                   \
10628 +       (elm)->field.sle_next = (head)->slh_first;                      \
10629 +       (head)->slh_first = (elm);                                      \
10630 +} while (0)
10631 +
10632 +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do {                   \
10633 +       (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;  \
10634 +} while (0)
10635 +
10636 +#define DWC_SLIST_REMOVE_HEAD(head, field) do {                                \
10637 +       (head)->slh_first = (head)->slh_first->field.sle_next;          \
10638 +} while (0)
10639 +
10640 +#define DWC_SLIST_REMOVE(head, elm, type, field) do {                  \
10641 +       if ((head)->slh_first == (elm)) {                               \
10642 +               SLIST_REMOVE_HEAD((head), field);                       \
10643 +       }                                                               \
10644 +       else {                                                          \
10645 +               struct type *curelm = (head)->slh_first;                \
10646 +               while( curelm->field.sle_next != (elm) )                \
10647 +                       curelm = curelm->field.sle_next;                \
10648 +               curelm->field.sle_next =                                \
10649 +                   curelm->field.sle_next->field.sle_next;             \
10650 +       }                                                               \
10651 +} while (0)
10652 +
10653 +/*
10654 + * Simple queue definitions.
10655 + */
10656 +#define DWC_SIMPLEQ_HEAD(name, type)                                   \
10657 +struct name {                                                          \
10658 +       struct type *sqh_first; /* first element */                     \
10659 +       struct type **sqh_last; /* addr of last next element */         \
10660 +}
10661 +
10662 +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head)                             \
10663 +       { NULL, &(head).sqh_first }
10664 +
10665 +#define DWC_SIMPLEQ_ENTRY(type)                                                \
10666 +struct {                                                               \
10667 +       struct type *sqe_next;  /* next element */                      \
10668 +}
10669 +
10670 +/*
10671 + * Simple queue access methods.
10672 + */
10673 +#define DWC_SIMPLEQ_FIRST(head)            ((head)->sqh_first)
10674 +#define DWC_SIMPLEQ_END(head)      NULL
10675 +#define DWC_SIMPLEQ_EMPTY(head)            (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
10676 +#define DWC_SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
10677 +
10678 +#define DWC_SIMPLEQ_FOREACH(var, head, field)                          \
10679 +       for((var) = SIMPLEQ_FIRST(head);                                \
10680 +           (var) != SIMPLEQ_END(head);                                 \
10681 +           (var) = SIMPLEQ_NEXT(var, field))
10682 +
10683 +/*
10684 + * Simple queue functions.
10685 + */
10686 +#define DWC_SIMPLEQ_INIT(head) do {                                    \
10687 +       (head)->sqh_first = NULL;                                       \
10688 +       (head)->sqh_last = &(head)->sqh_first;                          \
10689 +} while (0)
10690 +
10691 +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do {                 \
10692 +       if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)        \
10693 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10694 +       (head)->sqh_first = (elm);                                      \
10695 +} while (0)
10696 +
10697 +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do {                 \
10698 +       (elm)->field.sqe_next = NULL;                                   \
10699 +       *(head)->sqh_last = (elm);                                      \
10700 +       (head)->sqh_last = &(elm)->field.sqe_next;                      \
10701 +} while (0)
10702 +
10703 +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10704 +       if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
10705 +               (head)->sqh_last = &(elm)->field.sqe_next;              \
10706 +       (listelm)->field.sqe_next = (elm);                              \
10707 +} while (0)
10708 +
10709 +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do {                      \
10710 +       if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
10711 +               (head)->sqh_last = &(head)->sqh_first;                  \
10712 +} while (0)
10713 +
10714 +/*
10715 + * Tail queue definitions.
10716 + */
10717 +#define DWC_TAILQ_HEAD(name, type)                                     \
10718 +struct name {                                                          \
10719 +       struct type *tqh_first; /* first element */                     \
10720 +       struct type **tqh_last; /* addr of last next element */         \
10721 +}
10722 +
10723 +#define DWC_TAILQ_HEAD_INITIALIZER(head)                               \
10724 +       { NULL, &(head).tqh_first }
10725 +
10726 +#define DWC_TAILQ_ENTRY(type)                                          \
10727 +struct {                                                               \
10728 +       struct type *tqe_next;  /* next element */                      \
10729 +       struct type **tqe_prev; /* address of previous next element */  \
10730 +}
10731 +
10732 +/*
10733 + * tail queue access methods
10734 + */
10735 +#define DWC_TAILQ_FIRST(head)          ((head)->tqh_first)
10736 +#define DWC_TAILQ_END(head)            NULL
10737 +#define DWC_TAILQ_NEXT(elm, field)     ((elm)->field.tqe_next)
10738 +#define DWC_TAILQ_LAST(head, headname)                                 \
10739 +       (*(((struct headname *)((head)->tqh_last))->tqh_last))
10740 +/* XXX */
10741 +#define DWC_TAILQ_PREV(elm, headname, field)                           \
10742 +       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
10743 +#define DWC_TAILQ_EMPTY(head)                                          \
10744 +       (TAILQ_FIRST(head) == TAILQ_END(head))
10745 +
10746 +#define DWC_TAILQ_FOREACH(var, head, field)                            \
10747 +       for((var) = TAILQ_FIRST(head);                                  \
10748 +           (var) != TAILQ_END(head);                                   \
10749 +           (var) = TAILQ_NEXT(var, field))
10750 +
10751 +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field)          \
10752 +       for((var) = TAILQ_LAST(head, headname);                         \
10753 +           (var) != TAILQ_END(head);                                   \
10754 +           (var) = TAILQ_PREV(var, headname, field))
10755 +
10756 +/*
10757 + * Tail queue functions.
10758 + */
10759 +#define DWC_TAILQ_INIT(head) do {                                      \
10760 +       (head)->tqh_first = NULL;                                       \
10761 +       (head)->tqh_last = &(head)->tqh_first;                          \
10762 +} while (0)
10763 +
10764 +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do {                   \
10765 +       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
10766 +               (head)->tqh_first->field.tqe_prev =                     \
10767 +                   &(elm)->field.tqe_next;                             \
10768 +       else                                                            \
10769 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10770 +       (head)->tqh_first = (elm);                                      \
10771 +       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
10772 +} while (0)
10773 +
10774 +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do {                   \
10775 +       (elm)->field.tqe_next = NULL;                                   \
10776 +       (elm)->field.tqe_prev = (head)->tqh_last;                       \
10777 +       *(head)->tqh_last = (elm);                                      \
10778 +       (head)->tqh_last = &(elm)->field.tqe_next;                      \
10779 +} while (0)
10780 +
10781 +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {         \
10782 +       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
10783 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10784 +                   &(elm)->field.tqe_next;                             \
10785 +       else                                                            \
10786 +               (head)->tqh_last = &(elm)->field.tqe_next;              \
10787 +       (listelm)->field.tqe_next = (elm);                              \
10788 +       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
10789 +} while (0)
10790 +
10791 +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do {              \
10792 +       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
10793 +       (elm)->field.tqe_next = (listelm);                              \
10794 +       *(listelm)->field.tqe_prev = (elm);                             \
10795 +       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
10796 +} while (0)
10797 +
10798 +#define DWC_TAILQ_REMOVE(head, elm, field) do {                                \
10799 +       if (((elm)->field.tqe_next) != NULL)                            \
10800 +               (elm)->field.tqe_next->field.tqe_prev =                 \
10801 +                   (elm)->field.tqe_prev;                              \
10802 +       else                                                            \
10803 +               (head)->tqh_last = (elm)->field.tqe_prev;               \
10804 +       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
10805 +} while (0)
10806 +
10807 +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do {                 \
10808 +       if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   \
10809 +               (elm2)->field.tqe_next->field.tqe_prev =                \
10810 +                   &(elm2)->field.tqe_next;                            \
10811 +       else                                                            \
10812 +               (head)->tqh_last = &(elm2)->field.tqe_next;             \
10813 +       (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
10814 +       *(elm2)->field.tqe_prev = (elm2);                               \
10815 +} while (0)
10816 +
10817 +/*
10818 + * Circular queue definitions.
10819 + */
10820 +#define DWC_CIRCLEQ_HEAD(name, type)                                   \
10821 +struct name {                                                          \
10822 +       struct type *cqh_first;         /* first element */             \
10823 +       struct type *cqh_last;          /* last element */              \
10824 +}
10825 +
10826 +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head)                             \
10827 +       { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
10828 +
10829 +#define DWC_CIRCLEQ_ENTRY(type)                                                \
10830 +struct {                                                               \
10831 +       struct type *cqe_next;          /* next element */              \
10832 +       struct type *cqe_prev;          /* previous element */          \
10833 +}
10834 +
10835 +/*
10836 + * Circular queue access methods
10837 + */
10838 +#define DWC_CIRCLEQ_FIRST(head)                ((head)->cqh_first)
10839 +#define DWC_CIRCLEQ_LAST(head)         ((head)->cqh_last)
10840 +#define DWC_CIRCLEQ_END(head)          ((void *)(head))
10841 +#define DWC_CIRCLEQ_NEXT(elm, field)   ((elm)->field.cqe_next)
10842 +#define DWC_CIRCLEQ_PREV(elm, field)   ((elm)->field.cqe_prev)
10843 +#define DWC_CIRCLEQ_EMPTY(head)                                                \
10844 +       (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
10845 +
10846 +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
10847 +
10848 +#define DWC_CIRCLEQ_FOREACH(var, head, field)                          \
10849 +       for((var) = DWC_CIRCLEQ_FIRST(head);                            \
10850 +           (var) != DWC_CIRCLEQ_END(head);                             \
10851 +           (var) = DWC_CIRCLEQ_NEXT(var, field))
10852 +
10853 +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field)                       \
10854 +       for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \
10855 +           (var) != DWC_CIRCLEQ_END(head);                                     \
10856 +           (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
10857 +
10858 +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field)                  \
10859 +       for((var) = DWC_CIRCLEQ_LAST(head);                             \
10860 +           (var) != DWC_CIRCLEQ_END(head);                             \
10861 +           (var) = DWC_CIRCLEQ_PREV(var, field))
10862 +
10863 +/*
10864 + * Circular queue functions.
10865 + */
10866 +#define DWC_CIRCLEQ_INIT(head) do {                                    \
10867 +       (head)->cqh_first = DWC_CIRCLEQ_END(head);                      \
10868 +       (head)->cqh_last = DWC_CIRCLEQ_END(head);                       \
10869 +} while (0)
10870 +
10871 +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do {                                \
10872 +       (elm)->field.cqe_next = NULL;                                   \
10873 +       (elm)->field.cqe_prev = NULL;                                   \
10874 +} while (0)
10875 +
10876 +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {       \
10877 +       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
10878 +       (elm)->field.cqe_prev = (listelm);                              \
10879 +       if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head))         \
10880 +               (head)->cqh_last = (elm);                               \
10881 +       else                                                            \
10882 +               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
10883 +       (listelm)->field.cqe_next = (elm);                              \
10884 +} while (0)
10885 +
10886 +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {      \
10887 +       (elm)->field.cqe_next = (listelm);                              \
10888 +       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
10889 +       if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head))         \
10890 +               (head)->cqh_first = (elm);                              \
10891 +       else                                                            \
10892 +               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
10893 +       (listelm)->field.cqe_prev = (elm);                              \
10894 +} while (0)
10895 +
10896 +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do {                 \
10897 +       (elm)->field.cqe_next = (head)->cqh_first;                      \
10898 +       (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head);                  \
10899 +       if ((head)->cqh_last == DWC_CIRCLEQ_END(head))                  \
10900 +               (head)->cqh_last = (elm);                               \
10901 +       else                                                            \
10902 +               (head)->cqh_first->field.cqe_prev = (elm);              \
10903 +       (head)->cqh_first = (elm);                                      \
10904 +} while (0)
10905 +
10906 +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do {                 \
10907 +       (elm)->field.cqe_next = DWC_CIRCLEQ_END(head);                  \
10908 +       (elm)->field.cqe_prev = (head)->cqh_last;                       \
10909 +       if ((head)->cqh_first == DWC_CIRCLEQ_END(head))                 \
10910 +               (head)->cqh_first = (elm);                              \
10911 +       else                                                            \
10912 +               (head)->cqh_last->field.cqe_next = (elm);               \
10913 +       (head)->cqh_last = (elm);                                       \
10914 +} while (0)
10915 +
10916 +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do {                      \
10917 +       if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head))             \
10918 +               (head)->cqh_last = (elm)->field.cqe_prev;               \
10919 +       else                                                            \
10920 +               (elm)->field.cqe_next->field.cqe_prev =                 \
10921 +                   (elm)->field.cqe_prev;                              \
10922 +       if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head))             \
10923 +               (head)->cqh_first = (elm)->field.cqe_next;              \
10924 +       else                                                            \
10925 +               (elm)->field.cqe_prev->field.cqe_next =                 \
10926 +                   (elm)->field.cqe_next;                              \
10927 +} while (0)
10928 +
10929 +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do {                 \
10930 +       DWC_CIRCLEQ_REMOVE(head, elm, field);                           \
10931 +       DWC_CIRCLEQ_INIT_ENTRY(elm, field);                             \
10932 +} while (0)
10933 +
10934 +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do {               \
10935 +       if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==         \
10936 +           DWC_CIRCLEQ_END(head))                                      \
10937 +               (head).cqh_last = (elm2);                               \
10938 +       else                                                            \
10939 +               (elm2)->field.cqe_next->field.cqe_prev = (elm2);        \
10940 +       if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==         \
10941 +           DWC_CIRCLEQ_END(head))                                      \
10942 +               (head).cqh_first = (elm2);                              \
10943 +       else                                                            \
10944 +               (elm2)->field.cqe_prev->field.cqe_next = (elm2);        \
10945 +} while (0)
10946 +
10947 +#ifdef __cplusplus
10948 +}
10949 +#endif
10950 +
10951 +#endif /* _DWC_LIST_H_ */
10952 --- /dev/null
10953 +++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
10954 @@ -0,0 +1,245 @@
10955 +/* Memory Debugging */
10956 +#ifdef DWC_DEBUG_MEMORY
10957 +
10958 +#include "dwc_os.h"
10959 +#include "dwc_list.h"
10960 +
10961 +struct allocation {
10962 +       void *addr;
10963 +       void *ctx;
10964 +       char *func;
10965 +       int line;
10966 +       uint32_t size;
10967 +       int dma;
10968 +       DWC_CIRCLEQ_ENTRY(allocation) entry;
10969 +};
10970 +
10971 +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
10972 +
10973 +struct allocation_manager {
10974 +       void *mem_ctx;
10975 +       struct allocation_queue allocations;
10976 +
10977 +       /* statistics */
10978 +       int num;
10979 +       int num_freed;
10980 +       int num_active;
10981 +       uint32_t total;
10982 +       uint32_t cur;
10983 +       uint32_t max;
10984 +};
10985 +
10986 +static struct allocation_manager *manager = NULL;
10987 +
10988 +static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
10989 +                         int dma)
10990 +{
10991 +       struct allocation *a;
10992 +
10993 +       DWC_ASSERT(manager != NULL, "manager not allocated");
10994 +
10995 +       a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
10996 +       if (!a) {
10997 +               return -DWC_E_NO_MEMORY;
10998 +       }
10999 +
11000 +       a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
11001 +       if (!a->func) {
11002 +               __DWC_FREE(manager->mem_ctx, a);
11003 +               return -DWC_E_NO_MEMORY;
11004 +       }
11005 +
11006 +       DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
11007 +       a->addr = addr;
11008 +       a->ctx = ctx;
11009 +       a->line = line;
11010 +       a->size = size;
11011 +       a->dma = dma;
11012 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
11013 +
11014 +       /* Update stats */
11015 +       manager->num++;
11016 +       manager->num_active++;
11017 +       manager->total += size;
11018 +       manager->cur += size;
11019 +
11020 +       if (manager->max < manager->cur) {
11021 +               manager->max = manager->cur;
11022 +       }
11023 +
11024 +       return 0;
11025 +}
11026 +
11027 +static struct allocation *find_allocation(void *ctx, void *addr)
11028 +{
11029 +       struct allocation *a;
11030 +
11031 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11032 +               if (a->ctx == ctx && a->addr == addr) {
11033 +                       return a;
11034 +               }
11035 +       }
11036 +
11037 +       return NULL;
11038 +}
11039 +
11040 +static void free_allocation(void *ctx, void *addr, char const *func, int line)
11041 +{
11042 +       struct allocation *a = find_allocation(ctx, addr);
11043 +
11044 +       if (!a) {
11045 +               DWC_ASSERT(0,
11046 +                          "Free of address %p that was never allocated or already freed %s:%d",
11047 +                          addr, func, line);
11048 +               return;
11049 +       }
11050 +
11051 +       DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
11052 +
11053 +       manager->num_active--;
11054 +       manager->num_freed++;
11055 +       manager->cur -= a->size;
11056 +       __DWC_FREE(manager->mem_ctx, a->func);
11057 +       __DWC_FREE(manager->mem_ctx, a);
11058 +}
11059 +
11060 +int dwc_memory_debug_start(void *mem_ctx)
11061 +{
11062 +       DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
11063 +
11064 +       if (manager) {
11065 +               return -DWC_E_BUSY;
11066 +       }
11067 +
11068 +       manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
11069 +       if (!manager) {
11070 +               return -DWC_E_NO_MEMORY;
11071 +       }
11072 +
11073 +       DWC_CIRCLEQ_INIT(&manager->allocations);
11074 +       manager->mem_ctx = mem_ctx;
11075 +       manager->num = 0;
11076 +       manager->num_freed = 0;
11077 +       manager->num_active = 0;
11078 +       manager->total = 0;
11079 +       manager->cur = 0;
11080 +       manager->max = 0;
11081 +
11082 +       return 0;
11083 +}
11084 +
11085 +void dwc_memory_debug_stop(void)
11086 +{
11087 +       struct allocation *a;
11088 +
11089 +       dwc_memory_debug_report();
11090 +
11091 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11092 +               DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
11093 +               free_allocation(a->ctx, a->addr, NULL, -1);
11094 +       }
11095 +
11096 +       __DWC_FREE(manager->mem_ctx, manager);
11097 +}
11098 +
11099 +void dwc_memory_debug_report(void)
11100 +{
11101 +       struct allocation *a;
11102 +
11103 +       DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
11104 +       DWC_PRINTF("Num Allocations = %d\n", manager->num);
11105 +       DWC_PRINTF("Freed = %d\n", manager->num_freed);
11106 +       DWC_PRINTF("Active = %d\n", manager->num_active);
11107 +       DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
11108 +       DWC_PRINTF("Total Memory Used = %d\n", manager->total);
11109 +       DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
11110 +       DWC_PRINTF("Unfreed allocations:\n");
11111 +
11112 +       DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
11113 +               DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n",
11114 +                          a->addr, a->size, a->func, a->line, a->dma);
11115 +       }
11116 +}
11117 +
11118 +/* The replacement functions */
11119 +void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
11120 +{
11121 +       void *addr = __DWC_ALLOC(mem_ctx, size);
11122 +
11123 +       if (!addr) {
11124 +               return NULL;
11125 +       }
11126 +
11127 +       if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
11128 +               __DWC_FREE(mem_ctx, addr);
11129 +               return NULL;
11130 +       }
11131 +
11132 +       return addr;
11133 +}
11134 +
11135 +void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
11136 +                            int line)
11137 +{
11138 +       void *addr = __DWC_ALLOC_ATOMIC(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_free_debug(void *mem_ctx, void *addr, char const *func, int line)
11153 +{
11154 +       free_allocation(mem_ctx, addr, func, line);
11155 +       __DWC_FREE(mem_ctx, addr);
11156 +}
11157 +
11158 +void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
11159 +                         char const *func, int line)
11160 +{
11161 +       void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
11162 +
11163 +       if (!addr) {
11164 +               return NULL;
11165 +       }
11166 +
11167 +       if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
11168 +               __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
11169 +               return NULL;
11170 +       }
11171 +
11172 +       return addr;
11173 +}
11174 +
11175 +void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
11176 +                                dwc_dma_t *dma_addr, char const *func, int line)
11177 +{
11178 +       void *addr = __DWC_DMA_ALLOC_ATOMIC(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_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
11193 +                       dwc_dma_t dma_addr, char const *func, int line)
11194 +{
11195 +       free_allocation(dma_ctx, virt_addr, func, line);
11196 +       __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
11197 +}
11198 +
11199 +#endif /* DWC_DEBUG_MEMORY */
11200 --- /dev/null
11201 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
11202 @@ -0,0 +1,636 @@
11203 +/* Bignum routines adapted from PUTTY sources.  PuTTY copyright notice follows.
11204 + *
11205 + * PuTTY is copyright 1997-2007 Simon Tatham.
11206 + *
11207 + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
11208 + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
11209 + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
11210 + * Kuhn, and CORE SDI S.A.
11211 + *
11212 + * Permission is hereby granted, free of charge, to any person
11213 + * obtaining a copy of this software and associated documentation files
11214 + * (the "Software"), to deal in the Software without restriction,
11215 + * including without limitation the rights to use, copy, modify, merge,
11216 + * publish, distribute, sublicense, and/or sell copies of the Software,
11217 + * and to permit persons to whom the Software is furnished to do so,
11218 + * subject to the following conditions:
11219 + *
11220 + * The above copyright notice and this permission notice shall be
11221 + * included in all copies or substantial portions of the Software.
11222 +
11223 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11224 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11225 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
11226 + * NONINFRINGEMENT.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
11227 + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
11228 + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
11229 + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11230 + *
11231 + */
11232 +#ifdef DWC_CRYPTOLIB
11233 +
11234 +#ifndef CONFIG_MACH_IPMATE
11235 +
11236 +#include "dwc_modpow.h"
11237 +
11238 +#define BIGNUM_INT_MASK  0xFFFFFFFFUL
11239 +#define BIGNUM_TOP_BIT   0x80000000UL
11240 +#define BIGNUM_INT_BITS  32
11241 +
11242 +
11243 +static void *snmalloc(void *mem_ctx, size_t n, size_t size)
11244 +{
11245 +    void *p;
11246 +    size *= n;
11247 +    if (size == 0) size = 1;
11248 +    p = dwc_alloc(mem_ctx, size);
11249 +    return p;
11250 +}
11251 +
11252 +#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))
11253 +#define sfree dwc_free
11254 +
11255 +/*
11256 + * Usage notes:
11257 + *  * Do not call the DIVMOD_WORD macro with expressions such as array
11258 + *    subscripts, as some implementations object to this (see below).
11259 + *  * Note that none of the division methods below will cope if the
11260 + *    quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
11261 + *    to avoid this case.
11262 + *    If this condition occurs, in the case of the x86 DIV instruction,
11263 + *    an overflow exception will occur, which (according to a correspondent)
11264 + *    will manifest on Windows as something like
11265 + *      0xC0000095: Integer overflow
11266 + *    The C variant won't give the right answer, either.
11267 + */
11268 +
11269 +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
11270 +
11271 +#if defined __GNUC__ && defined __i386__
11272 +#define DIVMOD_WORD(q, r, hi, lo, w) \
11273 +    __asm__("div %2" : \
11274 +           "=d" (r), "=a" (q) : \
11275 +           "r" (w), "d" (hi), "a" (lo))
11276 +#else
11277 +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
11278 +    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
11279 +    q = n / w; \
11280 +    r = n % w; \
11281 +} while (0)
11282 +#endif
11283 +
11284 +//    q = n / w;
11285 +//    r = n % w;
11286 +
11287 +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
11288 +
11289 +#define BIGNUM_INTERNAL
11290 +
11291 +static Bignum newbn(void *mem_ctx, int length)
11292 +{
11293 +    Bignum b = snewn(mem_ctx, length + 1, BignumInt);
11294 +    //if (!b)
11295 +    //abort();                /* FIXME */
11296 +    DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
11297 +    b[0] = length;
11298 +    return b;
11299 +}
11300 +
11301 +void freebn(void *mem_ctx, Bignum b)
11302 +{
11303 +    /*
11304 +     * Burn the evidence, just in case.
11305 +     */
11306 +    DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
11307 +    sfree(mem_ctx, b);
11308 +}
11309 +
11310 +/*
11311 + * Compute c = a * b.
11312 + * Input is in the first len words of a and b.
11313 + * Result is returned in the first 2*len words of c.
11314 + */
11315 +static void internal_mul(BignumInt *a, BignumInt *b,
11316 +                        BignumInt *c, int len)
11317 +{
11318 +    int i, j;
11319 +    BignumDblInt t;
11320 +
11321 +    for (j = 0; j < 2 * len; j++)
11322 +       c[j] = 0;
11323 +
11324 +    for (i = len - 1; i >= 0; i--) {
11325 +       t = 0;
11326 +       for (j = len - 1; j >= 0; j--) {
11327 +           t += MUL_WORD(a[i], (BignumDblInt) b[j]);
11328 +           t += (BignumDblInt) c[i + j + 1];
11329 +           c[i + j + 1] = (BignumInt) t;
11330 +           t = t >> BIGNUM_INT_BITS;
11331 +       }
11332 +       c[i] = (BignumInt) t;
11333 +    }
11334 +}
11335 +
11336 +static void internal_add_shifted(BignumInt *number,
11337 +                                unsigned n, int shift)
11338 +{
11339 +    int word = 1 + (shift / BIGNUM_INT_BITS);
11340 +    int bshift = shift % BIGNUM_INT_BITS;
11341 +    BignumDblInt addend;
11342 +
11343 +    addend = (BignumDblInt)n << bshift;
11344 +
11345 +    while (addend) {
11346 +       addend += number[word];
11347 +       number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
11348 +       addend >>= BIGNUM_INT_BITS;
11349 +       word++;
11350 +    }
11351 +}
11352 +
11353 +/*
11354 + * Compute a = a % m.
11355 + * Input in first alen words of a and first mlen words of m.
11356 + * Output in first alen words of a
11357 + * (of which first alen-mlen words will be zero).
11358 + * The MSW of m MUST have its high bit set.
11359 + * Quotient is accumulated in the `quotient' array, which is a Bignum
11360 + * rather than the internal bigendian format. Quotient parts are shifted
11361 + * left by `qshift' before adding into quot.
11362 + */
11363 +static void internal_mod(BignumInt *a, int alen,
11364 +                        BignumInt *m, int mlen,
11365 +                        BignumInt *quot, int qshift)
11366 +{
11367 +    BignumInt m0, m1;
11368 +    unsigned int h;
11369 +    int i, k;
11370 +
11371 +    m0 = m[0];
11372 +    if (mlen > 1)
11373 +       m1 = m[1];
11374 +    else
11375 +       m1 = 0;
11376 +
11377 +    for (i = 0; i <= alen - mlen; i++) {
11378 +       BignumDblInt t;
11379 +       unsigned int q, r, c, ai1;
11380 +
11381 +       if (i == 0) {
11382 +           h = 0;
11383 +       } else {
11384 +           h = a[i - 1];
11385 +           a[i - 1] = 0;
11386 +       }
11387 +
11388 +       if (i == alen - 1)
11389 +           ai1 = 0;
11390 +       else
11391 +           ai1 = a[i + 1];
11392 +
11393 +       /* Find q = h:a[i] / m0 */
11394 +       if (h >= m0) {
11395 +           /*
11396 +            * Special case.
11397 +            *
11398 +            * To illustrate it, suppose a BignumInt is 8 bits, and
11399 +            * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
11400 +            * our initial division will be 0xA123 / 0xA1, which
11401 +            * will give a quotient of 0x100 and a divide overflow.
11402 +            * However, the invariants in this division algorithm
11403 +            * are not violated, since the full number A1:23:... is
11404 +            * _less_ than the quotient prefix A1:B2:... and so the
11405 +            * following correction loop would have sorted it out.
11406 +            *
11407 +            * In this situation we set q to be the largest
11408 +            * quotient we _can_ stomach (0xFF, of course).
11409 +            */
11410 +           q = BIGNUM_INT_MASK;
11411 +       } else {
11412 +           /* Macro doesn't want an array subscript expression passed
11413 +            * into it (see definition), so use a temporary. */
11414 +           BignumInt tmplo = a[i];
11415 +           DIVMOD_WORD(q, r, h, tmplo, m0);
11416 +
11417 +           /* Refine our estimate of q by looking at
11418 +            h:a[i]:a[i+1] / m0:m1 */
11419 +           t = MUL_WORD(m1, q);
11420 +           if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
11421 +               q--;
11422 +               t -= m1;
11423 +               r = (r + m0) & BIGNUM_INT_MASK;     /* overflow? */
11424 +               if (r >= (BignumDblInt) m0 &&
11425 +                   t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
11426 +           }
11427 +       }
11428 +
11429 +       /* Subtract q * m from a[i...] */
11430 +       c = 0;
11431 +       for (k = mlen - 1; k >= 0; k--) {
11432 +           t = MUL_WORD(q, m[k]);
11433 +           t += c;
11434 +           c = (unsigned)(t >> BIGNUM_INT_BITS);
11435 +           if ((BignumInt) t > a[i + k])
11436 +               c++;
11437 +           a[i + k] -= (BignumInt) t;
11438 +       }
11439 +
11440 +       /* Add back m in case of borrow */
11441 +       if (c != h) {
11442 +           t = 0;
11443 +           for (k = mlen - 1; k >= 0; k--) {
11444 +               t += m[k];
11445 +               t += a[i + k];
11446 +               a[i + k] = (BignumInt) t;
11447 +               t = t >> BIGNUM_INT_BITS;
11448 +           }
11449 +           q--;
11450 +       }
11451 +       if (quot)
11452 +           internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
11453 +    }
11454 +}
11455 +
11456 +/*
11457 + * Compute p % mod.
11458 + * The most significant word of mod MUST be non-zero.
11459 + * We assume that the result array is the same size as the mod array.
11460 + * We optionally write out a quotient if `quotient' is non-NULL.
11461 + * We can avoid writing out the result if `result' is NULL.
11462 + */
11463 +void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)
11464 +{
11465 +    BignumInt *n, *m;
11466 +    int mshift;
11467 +    int plen, mlen, i, j;
11468 +
11469 +    /* Allocate m of size mlen, copy mod to m */
11470 +    /* We use big endian internally */
11471 +    mlen = mod[0];
11472 +    m = snewn(mem_ctx, mlen, BignumInt);
11473 +    //if (!m)
11474 +    //abort();                /* FIXME */
11475 +    for (j = 0; j < mlen; j++)
11476 +       m[j] = mod[mod[0] - j];
11477 +
11478 +    /* Shift m left to make msb bit set */
11479 +    for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
11480 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11481 +           break;
11482 +    if (mshift) {
11483 +       for (i = 0; i < mlen - 1; i++)
11484 +           m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
11485 +       m[mlen - 1] = m[mlen - 1] << mshift;
11486 +    }
11487 +
11488 +    plen = p[0];
11489 +    /* Ensure plen > mlen */
11490 +    if (plen <= mlen)
11491 +       plen = mlen + 1;
11492 +
11493 +    /* Allocate n of size plen, copy p to n */
11494 +    n = snewn(mem_ctx, plen, BignumInt);
11495 +    //if (!n)
11496 +    //abort();                /* FIXME */
11497 +    for (j = 0; j < plen; j++)
11498 +       n[j] = 0;
11499 +    for (j = 1; j <= (int)p[0]; j++)
11500 +       n[plen - j] = p[j];
11501 +
11502 +    /* Main computation */
11503 +    internal_mod(n, plen, m, mlen, quotient, mshift);
11504 +
11505 +    /* Fixup result in case the modulus was shifted */
11506 +    if (mshift) {
11507 +       for (i = plen - mlen - 1; i < plen - 1; i++)
11508 +           n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
11509 +       n[plen - 1] = n[plen - 1] << mshift;
11510 +       internal_mod(n, plen, m, mlen, quotient, 0);
11511 +       for (i = plen - 1; i >= plen - mlen; i--)
11512 +           n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
11513 +    }
11514 +
11515 +    /* Copy result to buffer */
11516 +    if (result) {
11517 +       for (i = 1; i <= (int)result[0]; i++) {
11518 +           int j = plen - i;
11519 +           result[i] = j >= 0 ? n[j] : 0;
11520 +       }
11521 +    }
11522 +
11523 +    /* Free temporary arrays */
11524 +    for (i = 0; i < mlen; i++)
11525 +       m[i] = 0;
11526 +    sfree(mem_ctx, m);
11527 +    for (i = 0; i < plen; i++)
11528 +       n[i] = 0;
11529 +    sfree(mem_ctx, n);
11530 +}
11531 +
11532 +/*
11533 + * Simple remainder.
11534 + */
11535 +Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)
11536 +{
11537 +    Bignum r = newbn(mem_ctx, b[0]);
11538 +    bigdivmod(mem_ctx, a, b, r, NULL);
11539 +    return r;
11540 +}
11541 +
11542 +/*
11543 + * Compute (base ^ exp) % mod.
11544 + */
11545 +Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)
11546 +{
11547 +    BignumInt *a, *b, *n, *m;
11548 +    int mshift;
11549 +    int mlen, i, j;
11550 +    Bignum base, result;
11551 +
11552 +    /*
11553 +     * The most significant word of mod needs to be non-zero. It
11554 +     * should already be, but let's make sure.
11555 +     */
11556 +    //assert(mod[mod[0]] != 0);
11557 +
11558 +    /*
11559 +     * Make sure the base is smaller than the modulus, by reducing
11560 +     * it modulo the modulus if not.
11561 +     */
11562 +    base = bigmod(mem_ctx, base_in, mod);
11563 +
11564 +    /* Allocate m of size mlen, copy mod to m */
11565 +    /* We use big endian internally */
11566 +    mlen = mod[0];
11567 +    m = snewn(mem_ctx, mlen, BignumInt);
11568 +    //if (!m)
11569 +    //abort();                /* FIXME */
11570 +    for (j = 0; j < mlen; j++)
11571 +       m[j] = mod[mod[0] - j];
11572 +
11573 +    /* Shift m left to make msb bit set */
11574 +    for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
11575 +       if ((m[0] << mshift) & BIGNUM_TOP_BIT)
11576 +           break;
11577 +    if (mshift) {
11578 +       for (i = 0; i < mlen - 1; i++)
11579 +           m[i] =
11580 +               (m[i] << mshift) | (m[i + 1] >>
11581 +                                   (BIGNUM_INT_BITS - mshift));
11582 +       m[mlen - 1] = m[mlen - 1] << mshift;
11583 +    }
11584 +
11585 +    /* Allocate n of size mlen, copy base to n */
11586 +    n = snewn(mem_ctx, mlen, BignumInt);
11587 +    //if (!n)
11588 +    //abort();                /* FIXME */
11589 +    i = mlen - base[0];
11590 +    for (j = 0; j < i; j++)
11591 +       n[j] = 0;
11592 +    for (j = 0; j < base[0]; j++)
11593 +       n[i + j] = base[base[0] - j];
11594 +
11595 +    /* Allocate a and b of size 2*mlen. Set a = 1 */
11596 +    a = snewn(mem_ctx, 2 * mlen, BignumInt);
11597 +    //if (!a)
11598 +    //abort();                /* FIXME */
11599 +    b = snewn(mem_ctx, 2 * mlen, BignumInt);
11600 +    //if (!b)
11601 +    //abort();                /* FIXME */
11602 +    for (i = 0; i < 2 * mlen; i++)
11603 +       a[i] = 0;
11604 +    a[2 * mlen - 1] = 1;
11605 +
11606 +    /* Skip leading zero bits of exp. */
11607 +    i = 0;
11608 +    j = BIGNUM_INT_BITS - 1;
11609 +    while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
11610 +       j--;
11611 +       if (j < 0) {
11612 +           i++;
11613 +           j = BIGNUM_INT_BITS - 1;
11614 +       }
11615 +    }
11616 +
11617 +    /* Main computation */
11618 +    while (i < exp[0]) {
11619 +       while (j >= 0) {
11620 +           internal_mul(a + mlen, a + mlen, b, mlen);
11621 +           internal_mod(b, mlen * 2, m, mlen, NULL, 0);
11622 +           if ((exp[exp[0] - i] & (1 << j)) != 0) {
11623 +               internal_mul(b + mlen, n, a, mlen);
11624 +               internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11625 +           } else {
11626 +               BignumInt *t;
11627 +               t = a;
11628 +               a = b;
11629 +               b = t;
11630 +           }
11631 +           j--;
11632 +       }
11633 +       i++;
11634 +       j = BIGNUM_INT_BITS - 1;
11635 +    }
11636 +
11637 +    /* Fixup result in case the modulus was shifted */
11638 +    if (mshift) {
11639 +       for (i = mlen - 1; i < 2 * mlen - 1; i++)
11640 +           a[i] =
11641 +               (a[i] << mshift) | (a[i + 1] >>
11642 +                                   (BIGNUM_INT_BITS - mshift));
11643 +       a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
11644 +       internal_mod(a, mlen * 2, m, mlen, NULL, 0);
11645 +       for (i = 2 * mlen - 1; i >= mlen; i--)
11646 +           a[i] =
11647 +               (a[i] >> mshift) | (a[i - 1] <<
11648 +                                   (BIGNUM_INT_BITS - mshift));
11649 +    }
11650 +
11651 +    /* Copy result to buffer */
11652 +    result = newbn(mem_ctx, mod[0]);
11653 +    for (i = 0; i < mlen; i++)
11654 +       result[result[0] - i] = a[i + mlen];
11655 +    while (result[0] > 1 && result[result[0]] == 0)
11656 +       result[0]--;
11657 +
11658 +    /* Free temporary arrays */
11659 +    for (i = 0; i < 2 * mlen; i++)
11660 +       a[i] = 0;
11661 +    sfree(mem_ctx, a);
11662 +    for (i = 0; i < 2 * mlen; i++)
11663 +       b[i] = 0;
11664 +    sfree(mem_ctx, b);
11665 +    for (i = 0; i < mlen; i++)
11666 +       m[i] = 0;
11667 +    sfree(mem_ctx, m);
11668 +    for (i = 0; i < mlen; i++)
11669 +       n[i] = 0;
11670 +    sfree(mem_ctx, n);
11671 +
11672 +    freebn(mem_ctx, base);
11673 +
11674 +    return result;
11675 +}
11676 +
11677 +
11678 +#ifdef UNITTEST
11679 +
11680 +static __u32 dh_p[] = {
11681 +       96,
11682 +       0xFFFFFFFF,
11683 +       0xFFFFFFFF,
11684 +       0xA93AD2CA,
11685 +       0x4B82D120,
11686 +       0xE0FD108E,
11687 +       0x43DB5BFC,
11688 +       0x74E5AB31,
11689 +       0x08E24FA0,
11690 +       0xBAD946E2,
11691 +       0x770988C0,
11692 +       0x7A615D6C,
11693 +       0xBBE11757,
11694 +       0x177B200C,
11695 +       0x521F2B18,
11696 +       0x3EC86A64,
11697 +       0xD8760273,
11698 +       0xD98A0864,
11699 +       0xF12FFA06,
11700 +       0x1AD2EE6B,
11701 +       0xCEE3D226,
11702 +       0x4A25619D,
11703 +       0x1E8C94E0,
11704 +       0xDB0933D7,
11705 +       0xABF5AE8C,
11706 +       0xA6E1E4C7,
11707 +       0xB3970F85,
11708 +       0x5D060C7D,
11709 +       0x8AEA7157,
11710 +       0x58DBEF0A,
11711 +       0xECFB8504,
11712 +       0xDF1CBA64,
11713 +       0xA85521AB,
11714 +       0x04507A33,
11715 +       0xAD33170D,
11716 +       0x8AAAC42D,
11717 +       0x15728E5A,
11718 +       0x98FA0510,
11719 +       0x15D22618,
11720 +       0xEA956AE5,
11721 +       0x3995497C,
11722 +       0x95581718,
11723 +       0xDE2BCBF6,
11724 +       0x6F4C52C9,
11725 +       0xB5C55DF0,
11726 +       0xEC07A28F,
11727 +       0x9B2783A2,
11728 +       0x180E8603,
11729 +       0xE39E772C,
11730 +       0x2E36CE3B,
11731 +       0x32905E46,
11732 +       0xCA18217C,
11733 +       0xF1746C08,
11734 +       0x4ABC9804,
11735 +       0x670C354E,
11736 +       0x7096966D,
11737 +       0x9ED52907,
11738 +       0x208552BB,
11739 +       0x1C62F356,
11740 +       0xDCA3AD96,
11741 +       0x83655D23,
11742 +       0xFD24CF5F,
11743 +       0x69163FA8,
11744 +       0x1C55D39A,
11745 +       0x98DA4836,
11746 +       0xA163BF05,
11747 +       0xC2007CB8,
11748 +       0xECE45B3D,
11749 +       0x49286651,
11750 +       0x7C4B1FE6,
11751 +       0xAE9F2411,
11752 +       0x5A899FA5,
11753 +       0xEE386BFB,
11754 +       0xF406B7ED,
11755 +       0x0BFF5CB6,
11756 +       0xA637ED6B,
11757 +       0xF44C42E9,
11758 +       0x625E7EC6,
11759 +       0xE485B576,
11760 +       0x6D51C245,
11761 +       0x4FE1356D,
11762 +       0xF25F1437,
11763 +       0x302B0A6D,
11764 +       0xCD3A431B,
11765 +       0xEF9519B3,
11766 +       0x8E3404DD,
11767 +       0x514A0879,
11768 +       0x3B139B22,
11769 +       0x020BBEA6,
11770 +       0x8A67CC74,
11771 +       0x29024E08,
11772 +       0x80DC1CD1,
11773 +       0xC4C6628B,
11774 +       0x2168C234,
11775 +       0xC90FDAA2,
11776 +       0xFFFFFFFF,
11777 +       0xFFFFFFFF,
11778 +};
11779 +
11780 +static __u32 dh_a[] = {
11781 +       8,
11782 +       0xdf367516,
11783 +       0x86459caa,
11784 +       0xe2d459a4,
11785 +       0xd910dae0,
11786 +       0x8a8b5e37,
11787 +       0x67ab31c6,
11788 +       0xf0b55ea9,
11789 +       0x440051d6,
11790 +};
11791 +
11792 +static __u32 dh_b[] = {
11793 +       8,
11794 +       0xded92656,
11795 +       0xe07a048a,
11796 +       0x6fa452cd,
11797 +       0x2df89d30,
11798 +       0xc75f1b0f,
11799 +       0x8ce3578f,
11800 +       0x7980a324,
11801 +       0x5daec786,
11802 +};
11803 +
11804 +static __u32 dh_g[] = {
11805 +       1,
11806 +       2,
11807 +};
11808 +
11809 +int main(void)
11810 +{
11811 +       int i;
11812 +       __u32 *k;
11813 +       k = dwc_modpow(NULL, dh_g, dh_a, dh_p);
11814 +
11815 +       printf("\n\n");
11816 +       for (i=0; i<k[0]; i++) {
11817 +               __u32 word32 = k[k[0] - i];
11818 +               __u16 l = word32 & 0xffff;
11819 +               __u16 m = (word32 & 0xffff0000) >> 16;
11820 +               printf("%04x %04x ", m, l);
11821 +               if (!((i + 1)%13)) printf("\n");
11822 +       }
11823 +       printf("\n\n");
11824 +
11825 +       if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
11826 +               printf("PASS\n\n");
11827 +       }
11828 +       else {
11829 +               printf("FAIL\n\n");
11830 +       }
11831 +
11832 +}
11833 +
11834 +#endif /* UNITTEST */
11835 +
11836 +#endif /* CONFIG_MACH_IPMATE */
11837 +
11838 +#endif /*DWC_CRYPTOLIB */
11839 --- /dev/null
11840 +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
11841 @@ -0,0 +1,34 @@
11842 +/*
11843 + * dwc_modpow.h
11844 + * See dwc_modpow.c for license and changes
11845 + */
11846 +#ifndef _DWC_MODPOW_H
11847 +#define _DWC_MODPOW_H
11848 +
11849 +#ifdef __cplusplus
11850 +extern "C" {
11851 +#endif
11852 +
11853 +#include "dwc_os.h"
11854 +
11855 +/** @file
11856 + *
11857 + * This file defines the module exponentiation function which is only used
11858 + * internally by the DWC UWB modules for calculation of PKs during numeric
11859 + * association.  The routine is taken from the PUTTY, an open source terminal
11860 + * emulator.  The PUTTY License is preserved in the dwc_modpow.c file.
11861 + *
11862 + */
11863 +
11864 +typedef uint32_t BignumInt;
11865 +typedef uint64_t BignumDblInt;
11866 +typedef BignumInt *Bignum;
11867 +
11868 +/* Compute modular exponentiaion */
11869 +extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);
11870 +
11871 +#ifdef __cplusplus
11872 +}
11873 +#endif
11874 +
11875 +#endif /* _LINUX_BIGNUM_H */
11876 --- /dev/null
11877 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
11878 @@ -0,0 +1,319 @@
11879 +#ifdef DWC_NOTIFYLIB
11880 +
11881 +#include "dwc_notifier.h"
11882 +#include "dwc_list.h"
11883 +
11884 +typedef struct dwc_observer {
11885 +       void *observer;
11886 +       dwc_notifier_callback_t callback;
11887 +       void *data;
11888 +       char *notification;
11889 +       DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
11890 +} observer_t;
11891 +
11892 +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
11893 +
11894 +typedef struct dwc_notifier {
11895 +       void *mem_ctx;
11896 +       void *object;
11897 +       struct observer_queue observers;
11898 +       DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
11899 +} notifier_t;
11900 +
11901 +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
11902 +
11903 +typedef struct manager {
11904 +       void *mem_ctx;
11905 +       void *wkq_ctx;
11906 +       dwc_workq_t *wq;
11907 +//     dwc_mutex_t *mutex;
11908 +       struct notifier_queue notifiers;
11909 +} manager_t;
11910 +
11911 +static manager_t *manager = NULL;
11912 +
11913 +static int create_manager(void *mem_ctx, void *wkq_ctx)
11914 +{
11915 +       manager = dwc_alloc(mem_ctx, sizeof(manager_t));
11916 +       if (!manager) {
11917 +               return -DWC_E_NO_MEMORY;
11918 +       }
11919 +
11920 +       DWC_CIRCLEQ_INIT(&manager->notifiers);
11921 +
11922 +       manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");
11923 +       if (!manager->wq) {
11924 +               return -DWC_E_NO_MEMORY;
11925 +       }
11926 +
11927 +       return 0;
11928 +}
11929 +
11930 +static void free_manager(void)
11931 +{
11932 +       dwc_workq_free(manager->wq);
11933 +
11934 +       /* All notifiers must have unregistered themselves before this module
11935 +        * can be removed.  Hitting this assertion indicates a programmer
11936 +        * error. */
11937 +       DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),
11938 +                  "Notification manager being freed before all notifiers have been removed");
11939 +       dwc_free(manager->mem_ctx, manager);
11940 +}
11941 +
11942 +#ifdef DEBUG
11943 +static void dump_manager(void)
11944 +{
11945 +       notifier_t *n;
11946 +       observer_t *o;
11947 +
11948 +       DWC_ASSERT(manager, "Notification manager not found");
11949 +
11950 +       DWC_DEBUG("List of all notifiers and observers:\n");
11951 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
11952 +               DWC_DEBUG("Notifier %p has observers:\n", n->object);
11953 +               DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
11954 +                       DWC_DEBUG("    %p watching %s\n", o->observer, o->notification);
11955 +               }
11956 +       }
11957 +}
11958 +#else
11959 +#define dump_manager(...)
11960 +#endif
11961 +
11962 +static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,
11963 +                                 dwc_notifier_callback_t callback, void *data)
11964 +{
11965 +       observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));
11966 +
11967 +       if (!new_observer) {
11968 +               return NULL;
11969 +       }
11970 +
11971 +       DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
11972 +       new_observer->observer = observer;
11973 +       new_observer->notification = notification;
11974 +       new_observer->callback = callback;
11975 +       new_observer->data = data;
11976 +       return new_observer;
11977 +}
11978 +
11979 +static void free_observer(void *mem_ctx, observer_t *observer)
11980 +{
11981 +       dwc_free(mem_ctx, observer);
11982 +}
11983 +
11984 +static notifier_t *alloc_notifier(void *mem_ctx, void *object)
11985 +{
11986 +       notifier_t *notifier;
11987 +
11988 +       if (!object) {
11989 +               return NULL;
11990 +       }
11991 +
11992 +       notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));
11993 +       if (!notifier) {
11994 +               return NULL;
11995 +       }
11996 +
11997 +       DWC_CIRCLEQ_INIT(&notifier->observers);
11998 +       DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
11999 +
12000 +       notifier->mem_ctx = mem_ctx;
12001 +       notifier->object = object;
12002 +       return notifier;
12003 +}
12004 +
12005 +static void free_notifier(notifier_t *notifier)
12006 +{
12007 +       observer_t *observer;
12008 +
12009 +       DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
12010 +               free_observer(notifier->mem_ctx, observer);
12011 +       }
12012 +
12013 +       dwc_free(notifier->mem_ctx, notifier);
12014 +}
12015 +
12016 +static notifier_t *find_notifier(void *object)
12017 +{
12018 +       notifier_t *notifier;
12019 +
12020 +       DWC_ASSERT(manager, "Notification manager not found");
12021 +
12022 +       if (!object) {
12023 +               return NULL;
12024 +       }
12025 +
12026 +       DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
12027 +               if (notifier->object == object) {
12028 +                       return notifier;
12029 +               }
12030 +       }
12031 +
12032 +       return NULL;
12033 +}
12034 +
12035 +int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)
12036 +{
12037 +       return create_manager(mem_ctx, wkq_ctx);
12038 +}
12039 +
12040 +void dwc_free_notification_manager(void)
12041 +{
12042 +       free_manager();
12043 +}
12044 +
12045 +dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)
12046 +{
12047 +       notifier_t *notifier;
12048 +
12049 +       DWC_ASSERT(manager, "Notification manager not found");
12050 +
12051 +       notifier = find_notifier(object);
12052 +       if (notifier) {
12053 +               DWC_ERROR("Notifier %p is already registered\n", object);
12054 +               return NULL;
12055 +       }
12056 +
12057 +       notifier = alloc_notifier(mem_ctx, object);
12058 +       if (!notifier) {
12059 +               return NULL;
12060 +       }
12061 +
12062 +       DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
12063 +
12064 +       DWC_INFO("Notifier %p registered", object);
12065 +       dump_manager();
12066 +
12067 +       return notifier;
12068 +}
12069 +
12070 +void dwc_unregister_notifier(dwc_notifier_t *notifier)
12071 +{
12072 +       DWC_ASSERT(manager, "Notification manager not found");
12073 +
12074 +       if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
12075 +               observer_t *o;
12076 +
12077 +               DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);
12078 +               DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12079 +                       DWC_DEBUGC("    %p watching %s\n", o->observer, o->notification);
12080 +               }
12081 +
12082 +               DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers),
12083 +                          "Notifier %p has active observers when removing", notifier);
12084 +       }
12085 +
12086 +       DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
12087 +       free_notifier(notifier);
12088 +
12089 +       DWC_INFO("Notifier unregistered");
12090 +       dump_manager();
12091 +}
12092 +
12093 +/* Add an observer to observe the notifier for a particular state, event, or notification. */
12094 +int dwc_add_observer(void *observer, void *object, char *notification,
12095 +                    dwc_notifier_callback_t callback, void *data)
12096 +{
12097 +       notifier_t *notifier = find_notifier(object);
12098 +       observer_t *new_observer;
12099 +
12100 +       if (!notifier) {
12101 +               DWC_ERROR("Notifier %p is not found when adding observer\n", object);
12102 +               return -DWC_E_INVALID;
12103 +       }
12104 +
12105 +       new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);
12106 +       if (!new_observer) {
12107 +               return -DWC_E_NO_MEMORY;
12108 +       }
12109 +
12110 +       DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
12111 +
12112 +       DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
12113 +                observer, object, notification, callback, data);
12114 +
12115 +       dump_manager();
12116 +       return 0;
12117 +}
12118 +
12119 +int dwc_remove_observer(void *observer)
12120 +{
12121 +       notifier_t *n;
12122 +
12123 +       DWC_ASSERT(manager, "Notification manager not found");
12124 +
12125 +       DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
12126 +               observer_t *o;
12127 +               observer_t *o2;
12128 +
12129 +               DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
12130 +                       if (o->observer == observer) {
12131 +                               DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
12132 +                               DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
12133 +                                        o->observer, n->object, o->notification);
12134 +                               free_observer(n->mem_ctx, o);
12135 +                       }
12136 +               }
12137 +       }
12138 +
12139 +       dump_manager();
12140 +       return 0;
12141 +}
12142 +
12143 +typedef struct callback_data {
12144 +       void *mem_ctx;
12145 +       dwc_notifier_callback_t cb;
12146 +       void *observer;
12147 +       void *data;
12148 +       void *object;
12149 +       char *notification;
12150 +       void *notification_data;
12151 +} cb_data_t;
12152 +
12153 +static void cb_task(void *data)
12154 +{
12155 +       cb_data_t *cb = (cb_data_t *)data;
12156 +
12157 +       cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
12158 +       dwc_free(cb->mem_ctx, cb);
12159 +}
12160 +
12161 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
12162 +{
12163 +       observer_t *o;
12164 +
12165 +       DWC_ASSERT(manager, "Notification manager not found");
12166 +
12167 +       DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
12168 +               int len = DWC_STRLEN(notification);
12169 +
12170 +               if (DWC_STRLEN(o->notification) != len) {
12171 +                       continue;
12172 +               }
12173 +
12174 +               if (DWC_STRNCMP(o->notification, notification, len) == 0) {
12175 +                       cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));
12176 +
12177 +                       if (!cb_data) {
12178 +                               DWC_ERROR("Failed to allocate callback data\n");
12179 +                               return;
12180 +                       }
12181 +
12182 +                       cb_data->mem_ctx = notifier->mem_ctx;
12183 +                       cb_data->cb = o->callback;
12184 +                       cb_data->observer = o->observer;
12185 +                       cb_data->data = o->data;
12186 +                       cb_data->object = notifier->object;
12187 +                       cb_data->notification = notification;
12188 +                       cb_data->notification_data = notification_data;
12189 +                       DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);
12190 +                       DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
12191 +                                          "Notify callback from %p for Notification %s, to observer %p",
12192 +                                          cb_data->object, notification, cb_data->observer);
12193 +               }
12194 +       }
12195 +}
12196 +
12197 +#endif /* DWC_NOTIFYLIB */
12198 --- /dev/null
12199 +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
12200 @@ -0,0 +1,122 @@
12201 +
12202 +#ifndef __DWC_NOTIFIER_H__
12203 +#define __DWC_NOTIFIER_H__
12204 +
12205 +#ifdef __cplusplus
12206 +extern "C" {
12207 +#endif
12208 +
12209 +#include "dwc_os.h"
12210 +
12211 +/** @file
12212 + *
12213 + * A simple implementation of the Observer pattern.  Any "module" can
12214 + * register as an observer or notifier.  The notion of "module" is abstract and
12215 + * can mean anything used to identify either an observer or notifier.  Usually
12216 + * it will be a pointer to a data structure which contains some state, ie an
12217 + * object.
12218 + *
12219 + * Before any notifiers can be added, the global notification manager must be
12220 + * brought up with dwc_alloc_notification_manager().
12221 + * dwc_free_notification_manager() will bring it down and free all resources.
12222 + * These would typically be called upon module load and unload.  The
12223 + * notification manager is a single global instance that handles all registered
12224 + * observable modules and observers so this should be done only once.
12225 + *
12226 + * A module can be observable by using Notifications to publicize some general
12227 + * information about it's state or operation.  It does not care who listens, or
12228 + * even if anyone listens, or what they do with the information.  The observable
12229 + * modules do not need to know any information about it's observers or their
12230 + * interface, or their state or data.
12231 + *
12232 + * Any module can register to emit Notifications.  It should publish a list of
12233 + * notifications that it can emit and their behavior, such as when they will get
12234 + * triggered, and what information will be provided to the observer.  Then it
12235 + * should register itself as an observable module. See dwc_register_notifier().
12236 + *
12237 + * Any module can observe any observable, registered module, provided it has a
12238 + * handle to the other module and knows what notifications to observe.  See
12239 + * dwc_add_observer().
12240 + *
12241 + * A function of type dwc_notifier_callback_t is called whenever a notification
12242 + * is triggered with one or more observers observing it.  This function is
12243 + * called in it's own process so it may sleep or block if needed.  It is
12244 + * guaranteed to be called sometime after the notification has occurred and will
12245 + * be called once per each time the notification is triggered.  It will NOT be
12246 + * called in the same process context used to trigger the notification.
12247 + *
12248 + * @section Limitiations
12249 + *
12250 + * Keep in mind that Notifications that can be triggered in rapid sucession may
12251 + * schedule too many processes too handle.  Be aware of this limitation when
12252 + * designing to use notifications, and only add notifications for appropriate
12253 + * observable information.
12254 + *
12255 + * Also Notification callbacks are not synchronous.  If you need to synchronize
12256 + * the behavior between module/observer you must use other means.  And perhaps
12257 + * that will mean Notifications are not the proper solution.
12258 + */
12259 +
12260 +struct dwc_notifier;
12261 +typedef struct dwc_notifier dwc_notifier_t;
12262 +
12263 +/** The callback function must be of this type.
12264 + *
12265 + * @param object This is the object that is being observed.
12266 + * @param notification This is the notification that was triggered.
12267 + * @param observer This is the observer
12268 + * @param notification_data This is notification-specific data that the notifier
12269 + * has included in this notification.  The value of this should be published in
12270 + * the documentation of the observable module with the notifications.
12271 + * @param user_data This is any custom data that the observer provided when
12272 + * adding itself as an observer to the notification. */
12273 +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
12274 +                                       void *notification_data, void *user_data);
12275 +
12276 +/** Brings up the notification manager. */
12277 +extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
12278 +/** Brings down the notification manager. */
12279 +extern void dwc_free_notification_manager(void);
12280 +
12281 +/** This function registers an observable module.  A dwc_notifier_t object is
12282 + * returned to the observable module.  This is an opaque object that is used by
12283 + * the observable module to trigger notifications.  This object should only be
12284 + * accessible to functions that are authorized to trigger notifications for this
12285 + * module.  Observers do not need this object. */
12286 +extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
12287 +
12288 +/** This function unregisters an observable module.  All observers have to be
12289 + * removed prior to unregistration. */
12290 +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
12291 +
12292 +/** Add a module as an observer to the observable module.  The observable module
12293 + * needs to have previously registered with the notification manager.
12294 + *
12295 + * @param observer The observer module
12296 + * @param object The module to observe
12297 + * @param notification The notification to observe
12298 + * @param callback The callback function to call
12299 + * @param user_data Any additional user data to pass into the callback function */
12300 +extern int dwc_add_observer(void *observer, void *object, char *notification,
12301 +                           dwc_notifier_callback_t callback, void *user_data);
12302 +
12303 +/** Removes the specified observer from all notifications that it is currently
12304 + * observing. */
12305 +extern int dwc_remove_observer(void *observer);
12306 +
12307 +/** This function triggers a Notification.  It should be called by the
12308 + * observable module, or any module or library which the observable module
12309 + * allows to trigger notification on it's behalf.  Such as the dwc_cc_t.
12310 + *
12311 + * dwc_notify is a non-blocking function.  Callbacks are scheduled called in
12312 + * their own process context for each trigger.  Callbacks can be blocking.
12313 + * dwc_notify can be called from interrupt context if needed.
12314 + *
12315 + */
12316 +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
12317 +
12318 +#ifdef __cplusplus
12319 +}
12320 +#endif
12321 +
12322 +#endif /* __DWC_NOTIFIER_H__ */
12323 --- /dev/null
12324 +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
12325 @@ -0,0 +1,1260 @@
12326 +/* =========================================================================
12327 + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
12328 + * $Revision: #14 $
12329 + * $Date: 2010/11/04 $
12330 + * $Change: 1621695 $
12331 + *
12332 + * Synopsys Portability Library Software and documentation
12333 + * (hereinafter, "Software") is an Unsupported proprietary work of
12334 + * Synopsys, Inc. unless otherwise expressly agreed to in writing
12335 + * between Synopsys and you.
12336 + *
12337 + * The Software IS NOT an item of Licensed Software or Licensed Product
12338 + * under any End User Software License Agreement or Agreement for
12339 + * Licensed Product with Synopsys or any supplement thereto. You are
12340 + * permitted to use and redistribute this Software in source and binary
12341 + * forms, with or without modification, provided that redistributions
12342 + * of source code must retain this notice. You may not view, use,
12343 + * disclose, copy or distribute this file or any information contained
12344 + * herein except pursuant to this license grant from Synopsys. If you
12345 + * do not agree with this notice, including the disclaimer below, then
12346 + * you are not authorized to use the Software.
12347 + *
12348 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
12349 + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
12350 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12351 + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
12352 + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
12353 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
12354 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
12355 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
12356 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12357 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
12358 + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
12359 + * DAMAGE.
12360 + * ========================================================================= */
12361 +#ifndef _DWC_OS_H_
12362 +#define _DWC_OS_H_
12363 +
12364 +#ifdef __cplusplus
12365 +extern "C" {
12366 +#endif
12367 +
12368 +/** @file
12369 + *
12370 + * DWC portability library, low level os-wrapper functions
12371 + *
12372 + */
12373 +
12374 +/* These basic types need to be defined by some OS header file or custom header
12375 + * file for your specific target architecture.
12376 + *
12377 + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
12378 + *
12379 + * Any custom or alternate header file must be added and enabled here.
12380 + */
12381 +
12382 +#ifdef DWC_LINUX
12383 +# include <linux/types.h>
12384 +# ifdef CONFIG_DEBUG_MUTEXES
12385 +#  include <linux/mutex.h>
12386 +# endif
12387 +# include <linux/errno.h>
12388 +# include <stdarg.h>
12389 +#endif
12390 +
12391 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12392 +# include <os_dep.h>
12393 +#endif
12394 +
12395 +
12396 +/** @name Primitive Types and Values */
12397 +
12398 +/** We define a boolean type for consistency.  Can be either YES or NO */
12399 +typedef uint8_t dwc_bool_t;
12400 +#define YES  1
12401 +#define NO   0
12402 +
12403 +#ifdef DWC_LINUX
12404 +
12405 +/** @name Error Codes */
12406 +#define DWC_E_INVALID          EINVAL
12407 +#define DWC_E_NO_MEMORY                ENOMEM
12408 +#define DWC_E_NO_DEVICE                ENODEV
12409 +#define DWC_E_NOT_SUPPORTED    EOPNOTSUPP
12410 +#define DWC_E_TIMEOUT          ETIMEDOUT
12411 +#define DWC_E_BUSY             EBUSY
12412 +#define DWC_E_AGAIN            EAGAIN
12413 +#define DWC_E_RESTART          ERESTART
12414 +#define DWC_E_ABORT            ECONNABORTED
12415 +#define DWC_E_SHUTDOWN         ESHUTDOWN
12416 +#define DWC_E_NO_DATA          ENODATA
12417 +#define DWC_E_DISCONNECT       ECONNRESET
12418 +#define DWC_E_UNKNOWN          EINVAL
12419 +#define DWC_E_NO_STREAM_RES    ENOSR
12420 +#define DWC_E_COMMUNICATION    ECOMM
12421 +#define DWC_E_OVERFLOW         EOVERFLOW
12422 +#define DWC_E_PROTOCOL         EPROTO
12423 +#define DWC_E_IN_PROGRESS      EINPROGRESS
12424 +#define DWC_E_PIPE             EPIPE
12425 +#define DWC_E_IO               EIO
12426 +#define DWC_E_NO_SPACE         ENOSPC
12427 +
12428 +#else
12429 +
12430 +/** @name Error Codes */
12431 +#define DWC_E_INVALID          1001
12432 +#define DWC_E_NO_MEMORY                1002
12433 +#define DWC_E_NO_DEVICE                1003
12434 +#define DWC_E_NOT_SUPPORTED    1004
12435 +#define DWC_E_TIMEOUT          1005
12436 +#define DWC_E_BUSY             1006
12437 +#define DWC_E_AGAIN            1007
12438 +#define DWC_E_RESTART          1008
12439 +#define DWC_E_ABORT            1009
12440 +#define DWC_E_SHUTDOWN         1010
12441 +#define DWC_E_NO_DATA          1011
12442 +#define DWC_E_DISCONNECT       2000
12443 +#define DWC_E_UNKNOWN          3000
12444 +#define DWC_E_NO_STREAM_RES    4001
12445 +#define DWC_E_COMMUNICATION    4002
12446 +#define DWC_E_OVERFLOW         4003
12447 +#define DWC_E_PROTOCOL         4004
12448 +#define DWC_E_IN_PROGRESS      4005
12449 +#define DWC_E_PIPE             4006
12450 +#define DWC_E_IO               4007
12451 +#define DWC_E_NO_SPACE         4008
12452 +
12453 +#endif
12454 +
12455 +
12456 +/** @name Tracing/Logging Functions
12457 + *
12458 + * These function provide the capability to add tracing, debugging, and error
12459 + * messages, as well exceptions as assertions.  The WUDEV uses these
12460 + * extensively.  These could be logged to the main console, the serial port, an
12461 + * internal buffer, etc.  These functions could also be no-op if they are too
12462 + * expensive on your system.  By default undefining the DEBUG macro already
12463 + * no-ops some of these functions. */
12464 +
12465 +/** Returns non-zero if in interrupt context. */
12466 +extern dwc_bool_t DWC_IN_IRQ(void);
12467 +#define dwc_in_irq DWC_IN_IRQ
12468 +
12469 +/** Returns "IRQ" if DWC_IN_IRQ is true. */
12470 +static inline char *dwc_irq(void) {
12471 +       return DWC_IN_IRQ() ? "IRQ" : "";
12472 +}
12473 +
12474 +/** Returns non-zero if in bottom-half context. */
12475 +extern dwc_bool_t DWC_IN_BH(void);
12476 +#define dwc_in_bh DWC_IN_BH
12477 +
12478 +/** Returns "BH" if DWC_IN_BH is true. */
12479 +static inline char *dwc_bh(void) {
12480 +       return DWC_IN_BH() ? "BH" : "";
12481 +}
12482 +
12483 +/**
12484 + * A vprintf() clone.  Just call vprintf if you've got it.
12485 + */
12486 +extern void DWC_VPRINTF(char *format, va_list args);
12487 +#define dwc_vprintf DWC_VPRINTF
12488 +
12489 +/**
12490 + * A vsnprintf() clone.  Just call vprintf if you've got it.
12491 + */
12492 +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
12493 +#define dwc_vsnprintf DWC_VSNPRINTF
12494 +
12495 +/**
12496 + * printf() clone.  Just call printf if you've go it.
12497 + */
12498 +extern void DWC_PRINTF(char *format, ...)
12499 +/* This provides compiler level static checking of the parameters if you're
12500 + * using GCC. */
12501 +#ifdef __GNUC__
12502 +       __attribute__ ((format(printf, 1, 2)));
12503 +#else
12504 +       ;
12505 +#endif
12506 +#define dwc_printf DWC_PRINTF
12507 +
12508 +/**
12509 + * sprintf() clone.  Just call sprintf if you've got it.
12510 + */
12511 +extern int DWC_SPRINTF(char *string, char *format, ...)
12512 +#ifdef __GNUC__
12513 +       __attribute__ ((format(printf, 2, 3)));
12514 +#else
12515 +       ;
12516 +#endif
12517 +#define dwc_sprintf DWC_SPRINTF
12518 +
12519 +/**
12520 + * snprintf() clone.  Just call snprintf if you've got it.
12521 + */
12522 +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
12523 +#ifdef __GNUC__
12524 +       __attribute__ ((format(printf, 3, 4)));
12525 +#else
12526 +       ;
12527 +#endif
12528 +#define dwc_snprintf DWC_SNPRINTF
12529 +
12530 +/**
12531 + * Prints a WARNING message.  On systems that don't differentiate between
12532 + * warnings and regular log messages, just print it.  Indicates that something
12533 + * may be wrong with the driver.  Works like printf().
12534 + *
12535 + * Use the DWC_WARN macro to call this function.
12536 + */
12537 +extern void __DWC_WARN(char *format, ...)
12538 +#ifdef __GNUC__
12539 +       __attribute__ ((format(printf, 1, 2)));
12540 +#else
12541 +       ;
12542 +#endif
12543 +
12544 +/**
12545 + * Prints an error message.  On systems that don't differentiate between errors
12546 + * and regular log messages, just print it.  Indicates that something went wrong
12547 + * with the driver.  Works like printf().
12548 + *
12549 + * Use the DWC_ERROR macro to call this function.
12550 + */
12551 +extern void __DWC_ERROR(char *format, ...)
12552 +#ifdef __GNUC__
12553 +       __attribute__ ((format(printf, 1, 2)));
12554 +#else
12555 +       ;
12556 +#endif
12557 +
12558 +/**
12559 + * Prints an exception error message and takes some user-defined action such as
12560 + * print out a backtrace or trigger a breakpoint.  Indicates that something went
12561 + * abnormally wrong with the driver such as programmer error, or other
12562 + * exceptional condition.  It should not be ignored so even on systems without
12563 + * printing capability, some action should be taken to notify the developer of
12564 + * it.  Works like printf().
12565 + */
12566 +extern void DWC_EXCEPTION(char *format, ...)
12567 +#ifdef __GNUC__
12568 +       __attribute__ ((format(printf, 1, 2)));
12569 +#else
12570 +       ;
12571 +#endif
12572 +#define dwc_exception DWC_EXCEPTION
12573 +
12574 +#ifndef DWC_OTG_DEBUG_LEV
12575 +#define DWC_OTG_DEBUG_LEV 0
12576 +#endif
12577 +
12578 +#ifdef DEBUG
12579 +/**
12580 + * Prints out a debug message.  Used for logging/trace messages.
12581 + *
12582 + * Use the DWC_DEBUG macro to call this function
12583 + */
12584 +extern void __DWC_DEBUG(char *format, ...)
12585 +#ifdef __GNUC__
12586 +       __attribute__ ((format(printf, 1, 2)));
12587 +#else
12588 +       ;
12589 +#endif
12590 +#else
12591 +#define __DWC_DEBUG printk
12592 +#endif
12593 +
12594 +/**
12595 + * Prints out a Debug message.
12596 + */
12597 +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
12598 +                                                __func__, dwc_irq(), ## _args)
12599 +#define dwc_debug DWC_DEBUG
12600 +/**
12601 + * Prints out a Debug message if enabled at compile time.
12602 + */
12603 +#if DWC_OTG_DEBUG_LEV > 0
12604 +#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
12605 +#else
12606 +#define DWC_DEBUGC(_format, _args...)
12607 +#endif
12608 +#define dwc_debugc DWC_DEBUGC
12609 +/**
12610 + * Prints out an informative message.
12611 + */
12612 +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
12613 +                                              dwc_irq(), ## _args)
12614 +#define dwc_info DWC_INFO
12615 +/**
12616 + * Prints out an informative message if enabled at compile time.
12617 + */
12618 +#if DWC_OTG_DEBUG_LEV > 1
12619 +#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
12620 +#else
12621 +#define DWC_INFOC(_format, _args...)
12622 +#endif
12623 +#define dwc_infoc DWC_INFOC
12624 +/**
12625 + * Prints out a warning message.
12626 + */
12627 +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
12628 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12629 +#define dwc_warn DWC_WARN
12630 +/**
12631 + * Prints out an error message.
12632 + */
12633 +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
12634 +                                       dwc_irq(), __func__, __LINE__, ## _args)
12635 +#define dwc_error DWC_ERROR
12636 +
12637 +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
12638 +                                               dwc_irq(), __func__, __LINE__, ## _args)
12639 +#define dwc_proto_error DWC_PROTO_ERROR
12640 +
12641 +#ifdef DEBUG
12642 +/** Prints out a exception error message if the _expr expression fails.  Disabled
12643 + * if DEBUG is not enabled. */
12644 +#define DWC_ASSERT(_expr, _format, _args...) do { \
12645 +       if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
12646 +                                     __FILE__, __LINE__, ## _args); } \
12647 +       } while (0)
12648 +#else
12649 +#define DWC_ASSERT(_x...)
12650 +#endif
12651 +#define dwc_assert DWC_ASSERT
12652 +
12653 +
12654 +/** @name Byte Ordering
12655 + * The following functions are for conversions between processor's byte ordering
12656 + * and specific ordering you want.
12657 + */
12658 +
12659 +/** Converts 32 bit data in CPU byte ordering to little endian. */
12660 +extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
12661 +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
12662 +
12663 +/** Converts 32 bit data in CPU byte orderint to big endian. */
12664 +extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
12665 +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
12666 +
12667 +/** Converts 32 bit little endian data to CPU byte ordering. */
12668 +extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
12669 +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
12670 +
12671 +/** Converts 32 bit big endian data to CPU byte ordering. */
12672 +extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
12673 +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
12674 +
12675 +/** Converts 16 bit data in CPU byte ordering to little endian. */
12676 +extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
12677 +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
12678 +
12679 +/** Converts 16 bit data in CPU byte orderint to big endian. */
12680 +extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
12681 +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
12682 +
12683 +/** Converts 16 bit little endian data to CPU byte ordering. */
12684 +extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
12685 +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
12686 +
12687 +/** Converts 16 bit bi endian data to CPU byte ordering. */
12688 +extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
12689 +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
12690 +
12691 +
12692 +/** @name Register Read/Write
12693 + *
12694 + * The following six functions should be implemented to read/write registers of
12695 + * 32-bit and 64-bit sizes.  All modules use this to read/write register values.
12696 + * The reg value is a pointer to the register calculated from the void *base
12697 + * variable passed into the driver when it is started.  */
12698 +
12699 +#ifdef DWC_LINUX
12700 +/* Linux doesn't need any extra parameters for register read/write, so we
12701 + * just throw away the IO context parameter.
12702 + */
12703 +/** Reads the content of a 32-bit register. */
12704 +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
12705 +#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
12706 +
12707 +/** Reads the content of a 64-bit register. */
12708 +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
12709 +#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
12710 +
12711 +/** Writes to a 32-bit register. */
12712 +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
12713 +#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
12714 +
12715 +/** Writes to a 64-bit register. */
12716 +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
12717 +#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
12718 +
12719 +/**
12720 + * Modify bit values in a register.  Using the
12721 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12722 + */
12723 +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12724 +#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
12725 +extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12726 +#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
12727 +
12728 +#endif /* DWC_LINUX */
12729 +
12730 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12731 +typedef struct dwc_ioctx {
12732 +       struct device *dev;
12733 +       bus_space_tag_t iot;
12734 +       bus_space_handle_t ioh;
12735 +} dwc_ioctx_t;
12736 +
12737 +/** BSD needs two extra parameters for register read/write, so we pass
12738 + * them in using the IO context parameter.
12739 + */
12740 +/** Reads the content of a 32-bit register. */
12741 +extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
12742 +#define dwc_read_reg32 DWC_READ_REG32
12743 +
12744 +/** Reads the content of a 64-bit register. */
12745 +extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
12746 +#define dwc_read_reg64 DWC_READ_REG64
12747 +
12748 +/** Writes to a 32-bit register. */
12749 +extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
12750 +#define dwc_write_reg32 DWC_WRITE_REG32
12751 +
12752 +/** Writes to a 64-bit register. */
12753 +extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
12754 +#define dwc_write_reg64 DWC_WRITE_REG64
12755 +
12756 +/**
12757 + * Modify bit values in a register.  Using the
12758 + * algorithm: (reg_contents & ~clear_mask) | set_mask.
12759 + */
12760 +extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
12761 +#define dwc_modify_reg32 DWC_MODIFY_REG32
12762 +extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
12763 +#define dwc_modify_reg64 DWC_MODIFY_REG64
12764 +
12765 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12766 +
12767 +/** @cond */
12768 +
12769 +/** @name Some convenience MACROS used internally.  Define DWC_DEBUG_REGS to log the
12770 + * register writes. */
12771 +
12772 +#ifdef DWC_LINUX
12773 +
12774 +# ifdef DWC_DEBUG_REGS
12775 +
12776 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12777 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12778 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12779 +} \
12780 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12781 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12782 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12783 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12784 +}
12785 +
12786 +#define dwc_define_read_write_reg(_reg,_container_type) \
12787 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12788 +       return DWC_READ_REG32(&container->regs->_reg); \
12789 +} \
12790 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12791 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12792 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12793 +}
12794 +
12795 +# else /* DWC_DEBUG_REGS */
12796 +
12797 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12798 +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
12799 +       return DWC_READ_REG32(&container->regs->_reg[num]); \
12800 +} \
12801 +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
12802 +       DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
12803 +}
12804 +
12805 +#define dwc_define_read_write_reg(_reg,_container_type) \
12806 +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
12807 +       return DWC_READ_REG32(&container->regs->_reg); \
12808 +} \
12809 +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
12810 +       DWC_WRITE_REG32(&container->regs->_reg, data); \
12811 +}
12812 +
12813 +# endif        /* DWC_DEBUG_REGS */
12814 +
12815 +#endif /* DWC_LINUX */
12816 +
12817 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12818 +
12819 +# ifdef DWC_DEBUG_REGS
12820 +
12821 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12822 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12823 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12824 +} \
12825 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12826 +       DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
12827 +                 &(((uint32_t*)container->regs->_reg)[num]), data); \
12828 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12829 +}
12830 +
12831 +#define dwc_define_read_write_reg(_reg,_container_type) \
12832 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12833 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12834 +} \
12835 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12836 +       DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
12837 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12838 +}
12839 +
12840 +# else /* DWC_DEBUG_REGS */
12841 +
12842 +#define dwc_define_read_write_reg_n(_reg,_container_type) \
12843 +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
12844 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
12845 +} \
12846 +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
12847 +       DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
12848 +}
12849 +
12850 +#define dwc_define_read_write_reg(_reg,_container_type) \
12851 +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
12852 +       return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
12853 +} \
12854 +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
12855 +       DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
12856 +}
12857 +
12858 +# endif        /* DWC_DEBUG_REGS */
12859 +
12860 +#endif /* DWC_FREEBSD || DWC_NETBSD */
12861 +
12862 +/** @endcond */
12863 +
12864 +
12865 +#ifdef DWC_CRYPTOLIB
12866 +/** @name Crypto Functions
12867 + *
12868 + * These are the low-level cryptographic functions used by the driver. */
12869 +
12870 +/** Perform AES CBC */
12871 +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
12872 +#define dwc_aes_cbc DWC_AES_CBC
12873 +
12874 +/** Fill the provided buffer with random bytes.  These should be cryptographic grade random numbers. */
12875 +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
12876 +#define dwc_random_bytes DWC_RANDOM_BYTES
12877 +
12878 +/** Perform the SHA-256 hash function */
12879 +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
12880 +#define dwc_sha256 DWC_SHA256
12881 +
12882 +/** Calculated the HMAC-SHA256 */
12883 +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
12884 +#define dwc_hmac_sha256 DWC_HMAC_SHA256
12885 +
12886 +#endif /* DWC_CRYPTOLIB */
12887 +
12888 +
12889 +/** @name Memory Allocation
12890 + *
12891 + * These function provide access to memory allocation.  There are only 2 DMA
12892 + * functions and 3 Regular memory functions that need to be implemented.  None
12893 + * of the memory debugging routines need to be implemented.  The allocation
12894 + * routines all ZERO the contents of the memory.
12895 + *
12896 + * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
12897 + * This checks for memory leaks, keeping track of alloc/free pairs.  It also
12898 + * keeps track of how much memory the driver is using at any given time. */
12899 +
12900 +#define DWC_PAGE_SIZE 4096
12901 +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
12902 +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
12903 +
12904 +#define DWC_INVALID_DMA_ADDR 0x0
12905 +
12906 +#ifdef DWC_LINUX
12907 +/** Type for a DMA address */
12908 +typedef dma_addr_t dwc_dma_t;
12909 +#endif
12910 +
12911 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
12912 +typedef bus_addr_t dwc_dma_t;
12913 +#endif
12914 +
12915 +#ifdef DWC_FREEBSD
12916 +typedef struct dwc_dmactx {
12917 +       struct device *dev;
12918 +       bus_dma_tag_t dma_tag;
12919 +       bus_dmamap_t dma_map;
12920 +       bus_addr_t dma_paddr;
12921 +       void *dma_vaddr;
12922 +} dwc_dmactx_t;
12923 +#endif
12924 +
12925 +#ifdef DWC_NETBSD
12926 +typedef struct dwc_dmactx {
12927 +       struct device *dev;
12928 +       bus_dma_tag_t dma_tag;
12929 +       bus_dmamap_t dma_map;
12930 +       bus_dma_segment_t segs[1];
12931 +       int nsegs;
12932 +       bus_addr_t dma_paddr;
12933 +       void *dma_vaddr;
12934 +} dwc_dmactx_t;
12935 +#endif
12936 +
12937 +/* @todo these functions will be added in the future */
12938 +#if 0
12939 +/**
12940 + * Creates a DMA pool from which you can allocate DMA buffers.  Buffers
12941 + * allocated from this pool will be guaranteed to meet the size, alignment, and
12942 + * boundary requirements specified.
12943 + *
12944 + * @param[in] size Specifies the size of the buffers that will be allocated from
12945 + * this pool.
12946 + * @param[in] align Specifies the byte alignment requirements of the buffers
12947 + * allocated from this pool.  Must be a power of 2.
12948 + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
12949 + * this pool must not cross.
12950 + *
12951 + * @returns A pointer to an internal opaque structure which is not to be
12952 + * accessed outside of these library functions.  Use this handle to specify
12953 + * which pools to allocate/free DMA buffers from and also to destroy the pool,
12954 + * when you are done with it.
12955 + */
12956 +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
12957 +
12958 +/**
12959 + * Destroy a DMA pool.  All buffers allocated from that pool must be freed first.
12960 + */
12961 +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
12962 +
12963 +/**
12964 + * Allocate a buffer from the specified DMA pool and zeros its contents.
12965 + */
12966 +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
12967 +
12968 +/**
12969 + * Free a previously allocated buffer from the DMA pool.
12970 + */
12971 +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
12972 +#endif
12973 +
12974 +/** Allocates a DMA capable buffer and zeroes its contents. */
12975 +extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
12976 +
12977 +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
12978 +extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
12979 +
12980 +/** Frees a previously allocated buffer. */
12981 +extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
12982 +
12983 +/** Allocates a block of memory and zeroes its contents. */
12984 +extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
12985 +
12986 +/** Allocates a block of memory and zeroes its contents, in an atomic manner
12987 + * which can be used inside interrupt context.  The size should be sufficiently
12988 + * small, a few KB at most, such that failures are not likely to occur.  Can just call
12989 + * __DWC_ALLOC if it is atomic. */
12990 +extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
12991 +
12992 +/** Frees a previously allocated buffer. */
12993 +extern void __DWC_FREE(void *mem_ctx, void *addr);
12994 +
12995 +#ifndef DWC_DEBUG_MEMORY
12996 +
12997 +#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
12998 +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
12999 +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
13000 +
13001 +# ifdef DWC_LINUX
13002 +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)
13003 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)
13004 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)
13005 +# endif
13006 +
13007 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13008 +#define DWC_DMA_ALLOC __DWC_DMA_ALLOC
13009 +#define DWC_DMA_FREE __DWC_DMA_FREE
13010 +# endif
13011 +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
13012 +
13013 +#else  /* DWC_DEBUG_MEMORY */
13014 +
13015 +extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
13016 +extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
13017 +extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
13018 +extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
13019 +                                char const *func, int line);
13020 +extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
13021 +                               char const *func, int line);
13022 +extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
13023 +                              dwc_dma_t dma_addr, char const *func, int line);
13024 +
13025 +extern int dwc_memory_debug_start(void *mem_ctx);
13026 +extern void dwc_memory_debug_stop(void);
13027 +extern void dwc_memory_debug_report(void);
13028 +
13029 +#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
13030 +#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
13031 +                                                       __func__, __LINE__)
13032 +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
13033 +
13034 +# ifdef DWC_LINUX
13035 +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \
13036 +                                               _dma_, __func__, __LINE__)
13037 +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \
13038 +                                               _dma_, __func__, __LINE__)
13039 +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \
13040 +                                               _virt_, _dma_, __func__, __LINE__)
13041 +# endif
13042 +
13043 +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13044 +#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
13045 +                                               _dma_, __func__, __LINE__)
13046 +#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
13047 +                                                _virt_, _dma_, __func__, __LINE__)
13048 +# endif
13049 +
13050 +#endif /* DWC_DEBUG_MEMORY */
13051 +
13052 +#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
13053 +#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
13054 +#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
13055 +
13056 +#ifdef DWC_LINUX
13057 +/* Linux doesn't need any extra parameters for DMA buffer allocation, so we
13058 + * just throw away the DMA context parameter.
13059 + */
13060 +#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
13061 +#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
13062 +#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
13063 +#endif
13064 +
13065 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13066 +/** BSD needs several extra parameters for DMA buffer allocation, so we pass
13067 + * them in using the DMA context parameter.
13068 + */
13069 +#define dwc_dma_alloc DWC_DMA_ALLOC
13070 +#define dwc_dma_free DWC_DMA_FREE
13071 +#endif
13072 +
13073 +
13074 +/** @name Memory and String Processing */
13075 +
13076 +/** memset() clone */
13077 +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
13078 +#define dwc_memset DWC_MEMSET
13079 +
13080 +/** memcpy() clone */
13081 +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
13082 +#define dwc_memcpy DWC_MEMCPY
13083 +
13084 +/** memmove() clone */
13085 +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
13086 +#define dwc_memmove DWC_MEMMOVE
13087 +
13088 +/** memcmp() clone */
13089 +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
13090 +#define dwc_memcmp DWC_MEMCMP
13091 +
13092 +/** strcmp() clone */
13093 +extern int DWC_STRCMP(void *s1, void *s2);
13094 +#define dwc_strcmp DWC_STRCMP
13095 +
13096 +/** strncmp() clone */
13097 +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
13098 +#define dwc_strncmp DWC_STRNCMP
13099 +
13100 +/** strlen() clone, for NULL terminated ASCII strings */
13101 +extern int DWC_STRLEN(char const *str);
13102 +#define dwc_strlen DWC_STRLEN
13103 +
13104 +/** strcpy() clone, for NULL terminated ASCII strings */
13105 +extern char *DWC_STRCPY(char *to, const char *from);
13106 +#define dwc_strcpy DWC_STRCPY
13107 +
13108 +/** strdup() clone.  If you wish to use memory allocation debugging, this
13109 + * implementation of strdup should use the DWC_* memory routines instead of
13110 + * calling a predefined strdup.  Otherwise the memory allocated by this routine
13111 + * will not be seen by the debugging routines. */
13112 +extern char *DWC_STRDUP(char const *str);
13113 +#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
13114 +
13115 +/** NOT an atoi() clone.  Read the description carefully.  Returns an integer
13116 + * converted from the string str in base 10 unless the string begins with a "0x"
13117 + * in which case it is base 16.  String must be a NULL terminated sequence of
13118 + * ASCII characters and may optionally begin with whitespace, a + or -, and a
13119 + * "0x" prefix if base 16.  The remaining characters must be valid digits for
13120 + * the number and end with a NULL character.  If any invalid characters are
13121 + * encountered or it returns with a negative error code and the results of the
13122 + * conversion are undefined.  On sucess it returns 0.  Overflow conditions are
13123 + * undefined.  An example implementation using atoi() can be referenced from the
13124 + * Linux implementation. */
13125 +extern int DWC_ATOI(const char *str, int32_t *value);
13126 +#define dwc_atoi DWC_ATOI
13127 +
13128 +/** Same as above but for unsigned. */
13129 +extern int DWC_ATOUI(const char *str, uint32_t *value);
13130 +#define dwc_atoui DWC_ATOUI
13131 +
13132 +#ifdef DWC_UTFLIB
13133 +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
13134 +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
13135 +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
13136 +#endif
13137 +
13138 +
13139 +/** @name Wait queues
13140 + *
13141 + * Wait queues provide a means of synchronizing between threads or processes.  A
13142 + * process can block on a waitq if some condition is not true, waiting for it to
13143 + * become true.  When the waitq is triggered all waiting process will get
13144 + * unblocked and the condition will be check again.  Waitqs should be triggered
13145 + * every time a condition can potentially change.*/
13146 +struct dwc_waitq;
13147 +
13148 +/** Type for a waitq */
13149 +typedef struct dwc_waitq dwc_waitq_t;
13150 +
13151 +/** The type of waitq condition callback function.  This is called every time
13152 + * condition is evaluated. */
13153 +typedef int (*dwc_waitq_condition_t)(void *data);
13154 +
13155 +/** Allocate a waitq */
13156 +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
13157 +#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
13158 +
13159 +/** Free a waitq */
13160 +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
13161 +#define dwc_waitq_free DWC_WAITQ_FREE
13162 +
13163 +/** Check the condition and if it is false, block on the waitq.  When unblocked, check the
13164 + * condition again.  The function returns when the condition becomes true.  The return value
13165 + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
13166 +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
13167 +#define dwc_waitq_wait DWC_WAITQ_WAIT
13168 +
13169 +/** Check the condition and if it is false, block on the waitq.  When unblocked,
13170 + * check the condition again.  The function returns when the condition become
13171 + * true or the timeout has passed.  The return value is 0 on condition true or
13172 + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
13173 + * error. */
13174 +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
13175 +                                     void *data, int32_t msecs);
13176 +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
13177 +
13178 +/** Trigger a waitq, unblocking all processes.  This should be called whenever a condition
13179 + * has potentially changed. */
13180 +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
13181 +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
13182 +
13183 +/** Unblock all processes waiting on the waitq with an ABORTED result. */
13184 +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
13185 +#define dwc_waitq_abort DWC_WAITQ_ABORT
13186 +
13187 +
13188 +/** @name Threads
13189 + *
13190 + * A thread must be explicitly stopped.  It must check DWC_THREAD_SHOULD_STOP
13191 + * whenever it is woken up, and then return.  The DWC_THREAD_STOP function
13192 + * returns the value from the thread.
13193 + */
13194 +
13195 +struct dwc_thread;
13196 +
13197 +/** Type for a thread */
13198 +typedef struct dwc_thread dwc_thread_t;
13199 +
13200 +/** The thread function */
13201 +typedef int (*dwc_thread_function_t)(void *data);
13202 +
13203 +/** Create a thread and start it running the thread_function.  Returns a handle
13204 + * to the thread */
13205 +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
13206 +#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
13207 +
13208 +/** Stops a thread.  Return the value returned by the thread.  Or will return
13209 + * DWC_ABORT if the thread never started. */
13210 +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
13211 +#define dwc_thread_stop DWC_THREAD_STOP
13212 +
13213 +/** Signifies to the thread that it must stop. */
13214 +#ifdef DWC_LINUX
13215 +/* Linux doesn't need any parameters for kthread_should_stop() */
13216 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
13217 +#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
13218 +
13219 +/* No thread_exit function in Linux */
13220 +#define dwc_thread_exit(_thrd_)
13221 +#endif
13222 +
13223 +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
13224 +/** BSD needs the thread pointer for kthread_suspend_check() */
13225 +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
13226 +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
13227 +
13228 +/** The thread must call this to exit. */
13229 +extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
13230 +#define dwc_thread_exit DWC_THREAD_EXIT
13231 +#endif
13232 +
13233 +
13234 +/** @name Work queues
13235 + *
13236 + * Workqs are used to queue a callback function to be called at some later time,
13237 + * in another thread. */
13238 +struct dwc_workq;
13239 +
13240 +/** Type for a workq */
13241 +typedef struct dwc_workq dwc_workq_t;
13242 +
13243 +/** The type of the callback function to be called. */
13244 +typedef void (*dwc_work_callback_t)(void *data);
13245 +
13246 +/** Allocate a workq */
13247 +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
13248 +#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
13249 +
13250 +/** Free a workq.  All work must be completed before being freed. */
13251 +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
13252 +#define dwc_workq_free DWC_WORKQ_FREE
13253 +
13254 +/** Schedule a callback on the workq, passing in data.  The function will be
13255 + * scheduled at some later time. */
13256 +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
13257 +                              void *data, char *format, ...)
13258 +#ifdef __GNUC__
13259 +       __attribute__ ((format(printf, 4, 5)));
13260 +#else
13261 +       ;
13262 +#endif
13263 +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
13264 +
13265 +/** Schedule a callback on the workq, that will be called until at least
13266 + * given number miliseconds have passed. */
13267 +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
13268 +                                      void *data, uint32_t time, char *format, ...)
13269 +#ifdef __GNUC__
13270 +       __attribute__ ((format(printf, 5, 6)));
13271 +#else
13272 +       ;
13273 +#endif
13274 +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
13275 +
13276 +/** The number of processes in the workq */
13277 +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
13278 +#define dwc_workq_pending DWC_WORKQ_PENDING
13279 +
13280 +/** Blocks until all the work in the workq is complete or timed out.  Returns <
13281 + * 0 on timeout. */
13282 +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
13283 +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
13284 +
13285 +
13286 +/** @name Tasklets
13287 + *
13288 + */
13289 +struct dwc_tasklet;
13290 +
13291 +/** Type for a tasklet */
13292 +typedef struct dwc_tasklet dwc_tasklet_t;
13293 +
13294 +/** The type of the callback function to be called */
13295 +typedef void (*dwc_tasklet_callback_t)(void *data);
13296 +
13297 +/** Allocates a tasklet */
13298 +extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
13299 +#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
13300 +
13301 +/** Frees a tasklet */
13302 +extern void DWC_TASK_FREE(dwc_tasklet_t *task);
13303 +#define dwc_task_free DWC_TASK_FREE
13304 +
13305 +/** Schedules a tasklet to run */
13306 +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
13307 +#define dwc_task_schedule DWC_TASK_SCHEDULE
13308 +
13309 +
13310 +/** @name Timer
13311 + *
13312 + * Callbacks must be small and atomic.
13313 + */
13314 +struct dwc_timer;
13315 +
13316 +/** Type for a timer */
13317 +typedef struct dwc_timer dwc_timer_t;
13318 +
13319 +/** The type of the callback function to be called */
13320 +typedef void (*dwc_timer_callback_t)(void *data);
13321 +
13322 +/** Allocates a timer */
13323 +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
13324 +#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
13325 +
13326 +/** Frees a timer */
13327 +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
13328 +#define dwc_timer_free DWC_TIMER_FREE
13329 +
13330 +/** Schedules the timer to run at time ms from now.  And will repeat at every
13331 + * repeat_interval msec therafter
13332 + *
13333 + * Modifies a timer that is still awaiting execution to a new expiration time.
13334 + * The mod_time is added to the old time.  */
13335 +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
13336 +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
13337 +
13338 +/** Disables the timer from execution. */
13339 +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
13340 +#define dwc_timer_cancel DWC_TIMER_CANCEL
13341 +
13342 +
13343 +/** @name Spinlocks
13344 + *
13345 + * These locks are used when the work between the lock/unlock is atomic and
13346 + * short.  Interrupts are also disabled during the lock/unlock and thus they are
13347 + * suitable to lock between interrupt/non-interrupt context.  They also lock
13348 + * between processes if you have multiple CPUs or Preemption.  If you don't have
13349 + * multiple CPUS or Preemption, then the you can simply implement the
13350 + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts.  Because
13351 + * the work between the lock/unlock is atomic, the process context will never
13352 + * change, and so you never have to lock between processes.  */
13353 +
13354 +struct dwc_spinlock;
13355 +
13356 +/** Type for a spinlock */
13357 +typedef struct dwc_spinlock dwc_spinlock_t;
13358 +
13359 +/** Type for the 'flags' argument to spinlock funtions */
13360 +typedef unsigned long dwc_irqflags_t;
13361 +
13362 +/** Returns an initialized lock variable.  This function should allocate and
13363 + * initialize the OS-specific data structure used for locking.  This data
13364 + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
13365 + * be freed by the DWC_FREE_LOCK when it is no longer used. */
13366 +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
13367 +#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
13368 +
13369 +/** Frees an initialized lock variable. */
13370 +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
13371 +#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
13372 +
13373 +/** Disables interrupts and blocks until it acquires the lock.
13374 + *
13375 + * @param lock Pointer to the spinlock.
13376 + * @param flags Unsigned long for irq flags storage.
13377 + */
13378 +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
13379 +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
13380 +
13381 +/** Re-enables the interrupt and releases the lock.
13382 + *
13383 + * @param lock Pointer to the spinlock.
13384 + * @param flags Unsigned long for irq flags storage.  Must be the same as was
13385 + * passed into DWC_LOCK.
13386 + */
13387 +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
13388 +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
13389 +
13390 +/** Blocks until it acquires the lock.
13391 + *
13392 + * @param lock Pointer to the spinlock.
13393 + */
13394 +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
13395 +#define dwc_spinlock DWC_SPINLOCK
13396 +
13397 +/** Releases the lock.
13398 + *
13399 + * @param lock Pointer to the spinlock.
13400 + */
13401 +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
13402 +#define dwc_spinunlock DWC_SPINUNLOCK
13403 +
13404 +
13405 +/** @name Mutexes
13406 + *
13407 + * Unlike spinlocks Mutexes lock only between processes and the work between the
13408 + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
13409 + */
13410 +
13411 +struct dwc_mutex;
13412 +
13413 +/** Type for a mutex */
13414 +typedef struct dwc_mutex dwc_mutex_t;
13415 +
13416 +/* For Linux Mutex Debugging make it inline because the debugging routines use
13417 + * the symbol to determine recursive locking.  This makes it falsely think
13418 + * recursive locking occurs. */
13419 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13420 +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
13421 +       __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
13422 +       mutex_init((struct mutex *)__mutexp); \
13423 +})
13424 +#endif
13425 +
13426 +/** Allocate a mutex */
13427 +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
13428 +#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
13429 +
13430 +/* For memory leak debugging when using Linux Mutex Debugging */
13431 +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
13432 +#define DWC_MUTEX_FREE(__mutexp) do { \
13433 +       mutex_destroy((struct mutex *)__mutexp); \
13434 +       DWC_FREE(__mutexp); \
13435 +} while(0)
13436 +#else
13437 +/** Free a mutex */
13438 +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
13439 +#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
13440 +#endif
13441 +
13442 +/** Lock a mutex */
13443 +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
13444 +#define dwc_mutex_lock DWC_MUTEX_LOCK
13445 +
13446 +/** Non-blocking lock returns 1 on successful lock. */
13447 +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
13448 +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
13449 +
13450 +/** Unlock a mutex */
13451 +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
13452 +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
13453 +
13454 +
13455 +/** @name Time */
13456 +
13457 +/** Microsecond delay.
13458 + *
13459 + * @param usecs  Microseconds to delay.
13460 + */
13461 +extern void DWC_UDELAY(uint32_t usecs);
13462 +#define dwc_udelay DWC_UDELAY
13463 +
13464 +/** Millisecond delay.
13465 + *
13466 + * @param msecs  Milliseconds to delay.
13467 + */
13468 +extern void DWC_MDELAY(uint32_t msecs);
13469 +#define dwc_mdelay DWC_MDELAY
13470 +
13471 +/** Non-busy waiting.
13472 + * Sleeps for specified number of milliseconds.
13473 + *
13474 + * @param msecs Milliseconds to sleep.
13475 + */
13476 +extern void DWC_MSLEEP(uint32_t msecs);
13477 +#define dwc_msleep DWC_MSLEEP
13478 +
13479 +/**
13480 + * Returns number of milliseconds since boot.
13481 + */
13482 +extern uint32_t DWC_TIME(void);
13483 +#define dwc_time DWC_TIME
13484 +
13485 +
13486 +
13487 +
13488 +/* @mainpage DWC Portability and Common Library
13489 + *
13490 + * This is the documentation for the DWC Portability and Common Library.
13491 + *
13492 + * @section intro Introduction
13493 + *
13494 + * The DWC Portability library consists of wrapper calls and data structures to
13495 + * all low-level functions which are typically provided by the OS.  The WUDEV
13496 + * driver uses only these functions.  In order to port the WUDEV driver, only
13497 + * the functions in this library need to be re-implemented, with the same
13498 + * behavior as documented here.
13499 + *
13500 + * The Common library consists of higher level functions, which rely only on
13501 + * calling the functions from the DWC Portability library.  These common
13502 + * routines are shared across modules.  Some of the common libraries need to be
13503 + * used directly by the driver programmer when porting WUDEV.  Such as the
13504 + * parameter and notification libraries.
13505 + *
13506 + * @section low Portability Library OS Wrapper Functions
13507 + *
13508 + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
13509 + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC().  All of
13510 + * these functions are included in the dwc_os.h file.
13511 + *
13512 + * There are many functions here covering a wide array of OS services.  Please
13513 + * see dwc_os.h for details, and implementation notes for each function.
13514 + *
13515 + * @section common Common Library Functions
13516 + *
13517 + * Any function starting with dwc and in all lowercase is a common library
13518 + * routine.  These functions have a portable implementation and do not need to
13519 + * be reimplemented when porting.  The common routines can be used by any
13520 + * driver, and some must be used by the end user to control the drivers.  For
13521 + * example, you must use the Parameter common library in order to set the
13522 + * parameters in the WUDEV module.
13523 + *
13524 + * The common libraries consist of the following:
13525 + *
13526 + * - Connection Contexts - Used internally and can be used by end-user.  See dwc_cc.h
13527 + * - Parameters - Used internally and can be used by end-user.  See dwc_params.h
13528 + * - Notifications - Used internally and can be used by end-user.  See dwc_notifier.h
13529 + * - Lists - Used internally and can be used by end-user.  See dwc_list.h
13530 + * - Memory Debugging - Used internally and can be used by end-user.  See dwc_os.h
13531 + * - Modpow - Used internally only.  See dwc_modpow.h
13532 + * - DH - Used internally only.  See dwc_dh.h
13533 + * - Crypto - Used internally only.  See dwc_crypto.h
13534 + *
13535 + *
13536 + * @section prereq Prerequistes For dwc_os.h
13537 + * @subsection types Data Types
13538 + *
13539 + * The dwc_os.h file assumes that several low-level data types are pre defined for the
13540 + * compilation environment.  These data types are:
13541 + *
13542 + * - uint8_t - unsigned 8-bit data type
13543 + * - int8_t - signed 8-bit data type
13544 + * - uint16_t - unsigned 16-bit data type
13545 + * - int16_t - signed 16-bit data type
13546 + * - uint32_t - unsigned 32-bit data type
13547 + * - int32_t - signed 32-bit data type
13548 + * - uint64_t - unsigned 64-bit data type
13549 + * - int64_t - signed 64-bit data type
13550 + *
13551 + * Ensure that these are defined before using dwc_os.h.  The easiest way to do
13552 + * that is to modify the top of the file to include the appropriate header.
13553 + * This is already done for the Linux environment.  If the DWC_LINUX macro is
13554 + * defined, the correct header will be added.  A standard header <stdint.h> is
13555 + * also used for environments where standard C headers are available.
13556 + *
13557 + * @subsection stdarg Variable Arguments
13558 + *
13559 + * Variable arguments are provided by a standard C header <stdarg.h>.  it is
13560 + * available in Both the Linux and ANSI C enviornment.  An equivalent must be
13561 + * provided in your enviornment in order to use dwc_os.h with the debug and
13562 + * tracing message functionality.
13563 + *
13564 + * @subsection thread Threading
13565 + *
13566 + * WUDEV Core must be run on an operating system that provides for multiple
13567 + * threads/processes.  Threading can be implemented in many ways, even in
13568 + * embedded systems without an operating system.  At the bare minimum, the
13569 + * system should be able to start any number of processes at any time to handle
13570 + * special work.  It need not be a pre-emptive system.  Process context can
13571 + * change upon a call to a blocking function.  The hardware interrupt context
13572 + * that calls the module's ISR() function must be differentiable from process
13573 + * context, even if your processes are impemented via a hardware interrupt.
13574 + * Further locking mechanism between process must exist (or be implemented), and
13575 + * process context must have a way to disable interrupts for a period of time to
13576 + * lock them out.  If all of this exists, the functions in dwc_os.h related to
13577 + * threading should be able to be implemented with the defined behavior.
13578 + *
13579 + */
13580 +
13581 +#ifdef __cplusplus
13582 +}
13583 +#endif
13584 +
13585 +#endif /* _DWC_OS_H_ */
13586 --- /dev/null
13587 +++ b/drivers/usb/host/dwc_common_port/usb.h
13588 @@ -0,0 +1,946 @@
13589 +/*
13590 + * Copyright (c) 1998 The NetBSD Foundation, Inc.
13591 + * All rights reserved.
13592 + *
13593 + * This code is derived from software contributed to The NetBSD Foundation
13594 + * by Lennart Augustsson (lennart@augustsson.net) at
13595 + * Carlstedt Research & Technology.
13596 + *
13597 + * Redistribution and use in source and binary forms, with or without
13598 + * modification, are permitted provided that the following conditions
13599 + * are met:
13600 + * 1. Redistributions of source code must retain the above copyright
13601 + *    notice, this list of conditions and the following disclaimer.
13602 + * 2. Redistributions in binary form must reproduce the above copyright
13603 + *    notice, this list of conditions and the following disclaimer in the
13604 + *    documentation and/or other materials provided with the distribution.
13605 + * 3. All advertising materials mentioning features or use of this software
13606 + *    must display the following acknowledgement:
13607 + *        This product includes software developed by the NetBSD
13608 + *        Foundation, Inc. and its contributors.
13609 + * 4. Neither the name of The NetBSD Foundation nor the names of its
13610 + *    contributors may be used to endorse or promote products derived
13611 + *    from this software without specific prior written permission.
13612 + *
13613 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
13614 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13615 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
13616 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
13617 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
13618 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13619 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
13620 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
13621 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
13622 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
13623 + * POSSIBILITY OF SUCH DAMAGE.
13624 + */
13625 +
13626 +/* Modified by Synopsys, Inc, 12/12/2007 */
13627 +
13628 +
13629 +#ifndef _USB_H_
13630 +#define _USB_H_
13631 +
13632 +#ifdef __cplusplus
13633 +extern "C" {
13634 +#endif
13635 +
13636 +/*
13637 + * The USB records contain some unaligned little-endian word
13638 + * components.  The U[SG]ETW macros take care of both the alignment
13639 + * and endian problem and should always be used to access non-byte
13640 + * values.
13641 + */
13642 +typedef u_int8_t uByte;
13643 +typedef u_int8_t uWord[2];
13644 +typedef u_int8_t uDWord[4];
13645 +
13646 +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
13647 +#define UCONSTW(x)     { (x) & 0xff, ((x) >> 8) & 0xff }
13648 +#define UCONSTDW(x)    { (x) & 0xff, ((x) >> 8) & 0xff, \
13649 +                         ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
13650 +
13651 +#if 1
13652 +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
13653 +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
13654 +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
13655 +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
13656 +                    (w)[1] = (u_int8_t)((v) >> 8), \
13657 +                    (w)[2] = (u_int8_t)((v) >> 16), \
13658 +                    (w)[3] = (u_int8_t)((v) >> 24))
13659 +#else
13660 +/*
13661 + * On little-endian machines that can handle unanliged accesses
13662 + * (e.g. i386) these macros can be replaced by the following.
13663 + */
13664 +#define UGETW(w) (*(u_int16_t *)(w))
13665 +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
13666 +#define UGETDW(w) (*(u_int32_t *)(w))
13667 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
13668 +#endif
13669 +
13670 +/*
13671 + * Macros for accessing UAS IU fields, which are big-endian
13672 + */
13673 +#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
13674 +#define IUCONSTW(x)    { ((x) >> 8) & 0xff, (x) & 0xff }
13675 +#define IUCONSTDW(x)   { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
13676 +                       ((x) >> 8) & 0xff, (x) & 0xff }
13677 +#define IUGETW(w) (((w)[0] << 8) | (w)[1])
13678 +#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
13679 +#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
13680 +#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
13681 +                     (w)[1] = (u_int8_t)((v) >> 16), \
13682 +                     (w)[2] = (u_int8_t)((v) >> 8), \
13683 +                     (w)[3] = (u_int8_t)(v))
13684 +
13685 +#define UPACKED __attribute__((__packed__))
13686 +
13687 +typedef struct {
13688 +       uByte           bmRequestType;
13689 +       uByte           bRequest;
13690 +       uWord           wValue;
13691 +       uWord           wIndex;
13692 +       uWord           wLength;
13693 +} UPACKED usb_device_request_t;
13694 +
13695 +#define UT_GET_DIR(a) ((a) & 0x80)
13696 +#define UT_WRITE               0x00
13697 +#define UT_READ                        0x80
13698 +
13699 +#define UT_GET_TYPE(a) ((a) & 0x60)
13700 +#define UT_STANDARD            0x00
13701 +#define UT_CLASS               0x20
13702 +#define UT_VENDOR              0x40
13703 +
13704 +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
13705 +#define UT_DEVICE              0x00
13706 +#define UT_INTERFACE           0x01
13707 +#define UT_ENDPOINT            0x02
13708 +#define UT_OTHER               0x03
13709 +
13710 +#define UT_READ_DEVICE         (UT_READ  | UT_STANDARD | UT_DEVICE)
13711 +#define UT_READ_INTERFACE      (UT_READ  | UT_STANDARD | UT_INTERFACE)
13712 +#define UT_READ_ENDPOINT       (UT_READ  | UT_STANDARD | UT_ENDPOINT)
13713 +#define UT_WRITE_DEVICE                (UT_WRITE | UT_STANDARD | UT_DEVICE)
13714 +#define UT_WRITE_INTERFACE     (UT_WRITE | UT_STANDARD | UT_INTERFACE)
13715 +#define UT_WRITE_ENDPOINT      (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
13716 +#define UT_READ_CLASS_DEVICE   (UT_READ  | UT_CLASS | UT_DEVICE)
13717 +#define UT_READ_CLASS_INTERFACE        (UT_READ  | UT_CLASS | UT_INTERFACE)
13718 +#define UT_READ_CLASS_OTHER    (UT_READ  | UT_CLASS | UT_OTHER)
13719 +#define UT_READ_CLASS_ENDPOINT (UT_READ  | UT_CLASS | UT_ENDPOINT)
13720 +#define UT_WRITE_CLASS_DEVICE  (UT_WRITE | UT_CLASS | UT_DEVICE)
13721 +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
13722 +#define UT_WRITE_CLASS_OTHER   (UT_WRITE | UT_CLASS | UT_OTHER)
13723 +#define UT_WRITE_CLASS_ENDPOINT        (UT_WRITE | UT_CLASS | UT_ENDPOINT)
13724 +#define UT_READ_VENDOR_DEVICE  (UT_READ  | UT_VENDOR | UT_DEVICE)
13725 +#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
13726 +#define UT_READ_VENDOR_OTHER   (UT_READ  | UT_VENDOR | UT_OTHER)
13727 +#define UT_READ_VENDOR_ENDPOINT        (UT_READ  | UT_VENDOR | UT_ENDPOINT)
13728 +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
13729 +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
13730 +#define UT_WRITE_VENDOR_OTHER  (UT_WRITE | UT_VENDOR | UT_OTHER)
13731 +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
13732 +
13733 +/* Requests */
13734 +#define UR_GET_STATUS          0x00
13735 +#define  USTAT_STANDARD_STATUS  0x00
13736 +#define  WUSTAT_WUSB_FEATURE    0x01
13737 +#define  WUSTAT_CHANNEL_INFO    0x02
13738 +#define  WUSTAT_RECEIVED_DATA   0x03
13739 +#define  WUSTAT_MAS_AVAILABILITY 0x04
13740 +#define  WUSTAT_CURRENT_TRANSMIT_POWER 0x05
13741 +#define UR_CLEAR_FEATURE       0x01
13742 +#define UR_SET_FEATURE         0x03
13743 +#define UR_SET_AND_TEST_FEATURE 0x0c
13744 +#define UR_SET_ADDRESS         0x05
13745 +#define UR_GET_DESCRIPTOR      0x06
13746 +#define  UDESC_DEVICE          0x01
13747 +#define  UDESC_CONFIG          0x02
13748 +#define  UDESC_STRING          0x03
13749 +#define  UDESC_INTERFACE       0x04
13750 +#define  UDESC_ENDPOINT                0x05
13751 +#define  UDESC_SS_USB_COMPANION        0x30
13752 +#define  UDESC_DEVICE_QUALIFIER        0x06
13753 +#define  UDESC_OTHER_SPEED_CONFIGURATION 0x07
13754 +#define  UDESC_INTERFACE_POWER 0x08
13755 +#define  UDESC_OTG             0x09
13756 +#define  WUDESC_SECURITY       0x0c
13757 +#define  WUDESC_KEY            0x0d
13758 +#define   WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
13759 +#define   WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
13760 +#define    WUD_KEY_TYPE_ASSOC    0x01
13761 +#define    WUD_KEY_TYPE_GTK      0x02
13762 +#define   WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
13763 +#define    WUD_KEY_ORIGIN_HOST   0x00
13764 +#define    WUD_KEY_ORIGIN_DEVICE 0x01
13765 +#define  WUDESC_ENCRYPTION_TYPE        0x0e
13766 +#define  WUDESC_BOS            0x0f
13767 +#define  WUDESC_DEVICE_CAPABILITY 0x10
13768 +#define  WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
13769 +#define  UDESC_BOS             0x0f
13770 +#define  UDESC_DEVICE_CAPABILITY 0x10
13771 +#define  UDESC_CS_DEVICE       0x21    /* class specific */
13772 +#define  UDESC_CS_CONFIG       0x22
13773 +#define  UDESC_CS_STRING       0x23
13774 +#define  UDESC_CS_INTERFACE    0x24
13775 +#define  UDESC_CS_ENDPOINT     0x25
13776 +#define  UDESC_HUB             0x29
13777 +#define UR_SET_DESCRIPTOR      0x07
13778 +#define UR_GET_CONFIG          0x08
13779 +#define UR_SET_CONFIG          0x09
13780 +#define UR_GET_INTERFACE       0x0a
13781 +#define UR_SET_INTERFACE       0x0b
13782 +#define UR_SYNCH_FRAME         0x0c
13783 +#define WUR_SET_ENCRYPTION      0x0d
13784 +#define WUR_GET_ENCRYPTION     0x0e
13785 +#define WUR_SET_HANDSHAKE      0x0f
13786 +#define WUR_GET_HANDSHAKE      0x10
13787 +#define WUR_SET_CONNECTION     0x11
13788 +#define WUR_SET_SECURITY_DATA  0x12
13789 +#define WUR_GET_SECURITY_DATA  0x13
13790 +#define WUR_SET_WUSB_DATA      0x14
13791 +#define  WUDATA_DRPIE_INFO     0x01
13792 +#define  WUDATA_TRANSMIT_DATA  0x02
13793 +#define  WUDATA_TRANSMIT_PARAMS        0x03
13794 +#define  WUDATA_RECEIVE_PARAMS 0x04
13795 +#define  WUDATA_TRANSMIT_POWER 0x05
13796 +#define WUR_LOOPBACK_DATA_WRITE        0x15
13797 +#define WUR_LOOPBACK_DATA_READ 0x16
13798 +#define WUR_SET_INTERFACE_DS   0x17
13799 +
13800 +/* Feature numbers */
13801 +#define UF_ENDPOINT_HALT       0
13802 +#define UF_DEVICE_REMOTE_WAKEUP        1
13803 +#define UF_TEST_MODE           2
13804 +#define UF_DEVICE_B_HNP_ENABLE 3
13805 +#define UF_DEVICE_A_HNP_SUPPORT        4
13806 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
13807 +#define WUF_WUSB               3
13808 +#define  WUF_TX_DRPIE          0x0
13809 +#define  WUF_DEV_XMIT_PACKET   0x1
13810 +#define  WUF_COUNT_PACKETS     0x2
13811 +#define  WUF_CAPTURE_PACKETS   0x3
13812 +#define UF_FUNCTION_SUSPEND    0
13813 +#define UF_U1_ENABLE           48
13814 +#define UF_U2_ENABLE           49
13815 +#define UF_LTM_ENABLE          50
13816 +
13817 +/* Class requests from the USB 2.0 hub spec, table 11-15 */
13818 +#define UCR_CLEAR_HUB_FEATURE          (0x2000 | UR_CLEAR_FEATURE)
13819 +#define UCR_CLEAR_PORT_FEATURE         (0x2300 | UR_CLEAR_FEATURE)
13820 +#define UCR_GET_HUB_DESCRIPTOR         (0xa000 | UR_GET_DESCRIPTOR)
13821 +#define UCR_GET_HUB_STATUS             (0xa000 | UR_GET_STATUS)
13822 +#define UCR_GET_PORT_STATUS            (0xa300 | UR_GET_STATUS)
13823 +#define UCR_SET_HUB_FEATURE            (0x2000 | UR_SET_FEATURE)
13824 +#define UCR_SET_PORT_FEATURE           (0x2300 | UR_SET_FEATURE)
13825 +#define UCR_SET_AND_TEST_PORT_FEATURE  (0xa300 | UR_SET_AND_TEST_FEATURE)
13826 +
13827 +#ifdef _MSC_VER
13828 +#include <pshpack1.h>
13829 +#endif
13830 +
13831 +typedef struct {
13832 +       uByte           bLength;
13833 +       uByte           bDescriptorType;
13834 +       uByte           bDescriptorSubtype;
13835 +} UPACKED usb_descriptor_t;
13836 +
13837 +typedef struct {
13838 +       uByte           bLength;
13839 +       uByte           bDescriptorType;
13840 +} UPACKED usb_descriptor_header_t;
13841 +
13842 +typedef struct {
13843 +       uByte           bLength;
13844 +       uByte           bDescriptorType;
13845 +       uWord           bcdUSB;
13846 +#define UD_USB_2_0             0x0200
13847 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
13848 +       uByte           bDeviceClass;
13849 +       uByte           bDeviceSubClass;
13850 +       uByte           bDeviceProtocol;
13851 +       uByte           bMaxPacketSize;
13852 +       /* The fields below are not part of the initial descriptor. */
13853 +       uWord           idVendor;
13854 +       uWord           idProduct;
13855 +       uWord           bcdDevice;
13856 +       uByte           iManufacturer;
13857 +       uByte           iProduct;
13858 +       uByte           iSerialNumber;
13859 +       uByte           bNumConfigurations;
13860 +} UPACKED usb_device_descriptor_t;
13861 +#define USB_DEVICE_DESCRIPTOR_SIZE 18
13862 +
13863 +typedef struct {
13864 +       uByte           bLength;
13865 +       uByte           bDescriptorType;
13866 +       uWord           wTotalLength;
13867 +       uByte           bNumInterface;
13868 +       uByte           bConfigurationValue;
13869 +       uByte           iConfiguration;
13870 +#define UC_ATT_ONE             (1 << 7)        /* must be set */
13871 +#define UC_ATT_SELFPOWER       (1 << 6)        /* self powered */
13872 +#define UC_ATT_WAKEUP          (1 << 5)        /* can wakeup */
13873 +#define UC_ATT_BATTERY         (1 << 4)        /* battery powered */
13874 +       uByte           bmAttributes;
13875 +#define UC_BUS_POWERED         0x80
13876 +#define UC_SELF_POWERED                0x40
13877 +#define UC_REMOTE_WAKEUP       0x20
13878 +       uByte           bMaxPower; /* max current in 2 mA units */
13879 +#define UC_POWER_FACTOR 2
13880 +} UPACKED usb_config_descriptor_t;
13881 +#define USB_CONFIG_DESCRIPTOR_SIZE 9
13882 +
13883 +typedef struct {
13884 +       uByte           bLength;
13885 +       uByte           bDescriptorType;
13886 +       uByte           bInterfaceNumber;
13887 +       uByte           bAlternateSetting;
13888 +       uByte           bNumEndpoints;
13889 +       uByte           bInterfaceClass;
13890 +       uByte           bInterfaceSubClass;
13891 +       uByte           bInterfaceProtocol;
13892 +       uByte           iInterface;
13893 +} UPACKED usb_interface_descriptor_t;
13894 +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
13895 +
13896 +typedef struct {
13897 +       uByte           bLength;
13898 +       uByte           bDescriptorType;
13899 +       uByte           bEndpointAddress;
13900 +#define UE_GET_DIR(a)  ((a) & 0x80)
13901 +#define UE_SET_DIR(a,d)        ((a) | (((d)&1) << 7))
13902 +#define UE_DIR_IN      0x80
13903 +#define UE_DIR_OUT     0x00
13904 +#define UE_ADDR                0x0f
13905 +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
13906 +       uByte           bmAttributes;
13907 +#define UE_XFERTYPE    0x03
13908 +#define  UE_CONTROL    0x00
13909 +#define  UE_ISOCHRONOUS        0x01
13910 +#define  UE_BULK       0x02
13911 +#define  UE_INTERRUPT  0x03
13912 +#define UE_GET_XFERTYPE(a)     ((a) & UE_XFERTYPE)
13913 +#define UE_ISO_TYPE    0x0c
13914 +#define  UE_ISO_ASYNC  0x04
13915 +#define  UE_ISO_ADAPT  0x08
13916 +#define  UE_ISO_SYNC   0x0c
13917 +#define UE_GET_ISO_TYPE(a)     ((a) & UE_ISO_TYPE)
13918 +       uWord           wMaxPacketSize;
13919 +       uByte           bInterval;
13920 +} UPACKED usb_endpoint_descriptor_t;
13921 +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
13922 +
13923 +typedef struct ss_endpoint_companion_descriptor {
13924 +       uByte bLength;
13925 +       uByte bDescriptorType;
13926 +       uByte bMaxBurst;
13927 +#define USSE_GET_MAX_STREAMS(a)                ((a) & 0x1f)
13928 +#define USSE_SET_MAX_STREAMS(a, b)     ((a) | ((b) & 0x1f))
13929 +#define USSE_GET_MAX_PACKET_NUM(a)     ((a) & 0x03)
13930 +#define USSE_SET_MAX_PACKET_NUM(a, b)  ((a) | ((b) & 0x03))
13931 +       uByte bmAttributes;
13932 +       uWord wBytesPerInterval;
13933 +} UPACKED ss_endpoint_companion_descriptor_t;
13934 +#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
13935 +
13936 +typedef struct {
13937 +       uByte           bLength;
13938 +       uByte           bDescriptorType;
13939 +       uWord           bString[127];
13940 +} UPACKED usb_string_descriptor_t;
13941 +#define USB_MAX_STRING_LEN 128
13942 +#define USB_LANGUAGE_TABLE 0   /* # of the string language id table */
13943 +
13944 +/* Hub specific request */
13945 +#define UR_GET_BUS_STATE       0x02
13946 +#define UR_CLEAR_TT_BUFFER     0x08
13947 +#define UR_RESET_TT            0x09
13948 +#define UR_GET_TT_STATE                0x0a
13949 +#define UR_STOP_TT             0x0b
13950 +
13951 +/* Hub features */
13952 +#define UHF_C_HUB_LOCAL_POWER  0
13953 +#define UHF_C_HUB_OVER_CURRENT 1
13954 +#define UHF_PORT_CONNECTION    0
13955 +#define UHF_PORT_ENABLE                1
13956 +#define UHF_PORT_SUSPEND       2
13957 +#define UHF_PORT_OVER_CURRENT  3
13958 +#define UHF_PORT_RESET         4
13959 +#define UHF_PORT_L1            5
13960 +#define UHF_PORT_POWER         8
13961 +#define UHF_PORT_LOW_SPEED     9
13962 +#define UHF_PORT_HIGH_SPEED    10
13963 +#define UHF_C_PORT_CONNECTION  16
13964 +#define UHF_C_PORT_ENABLE      17
13965 +#define UHF_C_PORT_SUSPEND     18
13966 +#define UHF_C_PORT_OVER_CURRENT        19
13967 +#define UHF_C_PORT_RESET       20
13968 +#define UHF_C_PORT_L1          23
13969 +#define UHF_PORT_TEST          21
13970 +#define UHF_PORT_INDICATOR     22
13971 +
13972 +typedef struct {
13973 +       uByte           bDescLength;
13974 +       uByte           bDescriptorType;
13975 +       uByte           bNbrPorts;
13976 +       uWord           wHubCharacteristics;
13977 +#define UHD_PWR                        0x0003
13978 +#define  UHD_PWR_GANGED                0x0000
13979 +#define  UHD_PWR_INDIVIDUAL    0x0001
13980 +#define  UHD_PWR_NO_SWITCH     0x0002
13981 +#define UHD_COMPOUND           0x0004
13982 +#define UHD_OC                 0x0018
13983 +#define  UHD_OC_GLOBAL         0x0000
13984 +#define  UHD_OC_INDIVIDUAL     0x0008
13985 +#define  UHD_OC_NONE           0x0010
13986 +#define UHD_TT_THINK           0x0060
13987 +#define  UHD_TT_THINK_8                0x0000
13988 +#define  UHD_TT_THINK_16       0x0020
13989 +#define  UHD_TT_THINK_24       0x0040
13990 +#define  UHD_TT_THINK_32       0x0060
13991 +#define UHD_PORT_IND           0x0080
13992 +       uByte           bPwrOn2PwrGood; /* delay in 2 ms units */
13993 +#define UHD_PWRON_FACTOR 2
13994 +       uByte           bHubContrCurrent;
13995 +       uByte           DeviceRemovable[32]; /* max 255 ports */
13996 +#define UHD_NOT_REMOV(desc, i) \
13997 +    (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
13998 +       /* deprecated */ uByte          PortPowerCtrlMask[1];
13999 +} UPACKED usb_hub_descriptor_t;
14000 +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
14001 +
14002 +typedef struct {
14003 +       uByte           bLength;
14004 +       uByte           bDescriptorType;
14005 +       uWord           bcdUSB;
14006 +       uByte           bDeviceClass;
14007 +       uByte           bDeviceSubClass;
14008 +       uByte           bDeviceProtocol;
14009 +       uByte           bMaxPacketSize0;
14010 +       uByte           bNumConfigurations;
14011 +       uByte           bReserved;
14012 +} UPACKED usb_device_qualifier_t;
14013 +#define USB_DEVICE_QUALIFIER_SIZE 10
14014 +
14015 +typedef struct {
14016 +       uByte           bLength;
14017 +       uByte           bDescriptorType;
14018 +       uByte           bmAttributes;
14019 +#define UOTG_SRP       0x01
14020 +#define UOTG_HNP       0x02
14021 +} UPACKED usb_otg_descriptor_t;
14022 +
14023 +/* OTG feature selectors */
14024 +#define UOTG_B_HNP_ENABLE      3
14025 +#define UOTG_A_HNP_SUPPORT     4
14026 +#define UOTG_A_ALT_HNP_SUPPORT 5
14027 +
14028 +typedef struct {
14029 +       uWord           wStatus;
14030 +/* Device status flags */
14031 +#define UDS_SELF_POWERED               0x0001
14032 +#define UDS_REMOTE_WAKEUP              0x0002
14033 +/* Endpoint status flags */
14034 +#define UES_HALT                       0x0001
14035 +} UPACKED usb_status_t;
14036 +
14037 +typedef struct {
14038 +       uWord           wHubStatus;
14039 +#define UHS_LOCAL_POWER                        0x0001
14040 +#define UHS_OVER_CURRENT               0x0002
14041 +       uWord           wHubChange;
14042 +} UPACKED usb_hub_status_t;
14043 +
14044 +typedef struct {
14045 +       uWord           wPortStatus;
14046 +#define UPS_CURRENT_CONNECT_STATUS     0x0001
14047 +#define UPS_PORT_ENABLED               0x0002
14048 +#define UPS_SUSPEND                    0x0004
14049 +#define UPS_OVERCURRENT_INDICATOR      0x0008
14050 +#define UPS_RESET                      0x0010
14051 +#define UPS_PORT_POWER                 0x0100
14052 +#define UPS_LOW_SPEED                  0x0200
14053 +#define UPS_HIGH_SPEED                 0x0400
14054 +#define UPS_PORT_TEST                  0x0800
14055 +#define UPS_PORT_INDICATOR             0x1000
14056 +       uWord           wPortChange;
14057 +#define UPS_C_CONNECT_STATUS           0x0001
14058 +#define UPS_C_PORT_ENABLED             0x0002
14059 +#define UPS_C_SUSPEND                  0x0004
14060 +#define UPS_C_OVERCURRENT_INDICATOR    0x0008
14061 +#define UPS_C_PORT_RESET               0x0010
14062 +} UPACKED usb_port_status_t;
14063 +
14064 +#ifdef _MSC_VER
14065 +#include <poppack.h>
14066 +#endif
14067 +
14068 +/* Device class codes */
14069 +#define UDCLASS_IN_INTERFACE   0x00
14070 +#define UDCLASS_COMM           0x02
14071 +#define UDCLASS_HUB            0x09
14072 +#define  UDSUBCLASS_HUB                0x00
14073 +#define  UDPROTO_FSHUB         0x00
14074 +#define  UDPROTO_HSHUBSTT      0x01
14075 +#define  UDPROTO_HSHUBMTT      0x02
14076 +#define UDCLASS_DIAGNOSTIC     0xdc
14077 +#define UDCLASS_WIRELESS       0xe0
14078 +#define  UDSUBCLASS_RF         0x01
14079 +#define   UDPROTO_BLUETOOTH    0x01
14080 +#define UDCLASS_VENDOR         0xff
14081 +
14082 +/* Interface class codes */
14083 +#define UICLASS_UNSPEC         0x00
14084 +
14085 +#define UICLASS_AUDIO          0x01
14086 +#define  UISUBCLASS_AUDIOCONTROL       1
14087 +#define  UISUBCLASS_AUDIOSTREAM                2
14088 +#define  UISUBCLASS_MIDISTREAM         3
14089 +
14090 +#define UICLASS_CDC            0x02 /* communication */
14091 +#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL  1
14092 +#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL     2
14093 +#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL    3
14094 +#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
14095 +#define  UISUBCLASS_CAPI_CONTROLMODEL          5
14096 +#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
14097 +#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
14098 +#define   UIPROTO_CDC_AT                       1
14099 +
14100 +#define UICLASS_HID            0x03
14101 +#define  UISUBCLASS_BOOT       1
14102 +#define  UIPROTO_BOOT_KEYBOARD 1
14103 +
14104 +#define UICLASS_PHYSICAL       0x05
14105 +
14106 +#define UICLASS_IMAGE          0x06
14107 +
14108 +#define UICLASS_PRINTER                0x07
14109 +#define  UISUBCLASS_PRINTER    1
14110 +#define  UIPROTO_PRINTER_UNI   1
14111 +#define  UIPROTO_PRINTER_BI    2
14112 +#define  UIPROTO_PRINTER_1284  3
14113 +
14114 +#define UICLASS_MASS           0x08
14115 +#define  UISUBCLASS_RBC                1
14116 +#define  UISUBCLASS_SFF8020I   2
14117 +#define  UISUBCLASS_QIC157     3
14118 +#define  UISUBCLASS_UFI                4
14119 +#define  UISUBCLASS_SFF8070I   5
14120 +#define  UISUBCLASS_SCSI       6
14121 +#define  UIPROTO_MASS_CBI_I    0
14122 +#define  UIPROTO_MASS_CBI      1
14123 +#define  UIPROTO_MASS_BBB_OLD  2       /* Not in the spec anymore */
14124 +#define  UIPROTO_MASS_BBB      80      /* 'P' for the Iomega Zip drive */
14125 +
14126 +#define UICLASS_HUB            0x09
14127 +#define  UISUBCLASS_HUB                0
14128 +#define  UIPROTO_FSHUB         0
14129 +#define  UIPROTO_HSHUBSTT      0 /* Yes, same as previous */
14130 +#define  UIPROTO_HSHUBMTT      1
14131 +
14132 +#define UICLASS_CDC_DATA       0x0a
14133 +#define  UISUBCLASS_DATA               0
14134 +#define   UIPROTO_DATA_ISDNBRI         0x30    /* Physical iface */
14135 +#define   UIPROTO_DATA_HDLC            0x31    /* HDLC */
14136 +#define   UIPROTO_DATA_TRANSPARENT     0x32    /* Transparent */
14137 +#define   UIPROTO_DATA_Q921M           0x50    /* Management for Q921 */
14138 +#define   UIPROTO_DATA_Q921            0x51    /* Data for Q921 */
14139 +#define   UIPROTO_DATA_Q921TM          0x52    /* TEI multiplexer for Q921 */
14140 +#define   UIPROTO_DATA_V42BIS          0x90    /* Data compression */
14141 +#define   UIPROTO_DATA_Q931            0x91    /* Euro-ISDN */
14142 +#define   UIPROTO_DATA_V120            0x92    /* V.24 rate adaption */
14143 +#define   UIPROTO_DATA_CAPI            0x93    /* CAPI 2.0 commands */
14144 +#define   UIPROTO_DATA_HOST_BASED      0xfd    /* Host based driver */
14145 +#define   UIPROTO_DATA_PUF             0xfe    /* see Prot. Unit Func. Desc.*/
14146 +#define   UIPROTO_DATA_VENDOR          0xff    /* Vendor specific */
14147 +
14148 +#define UICLASS_SMARTCARD      0x0b
14149 +
14150 +/*#define UICLASS_FIRM_UPD     0x0c*/
14151 +
14152 +#define UICLASS_SECURITY       0x0d
14153 +
14154 +#define UICLASS_DIAGNOSTIC     0xdc
14155 +
14156 +#define UICLASS_WIRELESS       0xe0
14157 +#define  UISUBCLASS_RF                 0x01
14158 +#define   UIPROTO_BLUETOOTH            0x01
14159 +
14160 +#define UICLASS_APPL_SPEC      0xfe
14161 +#define  UISUBCLASS_FIRMWARE_DOWNLOAD  1
14162 +#define  UISUBCLASS_IRDA               2
14163 +#define  UIPROTO_IRDA                  0
14164 +
14165 +#define UICLASS_VENDOR         0xff
14166 +
14167 +#define USB_HUB_MAX_DEPTH 5
14168 +
14169 +/*
14170 + * Minimum time a device needs to be powered down to go through
14171 + * a power cycle.  XXX Are these time in the spec?
14172 + */
14173 +#define USB_POWER_DOWN_TIME    200 /* ms */
14174 +#define USB_PORT_POWER_DOWN_TIME       100 /* ms */
14175 +
14176 +#if 0
14177 +/* These are the values from the spec. */
14178 +#define USB_PORT_RESET_DELAY   10  /* ms */
14179 +#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
14180 +#define USB_PORT_RESET_RECOVERY        10  /* ms */
14181 +#define USB_PORT_POWERUP_DELAY 100 /* ms */
14182 +#define USB_SET_ADDRESS_SETTLE 2   /* ms */
14183 +#define USB_RESUME_DELAY       (20*5)  /* ms */
14184 +#define USB_RESUME_WAIT                10  /* ms */
14185 +#define USB_RESUME_RECOVERY    10  /* ms */
14186 +#define USB_EXTRA_POWER_UP_TIME        0   /* ms */
14187 +#else
14188 +/* Allow for marginal (i.e. non-conforming) devices. */
14189 +#define USB_PORT_RESET_DELAY   50  /* ms */
14190 +#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
14191 +#define USB_PORT_RESET_RECOVERY        250  /* ms */
14192 +#define USB_PORT_POWERUP_DELAY 300 /* ms */
14193 +#define USB_SET_ADDRESS_SETTLE 10  /* ms */
14194 +#define USB_RESUME_DELAY       (50*5)  /* ms */
14195 +#define USB_RESUME_WAIT                50  /* ms */
14196 +#define USB_RESUME_RECOVERY    50  /* ms */
14197 +#define USB_EXTRA_POWER_UP_TIME        20  /* ms */
14198 +#endif
14199 +
14200 +#define USB_MIN_POWER          100 /* mA */
14201 +#define USB_MAX_POWER          500 /* mA */
14202 +
14203 +#define USB_BUS_RESET_DELAY    100 /* ms XXX?*/
14204 +
14205 +#define USB_UNCONFIG_NO 0
14206 +#define USB_UNCONFIG_INDEX (-1)
14207 +
14208 +/*** ioctl() related stuff ***/
14209 +
14210 +struct usb_ctl_request {
14211 +       int     ucr_addr;
14212 +       usb_device_request_t ucr_request;
14213 +       void    *ucr_data;
14214 +       int     ucr_flags;
14215 +#define USBD_SHORT_XFER_OK     0x04    /* allow short reads */
14216 +       int     ucr_actlen;             /* actual length transferred */
14217 +};
14218 +
14219 +struct usb_alt_interface {
14220 +       int     uai_config_index;
14221 +       int     uai_interface_index;
14222 +       int     uai_alt_no;
14223 +};
14224 +
14225 +#define USB_CURRENT_CONFIG_INDEX (-1)
14226 +#define USB_CURRENT_ALT_INDEX (-1)
14227 +
14228 +struct usb_config_desc {
14229 +       int     ucd_config_index;
14230 +       usb_config_descriptor_t ucd_desc;
14231 +};
14232 +
14233 +struct usb_interface_desc {
14234 +       int     uid_config_index;
14235 +       int     uid_interface_index;
14236 +       int     uid_alt_index;
14237 +       usb_interface_descriptor_t uid_desc;
14238 +};
14239 +
14240 +struct usb_endpoint_desc {
14241 +       int     ued_config_index;
14242 +       int     ued_interface_index;
14243 +       int     ued_alt_index;
14244 +       int     ued_endpoint_index;
14245 +       usb_endpoint_descriptor_t ued_desc;
14246 +};
14247 +
14248 +struct usb_full_desc {
14249 +       int     ufd_config_index;
14250 +       u_int   ufd_size;
14251 +       u_char  *ufd_data;
14252 +};
14253 +
14254 +struct usb_string_desc {
14255 +       int     usd_string_index;
14256 +       int     usd_language_id;
14257 +       usb_string_descriptor_t usd_desc;
14258 +};
14259 +
14260 +struct usb_ctl_report_desc {
14261 +       int     ucrd_size;
14262 +       u_char  ucrd_data[1024];        /* filled data size will vary */
14263 +};
14264 +
14265 +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
14266 +
14267 +#define USB_MAX_DEVNAMES 4
14268 +#define USB_MAX_DEVNAMELEN 16
14269 +struct usb_device_info {
14270 +       u_int8_t        udi_bus;
14271 +       u_int8_t        udi_addr;       /* device address */
14272 +       usb_event_cookie_t udi_cookie;
14273 +       char            udi_product[USB_MAX_STRING_LEN];
14274 +       char            udi_vendor[USB_MAX_STRING_LEN];
14275 +       char            udi_release[8];
14276 +       u_int16_t       udi_productNo;
14277 +       u_int16_t       udi_vendorNo;
14278 +       u_int16_t       udi_releaseNo;
14279 +       u_int8_t        udi_class;
14280 +       u_int8_t        udi_subclass;
14281 +       u_int8_t        udi_protocol;
14282 +       u_int8_t        udi_config;
14283 +       u_int8_t        udi_speed;
14284 +#define USB_SPEED_UNKNOWN      0
14285 +#define USB_SPEED_LOW          1
14286 +#define USB_SPEED_FULL         2
14287 +#define USB_SPEED_HIGH         3
14288 +#define USB_SPEED_VARIABLE     4
14289 +#define USB_SPEED_SUPER                5
14290 +       int             udi_power;      /* power consumption in mA, 0 if selfpowered */
14291 +       int             udi_nports;
14292 +       char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
14293 +       u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
14294 +#define USB_PORT_ENABLED 0xff
14295 +#define USB_PORT_SUSPENDED 0xfe
14296 +#define USB_PORT_POWERED 0xfd
14297 +#define USB_PORT_DISABLED 0xfc
14298 +};
14299 +
14300 +struct usb_ctl_report {
14301 +       int     ucr_report;
14302 +       u_char  ucr_data[1024]; /* filled data size will vary */
14303 +};
14304 +
14305 +struct usb_device_stats {
14306 +       u_long  uds_requests[4];        /* indexed by transfer type UE_* */
14307 +};
14308 +
14309 +#define WUSB_MIN_IE                    0x80
14310 +#define WUSB_WCTA_IE                   0x80
14311 +#define WUSB_WCONNECTACK_IE            0x81
14312 +#define WUSB_WHOSTINFO_IE              0x82
14313 +#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
14314 +#define   WUHI_CA_RECONN               0x00
14315 +#define   WUHI_CA_LIMITED              0x01
14316 +#define   WUHI_CA_ALL                  0x03
14317 +#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
14318 +#define WUSB_WCHCHANGEANNOUNCE_IE      0x83
14319 +#define WUSB_WDEV_DISCONNECT_IE                0x84
14320 +#define WUSB_WHOST_DISCONNECT_IE       0x85
14321 +#define WUSB_WRELEASE_CHANNEL_IE       0x86
14322 +#define WUSB_WWORK_IE                  0x87
14323 +#define WUSB_WCHANNEL_STOP_IE          0x88
14324 +#define WUSB_WDEV_KEEPALIVE_IE         0x89
14325 +#define WUSB_WISOCH_DISCARD_IE         0x8A
14326 +#define WUSB_WRESETDEVICE_IE           0x8B
14327 +#define WUSB_WXMIT_PACKET_ADJUST_IE    0x8C
14328 +#define WUSB_MAX_IE                    0x8C
14329 +
14330 +/* Device Notification Types */
14331 +
14332 +#define WUSB_DN_MIN                    0x01
14333 +#define WUSB_DN_CONNECT                        0x01
14334 +# define WUSB_DA_OLDCONN       0x00
14335 +# define WUSB_DA_NEWCONN       0x01
14336 +# define WUSB_DA_SELF_BEACON   0x02
14337 +# define WUSB_DA_DIR_BEACON    0x04
14338 +# define WUSB_DA_NO_BEACON     0x06
14339 +#define WUSB_DN_DISCONNECT             0x02
14340 +#define WUSB_DN_EPRDY                  0x03
14341 +#define WUSB_DN_MASAVAILCHANGED                0x04
14342 +#define WUSB_DN_REMOTEWAKEUP           0x05
14343 +#define WUSB_DN_SLEEP                  0x06
14344 +#define WUSB_DN_ALIVE                  0x07
14345 +#define WUSB_DN_MAX                    0x07
14346 +
14347 +#ifdef _MSC_VER
14348 +#include <pshpack1.h>
14349 +#endif
14350 +
14351 +/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
14352 +typedef struct wusb_hndshk_data {
14353 +       uByte bMessageNumber;
14354 +       uByte bStatus;
14355 +       uByte tTKID[3];
14356 +       uByte bReserved;
14357 +       uByte CDID[16];
14358 +       uByte Nonce[16];
14359 +       uByte MIC[8];
14360 +} UPACKED wusb_hndshk_data_t;
14361 +#define WUSB_HANDSHAKE_LEN_FOR_MIC     38
14362 +
14363 +/* WUSB Connection Context */
14364 +typedef struct wusb_conn_context {
14365 +       uByte CHID [16];
14366 +       uByte CDID [16];
14367 +       uByte CK [16];
14368 +} UPACKED wusb_conn_context_t;
14369 +
14370 +/* WUSB Security Descriptor */
14371 +typedef struct wusb_security_desc {
14372 +       uByte bLength;
14373 +       uByte bDescriptorType;
14374 +       uWord wTotalLength;
14375 +       uByte bNumEncryptionTypes;
14376 +} UPACKED wusb_security_desc_t;
14377 +
14378 +/* WUSB Encryption Type Descriptor */
14379 +typedef struct wusb_encrypt_type_desc {
14380 +       uByte bLength;
14381 +       uByte bDescriptorType;
14382 +
14383 +       uByte bEncryptionType;
14384 +#define WUETD_UNSECURE         0
14385 +#define WUETD_WIRED            1
14386 +#define WUETD_CCM_1            2
14387 +#define WUETD_RSA_1            3
14388 +
14389 +       uByte bEncryptionValue;
14390 +       uByte bAuthKeyIndex;
14391 +} UPACKED wusb_encrypt_type_desc_t;
14392 +
14393 +/* WUSB Key Descriptor */
14394 +typedef struct wusb_key_desc {
14395 +       uByte bLength;
14396 +       uByte bDescriptorType;
14397 +       uByte tTKID[3];
14398 +       uByte bReserved;
14399 +       uByte KeyData[1];       /* variable length */
14400 +} UPACKED wusb_key_desc_t;
14401 +
14402 +/* WUSB BOS Descriptor (Binary device Object Store) */
14403 +typedef struct wusb_bos_desc {
14404 +       uByte bLength;
14405 +       uByte bDescriptorType;
14406 +       uWord wTotalLength;
14407 +       uByte bNumDeviceCaps;
14408 +} UPACKED wusb_bos_desc_t;
14409 +
14410 +#define USB_DEVICE_CAPABILITY_20_EXTENSION     0x02
14411 +typedef struct usb_dev_cap_20_ext_desc {
14412 +       uByte bLength;
14413 +       uByte bDescriptorType;
14414 +       uByte bDevCapabilityType;
14415 +#define USB_20_EXT_LPM                         0x02
14416 +       uDWord bmAttributes;
14417 +} UPACKED usb_dev_cap_20_ext_desc_t;
14418 +
14419 +#define USB_DEVICE_CAPABILITY_SS_USB           0x03
14420 +typedef struct usb_dev_cap_ss_usb {
14421 +       uByte bLength;
14422 +       uByte bDescriptorType;
14423 +       uByte bDevCapabilityType;
14424 +#define USB_DC_SS_USB_LTM_CAPABLE              0x02
14425 +       uByte bmAttributes;
14426 +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW                0x01
14427 +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL       0x02
14428 +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH       0x04
14429 +#define USB_DC_SS_USB_SPEED_SUPPORT_SS         0x08
14430 +       uWord wSpeedsSupported;
14431 +       uByte bFunctionalitySupport;
14432 +       uByte bU1DevExitLat;
14433 +       uWord wU2DevExitLat;
14434 +} UPACKED usb_dev_cap_ss_usb_t;
14435 +
14436 +#define USB_DEVICE_CAPABILITY_CONTAINER_ID     0x04
14437 +typedef struct usb_dev_cap_container_id {
14438 +       uByte bLength;
14439 +       uByte bDescriptorType;
14440 +       uByte bDevCapabilityType;
14441 +       uByte bReserved;
14442 +       uByte containerID[16];
14443 +} UPACKED usb_dev_cap_container_id_t;
14444 +
14445 +/* Device Capability Type Codes */
14446 +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
14447 +
14448 +/* Device Capability Descriptor */
14449 +typedef struct wusb_dev_cap_desc {
14450 +       uByte bLength;
14451 +       uByte bDescriptorType;
14452 +       uByte bDevCapabilityType;
14453 +       uByte caps[1];  /* Variable length */
14454 +} UPACKED wusb_dev_cap_desc_t;
14455 +
14456 +/* Device Capability Descriptor */
14457 +typedef struct wusb_dev_cap_uwb_desc {
14458 +       uByte bLength;
14459 +       uByte bDescriptorType;
14460 +       uByte bDevCapabilityType;
14461 +       uByte bmAttributes;
14462 +       uWord wPHYRates;        /* Bitmap */
14463 +       uByte bmTFITXPowerInfo;
14464 +       uByte bmFFITXPowerInfo;
14465 +       uWord bmBandGroup;
14466 +       uByte bReserved;
14467 +} UPACKED wusb_dev_cap_uwb_desc_t;
14468 +
14469 +/* Wireless USB Endpoint Companion Descriptor */
14470 +typedef struct wusb_endpoint_companion_desc {
14471 +       uByte bLength;
14472 +       uByte bDescriptorType;
14473 +       uByte bMaxBurst;
14474 +       uByte bMaxSequence;
14475 +       uWord wMaxStreamDelay;
14476 +       uWord wOverTheAirPacketSize;
14477 +       uByte bOverTheAirInterval;
14478 +       uByte bmCompAttributes;
14479 +} UPACKED wusb_endpoint_companion_desc_t;
14480 +
14481 +/* Wireless USB Numeric Association M1 Data Structure */
14482 +typedef struct wusb_m1_data {
14483 +       uByte version;
14484 +       uWord langId;
14485 +       uByte deviceFriendlyNameLength;
14486 +       uByte sha_256_m3[32];
14487 +       uByte deviceFriendlyName[256];
14488 +} UPACKED wusb_m1_data_t;
14489 +
14490 +typedef struct wusb_m2_data {
14491 +       uByte version;
14492 +       uWord langId;
14493 +       uByte hostFriendlyNameLength;
14494 +       uByte pkh[384];
14495 +       uByte hostFriendlyName[256];
14496 +} UPACKED wusb_m2_data_t;
14497 +
14498 +typedef struct wusb_m3_data {
14499 +       uByte pkd[384];
14500 +       uByte nd;
14501 +} UPACKED wusb_m3_data_t;
14502 +
14503 +typedef struct wusb_m4_data {
14504 +       uDWord _attributeTypeIdAndLength_1;
14505 +       uWord  associationTypeId;
14506 +
14507 +       uDWord _attributeTypeIdAndLength_2;
14508 +       uWord  associationSubTypeId;
14509 +
14510 +       uDWord _attributeTypeIdAndLength_3;
14511 +       uDWord length;
14512 +
14513 +       uDWord _attributeTypeIdAndLength_4;
14514 +       uDWord associationStatus;
14515 +
14516 +       uDWord _attributeTypeIdAndLength_5;
14517 +       uByte  chid[16];
14518 +
14519 +       uDWord _attributeTypeIdAndLength_6;
14520 +       uByte  cdid[16];
14521 +
14522 +       uDWord _attributeTypeIdAndLength_7;
14523 +       uByte  bandGroups[2];
14524 +} UPACKED wusb_m4_data_t;
14525 +
14526 +#ifdef _MSC_VER
14527 +#include <poppack.h>
14528 +#endif
14529 +
14530 +#ifdef __cplusplus
14531 +}
14532 +#endif
14533 +
14534 +#endif /* _USB_H_ */
14535 --- /dev/null
14536 +++ b/drivers/usb/host/dwc_otg/Makefile
14537 @@ -0,0 +1,80 @@
14538 +#
14539 +# Makefile for DWC_otg Highspeed USB controller driver
14540 +#
14541 +
14542 +ifneq ($(KERNELRELEASE),)
14543 +
14544 +# Use the BUS_INTERFACE variable to compile the software for either
14545 +# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.
14546 +ifeq ($(BUS_INTERFACE),)
14547 +#      BUS_INTERFACE = -DPCI_INTERFACE
14548 +#      BUS_INTERFACE = -DLM_INTERFACE
14549 +        BUS_INTERFACE = -DPLATFORM_INTERFACE
14550 +endif
14551 +
14552 +#ccflags-y     += -DDEBUG
14553 +#ccflags-y     += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
14554 +
14555 +# Use one of the following flags to compile the software in host-only or
14556 +# device-only mode.
14557 +#ccflags-y        += -DDWC_HOST_ONLY
14558 +#ccflags-y        += -DDWC_DEVICE_ONLY
14559 +
14560 +ccflags-y      += -Dlinux -DDWC_HS_ELECT_TST
14561 +#ccflags-y     += -DDWC_EN_ISOC
14562 +ccflags-y      += -I$(obj)/../dwc_common_port
14563 +#ccflags-y     += -I$(PORTLIB)
14564 +ccflags-y      += -DDWC_LINUX
14565 +ccflags-y      += $(CFI)
14566 +ccflags-y      += $(BUS_INTERFACE)
14567 +#ccflags-y     += -DDWC_DEV_SRPCAP
14568 +
14569 +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
14570 +
14571 +dwc_otg-objs   := dwc_otg_driver.o dwc_otg_attr.o
14572 +dwc_otg-objs   += dwc_otg_cil.o dwc_otg_cil_intr.o
14573 +dwc_otg-objs   += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
14574 +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
14575 +dwc_otg-objs   += dwc_otg_adp.o
14576 +ifneq ($(CFI),)
14577 +dwc_otg-objs   += dwc_otg_cfi.o
14578 +endif
14579 +
14580 +kernrelwd := $(subst ., ,$(KERNELRELEASE))
14581 +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
14582 +
14583 +ifneq ($(kernrel3),2.6.20)
14584 +ccflags-y += $(CPPFLAGS)
14585 +endif
14586 +
14587 +else
14588 +
14589 +PWD            := $(shell pwd)
14590 +PORTLIB                := $(PWD)/../dwc_common_port
14591 +
14592 +# Command paths
14593 +CTAGS          := $(CTAGS)
14594 +DOXYGEN                := $(DOXYGEN)
14595 +
14596 +default: portlib
14597 +       $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14598 +
14599 +install: default
14600 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
14601 +       $(MAKE) -C$(KDIR) M=$(PWD) modules_install
14602 +
14603 +portlib:
14604 +       $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
14605 +       cp $(PORTLIB)/Module.symvers $(PWD)/
14606 +
14607 +docs:  $(wildcard *.[hc]) doc/doxygen.cfg
14608 +       $(DOXYGEN) doc/doxygen.cfg
14609 +
14610 +tags:  $(wildcard *.[hc])
14611 +       $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
14612 +
14613 +
14614 +clean:
14615 +       rm -rf   *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
14616 +
14617 +endif
14618 --- /dev/null
14619 +++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
14620 @@ -0,0 +1,224 @@
14621 +# Doxyfile 1.3.9.1
14622 +
14623 +#---------------------------------------------------------------------------
14624 +# Project related configuration options
14625 +#---------------------------------------------------------------------------
14626 +PROJECT_NAME           = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"
14627 +PROJECT_NUMBER         = v3.00a
14628 +OUTPUT_DIRECTORY       = ./doc/
14629 +CREATE_SUBDIRS         = NO
14630 +OUTPUT_LANGUAGE        = English
14631 +BRIEF_MEMBER_DESC      = YES
14632 +REPEAT_BRIEF           = YES
14633 +ABBREVIATE_BRIEF       = "The $name class" \
14634 +                         "The $name widget" \
14635 +                         "The $name file" \
14636 +                         is \
14637 +                         provides \
14638 +                         specifies \
14639 +                         contains \
14640 +                         represents \
14641 +                         a \
14642 +                         an \
14643 +                         the
14644 +ALWAYS_DETAILED_SEC    = NO
14645 +INLINE_INHERITED_MEMB  = NO
14646 +FULL_PATH_NAMES        = NO
14647 +STRIP_FROM_PATH        =
14648 +STRIP_FROM_INC_PATH    =
14649 +SHORT_NAMES            = NO
14650 +JAVADOC_AUTOBRIEF      = YES
14651 +MULTILINE_CPP_IS_BRIEF = NO
14652 +INHERIT_DOCS           = YES
14653 +DISTRIBUTE_GROUP_DOC   = NO
14654 +TAB_SIZE               = 8
14655 +ALIASES                =
14656 +OPTIMIZE_OUTPUT_FOR_C  = YES
14657 +OPTIMIZE_OUTPUT_JAVA   = NO
14658 +SUBGROUPING            = YES
14659 +#---------------------------------------------------------------------------
14660 +# Build related configuration options
14661 +#---------------------------------------------------------------------------
14662 +EXTRACT_ALL            = NO
14663 +EXTRACT_PRIVATE        = YES
14664 +EXTRACT_STATIC         = YES
14665 +EXTRACT_LOCAL_CLASSES  = YES
14666 +EXTRACT_LOCAL_METHODS  = NO
14667 +HIDE_UNDOC_MEMBERS     = NO
14668 +HIDE_UNDOC_CLASSES     = NO
14669 +HIDE_FRIEND_COMPOUNDS  = NO
14670 +HIDE_IN_BODY_DOCS      = NO
14671 +INTERNAL_DOCS          = NO
14672 +CASE_SENSE_NAMES       = NO
14673 +HIDE_SCOPE_NAMES       = NO
14674 +SHOW_INCLUDE_FILES     = YES
14675 +INLINE_INFO            = YES
14676 +SORT_MEMBER_DOCS       = NO
14677 +SORT_BRIEF_DOCS        = NO
14678 +SORT_BY_SCOPE_NAME     = NO
14679 +GENERATE_TODOLIST      = YES
14680 +GENERATE_TESTLIST      = YES
14681 +GENERATE_BUGLIST       = YES
14682 +GENERATE_DEPRECATEDLIST= YES
14683 +ENABLED_SECTIONS       =
14684 +MAX_INITIALIZER_LINES  = 30
14685 +SHOW_USED_FILES        = YES
14686 +SHOW_DIRECTORIES       = YES
14687 +#---------------------------------------------------------------------------
14688 +# configuration options related to warning and progress messages
14689 +#---------------------------------------------------------------------------
14690 +QUIET                  = YES
14691 +WARNINGS               = YES
14692 +WARN_IF_UNDOCUMENTED   = NO
14693 +WARN_IF_DOC_ERROR      = YES
14694 +WARN_FORMAT            = "$file:$line: $text"
14695 +WARN_LOGFILE           =
14696 +#---------------------------------------------------------------------------
14697 +# configuration options related to the input files
14698 +#---------------------------------------------------------------------------
14699 +INPUT                  = .
14700 +FILE_PATTERNS          = *.c \
14701 +                         *.h \
14702 +                         ./linux/*.c \
14703 +                         ./linux/*.h
14704 +RECURSIVE              = NO
14705 +EXCLUDE                = ./test/ \
14706 +                         ./dwc_otg/.AppleDouble/
14707 +EXCLUDE_SYMLINKS       = YES
14708 +EXCLUDE_PATTERNS       = *.mod.*
14709 +EXAMPLE_PATH           =
14710 +EXAMPLE_PATTERNS       = *
14711 +EXAMPLE_RECURSIVE      = NO
14712 +IMAGE_PATH             =
14713 +INPUT_FILTER           =
14714 +FILTER_PATTERNS        =
14715 +FILTER_SOURCE_FILES    = NO
14716 +#---------------------------------------------------------------------------
14717 +# configuration options related to source browsing
14718 +#---------------------------------------------------------------------------
14719 +SOURCE_BROWSER         = YES
14720 +INLINE_SOURCES         = NO
14721 +STRIP_CODE_COMMENTS    = YES
14722 +REFERENCED_BY_RELATION = NO
14723 +REFERENCES_RELATION    = NO
14724 +VERBATIM_HEADERS       = NO
14725 +#---------------------------------------------------------------------------
14726 +# configuration options related to the alphabetical class index
14727 +#---------------------------------------------------------------------------
14728 +ALPHABETICAL_INDEX     = NO
14729 +COLS_IN_ALPHA_INDEX    = 5
14730 +IGNORE_PREFIX          =
14731 +#---------------------------------------------------------------------------
14732 +# configuration options related to the HTML output
14733 +#---------------------------------------------------------------------------
14734 +GENERATE_HTML          = YES
14735 +HTML_OUTPUT            = html
14736 +HTML_FILE_EXTENSION    = .html
14737 +HTML_HEADER            =
14738 +HTML_FOOTER            =
14739 +HTML_STYLESHEET        =
14740 +HTML_ALIGN_MEMBERS     = YES
14741 +GENERATE_HTMLHELP      = NO
14742 +CHM_FILE               =
14743 +HHC_LOCATION           =
14744 +GENERATE_CHI           = NO
14745 +BINARY_TOC             = NO
14746 +TOC_EXPAND             = NO
14747 +DISABLE_INDEX          = NO
14748 +ENUM_VALUES_PER_LINE   = 4
14749 +GENERATE_TREEVIEW      = YES
14750 +TREEVIEW_WIDTH         = 250
14751 +#---------------------------------------------------------------------------
14752 +# configuration options related to the LaTeX output
14753 +#---------------------------------------------------------------------------
14754 +GENERATE_LATEX         = NO
14755 +LATEX_OUTPUT           = latex
14756 +LATEX_CMD_NAME         = latex
14757 +MAKEINDEX_CMD_NAME     = makeindex
14758 +COMPACT_LATEX          = NO
14759 +PAPER_TYPE             = a4wide
14760 +EXTRA_PACKAGES         =
14761 +LATEX_HEADER           =
14762 +PDF_HYPERLINKS         = NO
14763 +USE_PDFLATEX           = NO
14764 +LATEX_BATCHMODE        = NO
14765 +LATEX_HIDE_INDICES     = NO
14766 +#---------------------------------------------------------------------------
14767 +# configuration options related to the RTF output
14768 +#---------------------------------------------------------------------------
14769 +GENERATE_RTF           = NO
14770 +RTF_OUTPUT             = rtf
14771 +COMPACT_RTF            = NO
14772 +RTF_HYPERLINKS         = NO
14773 +RTF_STYLESHEET_FILE    =
14774 +RTF_EXTENSIONS_FILE    =
14775 +#---------------------------------------------------------------------------
14776 +# configuration options related to the man page output
14777 +#---------------------------------------------------------------------------
14778 +GENERATE_MAN           = NO
14779 +MAN_OUTPUT             = man
14780 +MAN_EXTENSION          = .3
14781 +MAN_LINKS              = NO
14782 +#---------------------------------------------------------------------------
14783 +# configuration options related to the XML output
14784 +#---------------------------------------------------------------------------
14785 +GENERATE_XML           = NO
14786 +XML_OUTPUT             = xml
14787 +XML_SCHEMA             =
14788 +XML_DTD                =
14789 +XML_PROGRAMLISTING     = YES
14790 +#---------------------------------------------------------------------------
14791 +# configuration options for the AutoGen Definitions output
14792 +#---------------------------------------------------------------------------
14793 +GENERATE_AUTOGEN_DEF   = NO
14794 +#---------------------------------------------------------------------------
14795 +# configuration options related to the Perl module output
14796 +#---------------------------------------------------------------------------
14797 +GENERATE_PERLMOD       = NO
14798 +PERLMOD_LATEX          = NO
14799 +PERLMOD_PRETTY         = YES
14800 +PERLMOD_MAKEVAR_PREFIX =
14801 +#---------------------------------------------------------------------------
14802 +# Configuration options related to the preprocessor
14803 +#---------------------------------------------------------------------------
14804 +ENABLE_PREPROCESSING   = YES
14805 +MACRO_EXPANSION        = YES
14806 +EXPAND_ONLY_PREDEF     = YES
14807 +SEARCH_INCLUDES        = YES
14808 +INCLUDE_PATH           =
14809 +INCLUDE_FILE_PATTERNS  =
14810 +PREDEFINED             = DEVICE_ATTR DWC_EN_ISOC
14811 +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
14812 +SKIP_FUNCTION_MACROS   = NO
14813 +#---------------------------------------------------------------------------
14814 +# Configuration::additions related to external references
14815 +#---------------------------------------------------------------------------
14816 +TAGFILES               =
14817 +GENERATE_TAGFILE       =
14818 +ALLEXTERNALS           = NO
14819 +EXTERNAL_GROUPS        = YES
14820 +PERL_PATH              = /usr/bin/perl
14821 +#---------------------------------------------------------------------------
14822 +# Configuration options related to the dot tool
14823 +#---------------------------------------------------------------------------
14824 +CLASS_DIAGRAMS         = YES
14825 +HIDE_UNDOC_RELATIONS   = YES
14826 +HAVE_DOT               = NO
14827 +CLASS_GRAPH            = YES
14828 +COLLABORATION_GRAPH    = YES
14829 +UML_LOOK               = NO
14830 +TEMPLATE_RELATIONS     = NO
14831 +INCLUDE_GRAPH          = YES
14832 +INCLUDED_BY_GRAPH      = YES
14833 +CALL_GRAPH             = NO
14834 +GRAPHICAL_HIERARCHY    = YES
14835 +DOT_IMAGE_FORMAT       = png
14836 +DOT_PATH               =
14837 +DOTFILE_DIRS           =
14838 +MAX_DOT_GRAPH_DEPTH    = 1000
14839 +GENERATE_LEGEND        = YES
14840 +DOT_CLEANUP            = YES
14841 +#---------------------------------------------------------------------------
14842 +# Configuration::additions related to the search engine
14843 +#---------------------------------------------------------------------------
14844 +SEARCHENGINE           = NO
14845 --- /dev/null
14846 +++ b/drivers/usb/host/dwc_otg/dummy_audio.c
14847 @@ -0,0 +1,1575 @@
14848 +/*
14849 + * zero.c -- Gadget Zero, for USB development
14850 + *
14851 + * Copyright (C) 2003-2004 David Brownell
14852 + * All rights reserved.
14853 + *
14854 + * Redistribution and use in source and binary forms, with or without
14855 + * modification, are permitted provided that the following conditions
14856 + * are met:
14857 + * 1. Redistributions of source code must retain the above copyright
14858 + *    notice, this list of conditions, and the following disclaimer,
14859 + *    without modification.
14860 + * 2. Redistributions in binary form must reproduce the above copyright
14861 + *    notice, this list of conditions and the following disclaimer in the
14862 + *    documentation and/or other materials provided with the distribution.
14863 + * 3. The names of the above-listed copyright holders may not be used
14864 + *    to endorse or promote products derived from this software without
14865 + *    specific prior written permission.
14866 + *
14867 + * ALTERNATIVELY, this software may be distributed under the terms of the
14868 + * GNU General Public License ("GPL") as published by the Free Software
14869 + * Foundation, either version 2 of that License or (at your option) any
14870 + * later version.
14871 + *
14872 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
14873 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14874 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
14875 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14876 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14877 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14878 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14879 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14880 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14881 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14882 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14883 + */
14884 +
14885 +
14886 +/*
14887 + * Gadget Zero only needs two bulk endpoints, and is an example of how you
14888 + * can write a hardware-agnostic gadget driver running inside a USB device.
14889 + *
14890 + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
14891 + * affect most of the driver.
14892 + *
14893 + * Use it with the Linux host/master side "usbtest" driver to get a basic
14894 + * functional test of your device-side usb stack, or with "usb-skeleton".
14895 + *
14896 + * It supports two similar configurations.  One sinks whatever the usb host
14897 + * writes, and in return sources zeroes.  The other loops whatever the host
14898 + * writes back, so the host can read it.  Module options include:
14899 + *
14900 + *   buflen=N          default N=4096, buffer size used
14901 + *   qlen=N            default N=32, how many buffers in the loopback queue
14902 + *   loopdefault       default false, list loopback config first
14903 + *
14904 + * Many drivers will only have one configuration, letting them be much
14905 + * simpler if they also don't support high speed operation (like this
14906 + * driver does).
14907 + */
14908 +
14909 +#include <linux/config.h>
14910 +#include <linux/module.h>
14911 +#include <linux/kernel.h>
14912 +#include <linux/delay.h>
14913 +#include <linux/ioport.h>
14914 +#include <linux/sched.h>
14915 +#include <linux/slab.h>
14916 +#include <linux/smp_lock.h>
14917 +#include <linux/errno.h>
14918 +#include <linux/init.h>
14919 +#include <linux/timer.h>
14920 +#include <linux/list.h>
14921 +#include <linux/interrupt.h>
14922 +#include <linux/uts.h>
14923 +#include <linux/version.h>
14924 +#include <linux/device.h>
14925 +#include <linux/moduleparam.h>
14926 +#include <linux/proc_fs.h>
14927 +
14928 +#include <asm/byteorder.h>
14929 +#include <asm/io.h>
14930 +#include <asm/irq.h>
14931 +#include <asm/system.h>
14932 +#include <asm/unaligned.h>
14933 +
14934 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
14935 +# include <linux/usb/ch9.h>
14936 +#else
14937 +# include <linux/usb_ch9.h>
14938 +#endif
14939 +
14940 +#include <linux/usb_gadget.h>
14941 +
14942 +
14943 +/*-------------------------------------------------------------------------*/
14944 +/*-------------------------------------------------------------------------*/
14945 +
14946 +
14947 +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
14948 +{
14949 +       int     count = 0;
14950 +       u8      c;
14951 +       u16     uchar;
14952 +
14953 +       /* this insists on correct encodings, though not minimal ones.
14954 +        * BUT it currently rejects legit 4-byte UTF-8 code points,
14955 +        * which need surrogate pairs.  (Unicode 3.1 can use them.)
14956 +        */
14957 +       while (len != 0 && (c = (u8) *s++) != 0) {
14958 +               if (unlikely(c & 0x80)) {
14959 +                       // 2-byte sequence:
14960 +                       // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
14961 +                       if ((c & 0xe0) == 0xc0) {
14962 +                               uchar = (c & 0x1f) << 6;
14963 +
14964 +                               c = (u8) *s++;
14965 +                               if ((c & 0xc0) != 0xc0)
14966 +                                       goto fail;
14967 +                               c &= 0x3f;
14968 +                               uchar |= c;
14969 +
14970 +                       // 3-byte sequence (most CJKV characters):
14971 +                       // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
14972 +                       } else if ((c & 0xf0) == 0xe0) {
14973 +                               uchar = (c & 0x0f) << 12;
14974 +
14975 +                               c = (u8) *s++;
14976 +                               if ((c & 0xc0) != 0xc0)
14977 +                                       goto fail;
14978 +                               c &= 0x3f;
14979 +                               uchar |= c << 6;
14980 +
14981 +                               c = (u8) *s++;
14982 +                               if ((c & 0xc0) != 0xc0)
14983 +                                       goto fail;
14984 +                               c &= 0x3f;
14985 +                               uchar |= c;
14986 +
14987 +                               /* no bogus surrogates */
14988 +                               if (0xd800 <= uchar && uchar <= 0xdfff)
14989 +                                       goto fail;
14990 +
14991 +                       // 4-byte sequence (surrogate pairs, currently rare):
14992 +                       // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
14993 +                       //     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
14994 +                       // (uuuuu = wwww + 1)
14995 +                       // FIXME accept the surrogate code points (only)
14996 +
14997 +                       } else
14998 +                               goto fail;
14999 +               } else
15000 +                       uchar = c;
15001 +               put_unaligned (cpu_to_le16 (uchar), cp++);
15002 +               count++;
15003 +               len--;
15004 +       }
15005 +       return count;
15006 +fail:
15007 +       return -1;
15008 +}
15009 +
15010 +
15011 +/**
15012 + * usb_gadget_get_string - fill out a string descriptor
15013 + * @table: of c strings encoded using UTF-8
15014 + * @id: string id, from low byte of wValue in get string descriptor
15015 + * @buf: at least 256 bytes
15016 + *
15017 + * Finds the UTF-8 string matching the ID, and converts it into a
15018 + * string descriptor in utf16-le.
15019 + * Returns length of descriptor (always even) or negative errno
15020 + *
15021 + * If your driver needs stings in multiple languages, you'll probably
15022 + * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
15023 + * using this routine after choosing which set of UTF-8 strings to use.
15024 + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
15025 + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
15026 + * characters (which are also widely used in C strings).
15027 + */
15028 +int
15029 +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
15030 +{
15031 +       struct usb_string       *s;
15032 +       int                     len;
15033 +
15034 +       /* descriptor 0 has the language id */
15035 +       if (id == 0) {
15036 +               buf [0] = 4;
15037 +               buf [1] = USB_DT_STRING;
15038 +               buf [2] = (u8) table->language;
15039 +               buf [3] = (u8) (table->language >> 8);
15040 +               return 4;
15041 +       }
15042 +       for (s = table->strings; s && s->s; s++)
15043 +               if (s->id == id)
15044 +                       break;
15045 +
15046 +       /* unrecognized: stall. */
15047 +       if (!s || !s->s)
15048 +               return -EINVAL;
15049 +
15050 +       /* string descriptors have length, tag, then UTF16-LE text */
15051 +       len = min ((size_t) 126, strlen (s->s));
15052 +       memset (buf + 2, 0, 2 * len);   /* zero all the bytes */
15053 +       len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
15054 +       if (len < 0)
15055 +               return -EINVAL;
15056 +       buf [0] = (len + 1) * 2;
15057 +       buf [1] = USB_DT_STRING;
15058 +       return buf [0];
15059 +}
15060 +
15061 +
15062 +/*-------------------------------------------------------------------------*/
15063 +/*-------------------------------------------------------------------------*/
15064 +
15065 +
15066 +/**
15067 + * usb_descriptor_fillbuf - fill buffer with descriptors
15068 + * @buf: Buffer to be filled
15069 + * @buflen: Size of buf
15070 + * @src: Array of descriptor pointers, terminated by null pointer.
15071 + *
15072 + * Copies descriptors into the buffer, returning the length or a
15073 + * negative error code if they can't all be copied.  Useful when
15074 + * assembling descriptors for an associated set of interfaces used
15075 + * as part of configuring a composite device; or in other cases where
15076 + * sets of descriptors need to be marshaled.
15077 + */
15078 +int
15079 +usb_descriptor_fillbuf(void *buf, unsigned buflen,
15080 +               const struct usb_descriptor_header **src)
15081 +{
15082 +       u8      *dest = buf;
15083 +
15084 +       if (!src)
15085 +               return -EINVAL;
15086 +
15087 +       /* fill buffer from src[] until null descriptor ptr */
15088 +       for (; 0 != *src; src++) {
15089 +               unsigned                len = (*src)->bLength;
15090 +
15091 +               if (len > buflen)
15092 +                       return -EINVAL;
15093 +               memcpy(dest, *src, len);
15094 +               buflen -= len;
15095 +               dest += len;
15096 +       }
15097 +       return dest - (u8 *)buf;
15098 +}
15099 +
15100 +
15101 +/**
15102 + * usb_gadget_config_buf - builts a complete configuration descriptor
15103 + * @config: Header for the descriptor, including characteristics such
15104 + *     as power requirements and number of interfaces.
15105 + * @desc: Null-terminated vector of pointers to the descriptors (interface,
15106 + *     endpoint, etc) defining all functions in this device configuration.
15107 + * @buf: Buffer for the resulting configuration descriptor.
15108 + * @length: Length of buffer.  If this is not big enough to hold the
15109 + *     entire configuration descriptor, an error code will be returned.
15110 + *
15111 + * This copies descriptors into the response buffer, building a descriptor
15112 + * for that configuration.  It returns the buffer length or a negative
15113 + * status code.  The config.wTotalLength field is set to match the length
15114 + * of the result, but other descriptor fields (including power usage and
15115 + * interface count) must be set by the caller.
15116 + *
15117 + * Gadget drivers could use this when constructing a config descriptor
15118 + * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
15119 + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
15120 + */
15121 +int usb_gadget_config_buf(
15122 +       const struct usb_config_descriptor      *config,
15123 +       void                                    *buf,
15124 +       unsigned                                length,
15125 +       const struct usb_descriptor_header      **desc
15126 +)
15127 +{
15128 +       struct usb_config_descriptor            *cp = buf;
15129 +       int                                     len;
15130 +
15131 +       /* config descriptor first */
15132 +       if (length < USB_DT_CONFIG_SIZE || !desc)
15133 +               return -EINVAL;
15134 +       *cp = *config;
15135 +
15136 +       /* then interface/endpoint/class/vendor/... */
15137 +       len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
15138 +                       length - USB_DT_CONFIG_SIZE, desc);
15139 +       if (len < 0)
15140 +               return len;
15141 +       len += USB_DT_CONFIG_SIZE;
15142 +       if (len > 0xffff)
15143 +               return -EINVAL;
15144 +
15145 +       /* patch up the config descriptor */
15146 +       cp->bLength = USB_DT_CONFIG_SIZE;
15147 +       cp->bDescriptorType = USB_DT_CONFIG;
15148 +       cp->wTotalLength = cpu_to_le16(len);
15149 +       cp->bmAttributes |= USB_CONFIG_ATT_ONE;
15150 +       return len;
15151 +}
15152 +
15153 +/*-------------------------------------------------------------------------*/
15154 +/*-------------------------------------------------------------------------*/
15155 +
15156 +
15157 +#define RBUF_LEN (1024*1024)
15158 +static int rbuf_start;
15159 +static int rbuf_len;
15160 +static __u8 rbuf[RBUF_LEN];
15161 +
15162 +/*-------------------------------------------------------------------------*/
15163 +
15164 +#define DRIVER_VERSION         "St Patrick's Day 2004"
15165 +
15166 +static const char shortname [] = "zero";
15167 +static const char longname [] = "YAMAHA YST-MS35D USB Speaker  ";
15168 +
15169 +static const char source_sink [] = "source and sink data";
15170 +static const char loopback [] = "loop input to output";
15171 +
15172 +/*-------------------------------------------------------------------------*/
15173 +
15174 +/*
15175 + * driver assumes self-powered hardware, and
15176 + * has no way for users to trigger remote wakeup.
15177 + *
15178 + * this version autoconfigures as much as possible,
15179 + * which is reasonable for most "bulk-only" drivers.
15180 + */
15181 +static const char *EP_IN_NAME;         /* source */
15182 +static const char *EP_OUT_NAME;                /* sink */
15183 +
15184 +/*-------------------------------------------------------------------------*/
15185 +
15186 +/* big enough to hold our biggest descriptor */
15187 +#define USB_BUFSIZ     512
15188 +
15189 +struct zero_dev {
15190 +       spinlock_t              lock;
15191 +       struct usb_gadget       *gadget;
15192 +       struct usb_request      *req;           /* for control responses */
15193 +
15194 +       /* when configured, we have one of two configs:
15195 +        * - source data (in to host) and sink it (out from host)
15196 +        * - or loop it back (out from host back in to host)
15197 +        */
15198 +       u8                      config;
15199 +       struct usb_ep           *in_ep, *out_ep;
15200 +
15201 +       /* autoresume timer */
15202 +       struct timer_list       resume;
15203 +};
15204 +
15205 +#define xprintk(d,level,fmt,args...) \
15206 +       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
15207 +
15208 +#ifdef DEBUG
15209 +#define DBG(dev,fmt,args...) \
15210 +       xprintk(dev , KERN_DEBUG , fmt , ## args)
15211 +#else
15212 +#define DBG(dev,fmt,args...) \
15213 +       do { } while (0)
15214 +#endif /* DEBUG */
15215 +
15216 +#ifdef VERBOSE
15217 +#define VDBG   DBG
15218 +#else
15219 +#define VDBG(dev,fmt,args...) \
15220 +       do { } while (0)
15221 +#endif /* VERBOSE */
15222 +
15223 +#define ERROR(dev,fmt,args...) \
15224 +       xprintk(dev , KERN_ERR , fmt , ## args)
15225 +#define WARN(dev,fmt,args...) \
15226 +       xprintk(dev , KERN_WARNING , fmt , ## args)
15227 +#define INFO(dev,fmt,args...) \
15228 +       xprintk(dev , KERN_INFO , fmt , ## args)
15229 +
15230 +/*-------------------------------------------------------------------------*/
15231 +
15232 +static unsigned buflen = 4096;
15233 +static unsigned qlen = 32;
15234 +static unsigned pattern = 0;
15235 +
15236 +module_param (buflen, uint, S_IRUGO|S_IWUSR);
15237 +module_param (qlen, uint, S_IRUGO|S_IWUSR);
15238 +module_param (pattern, uint, S_IRUGO|S_IWUSR);
15239 +
15240 +/*
15241 + * if it's nonzero, autoresume says how many seconds to wait
15242 + * before trying to wake up the host after suspend.
15243 + */
15244 +static unsigned autoresume = 0;
15245 +module_param (autoresume, uint, 0);
15246 +
15247 +/*
15248 + * Normally the "loopback" configuration is second (index 1) so
15249 + * it's not the default.  Here's where to change that order, to
15250 + * work better with hosts where config changes are problematic.
15251 + * Or controllers (like superh) that only support one config.
15252 + */
15253 +static int loopdefault = 0;
15254 +
15255 +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
15256 +
15257 +/*-------------------------------------------------------------------------*/
15258 +
15259 +/* Thanks to NetChip Technologies for donating this product ID.
15260 + *
15261 + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
15262 + * Instead:  allocate your own, using normal USB-IF procedures.
15263 + */
15264 +#ifndef        CONFIG_USB_ZERO_HNPTEST
15265 +#define DRIVER_VENDOR_NUM      0x0525          /* NetChip */
15266 +#define DRIVER_PRODUCT_NUM     0xa4a0          /* Linux-USB "Gadget Zero" */
15267 +#else
15268 +#define DRIVER_VENDOR_NUM      0x1a0a          /* OTG test device IDs */
15269 +#define DRIVER_PRODUCT_NUM     0xbadd
15270 +#endif
15271 +
15272 +/*-------------------------------------------------------------------------*/
15273 +
15274 +/*
15275 + * DESCRIPTORS ... most are static, but strings and (full)
15276 + * configuration descriptors are built on demand.
15277 + */
15278 +
15279 +/*
15280 +#define STRING_MANUFACTURER            25
15281 +#define STRING_PRODUCT                 42
15282 +#define STRING_SERIAL                  101
15283 +*/
15284 +#define STRING_MANUFACTURER            1
15285 +#define STRING_PRODUCT                 2
15286 +#define STRING_SERIAL                  3
15287 +
15288 +#define STRING_SOURCE_SINK             250
15289 +#define STRING_LOOPBACK                        251
15290 +
15291 +/*
15292 + * This device advertises two configurations; these numbers work
15293 + * on a pxa250 as well as more flexible hardware.
15294 + */
15295 +#define        CONFIG_SOURCE_SINK      3
15296 +#define        CONFIG_LOOPBACK         2
15297 +
15298 +/*
15299 +static struct usb_device_descriptor
15300 +device_desc = {
15301 +       .bLength =              sizeof device_desc,
15302 +       .bDescriptorType =      USB_DT_DEVICE,
15303 +
15304 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15305 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15306 +
15307 +       .idVendor =             __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
15308 +       .idProduct =            __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
15309 +       .iManufacturer =        STRING_MANUFACTURER,
15310 +       .iProduct =             STRING_PRODUCT,
15311 +       .iSerialNumber =        STRING_SERIAL,
15312 +       .bNumConfigurations =   2,
15313 +};
15314 +*/
15315 +static struct usb_device_descriptor
15316 +device_desc = {
15317 +       .bLength =              sizeof device_desc,
15318 +       .bDescriptorType =      USB_DT_DEVICE,
15319 +       .bcdUSB =               __constant_cpu_to_le16 (0x0100),
15320 +       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
15321 +       .bDeviceSubClass =      0,
15322 +       .bDeviceProtocol =      0,
15323 +       .bMaxPacketSize0 =      64,
15324 +       .bcdDevice =            __constant_cpu_to_le16 (0x0100),
15325 +       .idVendor =             __constant_cpu_to_le16 (0x0499),
15326 +       .idProduct =            __constant_cpu_to_le16 (0x3002),
15327 +       .iManufacturer =        STRING_MANUFACTURER,
15328 +       .iProduct =             STRING_PRODUCT,
15329 +       .iSerialNumber =        STRING_SERIAL,
15330 +       .bNumConfigurations =   1,
15331 +};
15332 +
15333 +static struct usb_config_descriptor
15334 +z_config = {
15335 +       .bLength =              sizeof z_config,
15336 +       .bDescriptorType =      USB_DT_CONFIG,
15337 +
15338 +       /* compute wTotalLength on the fly */
15339 +       .bNumInterfaces =       2,
15340 +       .bConfigurationValue =  1,
15341 +       .iConfiguration =       0,
15342 +       .bmAttributes =         0x40,
15343 +       .bMaxPower =            0,      /* self-powered */
15344 +};
15345 +
15346 +
15347 +static struct usb_otg_descriptor
15348 +otg_descriptor = {
15349 +       .bLength =              sizeof otg_descriptor,
15350 +       .bDescriptorType =      USB_DT_OTG,
15351 +
15352 +       .bmAttributes =         USB_OTG_SRP,
15353 +};
15354 +
15355 +/* one interface in each configuration */
15356 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15357 +
15358 +/*
15359 + * usb 2.0 devices need to expose both high speed and full speed
15360 + * descriptors, unless they only run at full speed.
15361 + *
15362 + * that means alternate endpoint descriptors (bigger packets)
15363 + * and a "device qualifier" ... plus more construction options
15364 + * for the config descriptor.
15365 + */
15366 +
15367 +static struct usb_qualifier_descriptor
15368 +dev_qualifier = {
15369 +       .bLength =              sizeof dev_qualifier,
15370 +       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
15371 +
15372 +       .bcdUSB =               __constant_cpu_to_le16 (0x0200),
15373 +       .bDeviceClass =         USB_CLASS_VENDOR_SPEC,
15374 +
15375 +       .bNumConfigurations =   2,
15376 +};
15377 +
15378 +
15379 +struct usb_cs_as_general_descriptor {
15380 +       __u8  bLength;
15381 +       __u8  bDescriptorType;
15382 +
15383 +       __u8  bDescriptorSubType;
15384 +       __u8  bTerminalLink;
15385 +       __u8  bDelay;
15386 +       __u16  wFormatTag;
15387 +} __attribute__ ((packed));
15388 +
15389 +struct usb_cs_as_format_descriptor {
15390 +       __u8  bLength;
15391 +       __u8  bDescriptorType;
15392 +
15393 +       __u8  bDescriptorSubType;
15394 +       __u8  bFormatType;
15395 +       __u8  bNrChannels;
15396 +       __u8  bSubframeSize;
15397 +       __u8  bBitResolution;
15398 +       __u8  bSamfreqType;
15399 +       __u8  tLowerSamFreq[3];
15400 +       __u8  tUpperSamFreq[3];
15401 +} __attribute__ ((packed));
15402 +
15403 +static const struct usb_interface_descriptor
15404 +z_audio_control_if_desc = {
15405 +       .bLength =              sizeof z_audio_control_if_desc,
15406 +       .bDescriptorType =      USB_DT_INTERFACE,
15407 +       .bInterfaceNumber = 0,
15408 +       .bAlternateSetting = 0,
15409 +       .bNumEndpoints = 0,
15410 +       .bInterfaceClass = USB_CLASS_AUDIO,
15411 +       .bInterfaceSubClass = 0x1,
15412 +       .bInterfaceProtocol = 0,
15413 +       .iInterface = 0,
15414 +};
15415 +
15416 +static const struct usb_interface_descriptor
15417 +z_audio_if_desc = {
15418 +       .bLength =              sizeof z_audio_if_desc,
15419 +       .bDescriptorType =      USB_DT_INTERFACE,
15420 +       .bInterfaceNumber = 1,
15421 +       .bAlternateSetting = 0,
15422 +       .bNumEndpoints = 0,
15423 +       .bInterfaceClass = USB_CLASS_AUDIO,
15424 +       .bInterfaceSubClass = 0x2,
15425 +       .bInterfaceProtocol = 0,
15426 +       .iInterface = 0,
15427 +};
15428 +
15429 +static const struct usb_interface_descriptor
15430 +z_audio_if_desc2 = {
15431 +       .bLength =              sizeof z_audio_if_desc,
15432 +       .bDescriptorType =      USB_DT_INTERFACE,
15433 +       .bInterfaceNumber = 1,
15434 +       .bAlternateSetting = 1,
15435 +       .bNumEndpoints = 1,
15436 +       .bInterfaceClass = USB_CLASS_AUDIO,
15437 +       .bInterfaceSubClass = 0x2,
15438 +       .bInterfaceProtocol = 0,
15439 +       .iInterface = 0,
15440 +};
15441 +
15442 +static const struct usb_cs_as_general_descriptor
15443 +z_audio_cs_as_if_desc = {
15444 +       .bLength = 7,
15445 +       .bDescriptorType = 0x24,
15446 +
15447 +       .bDescriptorSubType = 0x01,
15448 +       .bTerminalLink = 0x01,
15449 +       .bDelay = 0x0,
15450 +       .wFormatTag = __constant_cpu_to_le16 (0x0001)
15451 +};
15452 +
15453 +
15454 +static const struct usb_cs_as_format_descriptor
15455 +z_audio_cs_as_format_desc = {
15456 +       .bLength = 0xe,
15457 +       .bDescriptorType = 0x24,
15458 +
15459 +       .bDescriptorSubType = 2,
15460 +       .bFormatType = 1,
15461 +       .bNrChannels = 1,
15462 +       .bSubframeSize = 1,
15463 +       .bBitResolution = 8,
15464 +       .bSamfreqType = 0,
15465 +       .tLowerSamFreq = {0x7e, 0x13, 0x00},
15466 +       .tUpperSamFreq = {0xe2, 0xd6, 0x00},
15467 +};
15468 +
15469 +static const struct usb_endpoint_descriptor
15470 +z_iso_ep = {
15471 +       .bLength = 0x09,
15472 +       .bDescriptorType = 0x05,
15473 +       .bEndpointAddress = 0x04,
15474 +       .bmAttributes = 0x09,
15475 +       .wMaxPacketSize = 0x0038,
15476 +       .bInterval = 0x01,
15477 +       .bRefresh = 0x00,
15478 +       .bSynchAddress = 0x00,
15479 +};
15480 +
15481 +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15482 +
15483 +// 9 bytes
15484 +static char z_ac_interface_header_desc[] =
15485 +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
15486 +
15487 +// 12 bytes
15488 +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
15489 +                    0x03, 0x00, 0x00, 0x00};
15490 +// 13 bytes
15491 +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00,
15492 +                    0x02, 0x00, 0x02, 0x00, 0x00};
15493 +// 9 bytes
15494 +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02,
15495 +                    0x00};
15496 +
15497 +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,
15498 +                     0x00};
15499 +
15500 +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15501 +
15502 +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00,
15503 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15504 +
15505 +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15506 +                     0x00};
15507 +
15508 +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15509 +
15510 +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
15511 +                     0x00};
15512 +
15513 +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15514 +
15515 +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
15516 +                     0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15517 +
15518 +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
15519 +                     0x00};
15520 +
15521 +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15522 +
15523 +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
15524 +                      0x00};
15525 +
15526 +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15527 +
15528 +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
15529 +                      0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15530 +
15531 +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
15532 +                      0x00};
15533 +
15534 +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15535 +
15536 +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00,
15537 +                      0x00};
15538 +
15539 +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15540 +
15541 +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00,
15542 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15543 +
15544 +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
15545 +                      0x00};
15546 +
15547 +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15548 +
15549 +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
15550 +                      0x00};
15551 +
15552 +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
15553 +
15554 +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00,
15555 +                      0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
15556 +
15557 +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
15558 +                      0x00};
15559 +
15560 +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
15561 +
15562 +
15563 +
15564 +static const struct usb_descriptor_header *z_function [] = {
15565 +       (struct usb_descriptor_header *) &z_audio_control_if_desc,
15566 +       (struct usb_descriptor_header *) &z_ac_interface_header_desc,
15567 +       (struct usb_descriptor_header *) &z_0,
15568 +       (struct usb_descriptor_header *) &z_1,
15569 +       (struct usb_descriptor_header *) &z_2,
15570 +       (struct usb_descriptor_header *) &z_audio_if_desc,
15571 +       (struct usb_descriptor_header *) &z_audio_if_desc2,
15572 +       (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
15573 +       (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
15574 +       (struct usb_descriptor_header *) &z_iso_ep,
15575 +       (struct usb_descriptor_header *) &z_iso_ep2,
15576 +       (struct usb_descriptor_header *) &za_0,
15577 +       (struct usb_descriptor_header *) &za_1,
15578 +       (struct usb_descriptor_header *) &za_2,
15579 +       (struct usb_descriptor_header *) &za_3,
15580 +       (struct usb_descriptor_header *) &za_4,
15581 +       (struct usb_descriptor_header *) &za_5,
15582 +       (struct usb_descriptor_header *) &za_6,
15583 +       (struct usb_descriptor_header *) &za_7,
15584 +       (struct usb_descriptor_header *) &za_8,
15585 +       (struct usb_descriptor_header *) &za_9,
15586 +       (struct usb_descriptor_header *) &za_10,
15587 +       (struct usb_descriptor_header *) &za_11,
15588 +       (struct usb_descriptor_header *) &za_12,
15589 +       (struct usb_descriptor_header *) &za_13,
15590 +       (struct usb_descriptor_header *) &za_14,
15591 +       (struct usb_descriptor_header *) &za_15,
15592 +       (struct usb_descriptor_header *) &za_16,
15593 +       (struct usb_descriptor_header *) &za_17,
15594 +       (struct usb_descriptor_header *) &za_18,
15595 +       (struct usb_descriptor_header *) &za_19,
15596 +       (struct usb_descriptor_header *) &za_20,
15597 +       (struct usb_descriptor_header *) &za_21,
15598 +       (struct usb_descriptor_header *) &za_22,
15599 +       (struct usb_descriptor_header *) &za_23,
15600 +       (struct usb_descriptor_header *) &za_24,
15601 +       NULL,
15602 +};
15603 +
15604 +/* maxpacket and other transfer characteristics vary by speed. */
15605 +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
15606 +
15607 +#else
15608 +
15609 +/* if there's no high speed support, maxpacket doesn't change. */
15610 +#define ep_desc(g,hs,fs) fs
15611 +
15612 +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
15613 +
15614 +static char                            manufacturer [40];
15615 +//static char                          serial [40];
15616 +static char                            serial [] = "Ser 00 em";
15617 +
15618 +/* static strings, in UTF-8 */
15619 +static struct usb_string               strings [] = {
15620 +       { STRING_MANUFACTURER, manufacturer, },
15621 +       { STRING_PRODUCT, longname, },
15622 +       { STRING_SERIAL, serial, },
15623 +       { STRING_LOOPBACK, loopback, },
15624 +       { STRING_SOURCE_SINK, source_sink, },
15625 +       {  }                    /* end of list */
15626 +};
15627 +
15628 +static struct usb_gadget_strings       stringtab = {
15629 +       .language       = 0x0409,       /* en-us */
15630 +       .strings        = strings,
15631 +};
15632 +
15633 +/*
15634 + * config descriptors are also handcrafted.  these must agree with code
15635 + * that sets configurations, and with code managing interfaces and their
15636 + * altsettings.  other complexity may come from:
15637 + *
15638 + *  - high speed support, including "other speed config" rules
15639 + *  - multiple configurations
15640 + *  - interfaces with alternate settings
15641 + *  - embedded class or vendor-specific descriptors
15642 + *
15643 + * this handles high speed, and has a second config that could as easily
15644 + * have been an alternate interface setting (on most hardware).
15645 + *
15646 + * NOTE:  to demonstrate (and test) more USB capabilities, this driver
15647 + * should include an altsetting to test interrupt transfers, including
15648 + * high bandwidth modes at high speed.  (Maybe work like Intel's test
15649 + * device?)
15650 + */
15651 +static int
15652 +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
15653 +{
15654 +       int len;
15655 +       const struct usb_descriptor_header **function;
15656 +
15657 +       function = z_function;
15658 +       len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
15659 +       if (len < 0)
15660 +               return len;
15661 +       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
15662 +       return len;
15663 +}
15664 +
15665 +/*-------------------------------------------------------------------------*/
15666 +
15667 +static struct usb_request *
15668 +alloc_ep_req (struct usb_ep *ep, unsigned length)
15669 +{
15670 +       struct usb_request      *req;
15671 +
15672 +       req = usb_ep_alloc_request (ep, GFP_ATOMIC);
15673 +       if (req) {
15674 +               req->length = length;
15675 +               req->buf = usb_ep_alloc_buffer (ep, length,
15676 +                               &req->dma, GFP_ATOMIC);
15677 +               if (!req->buf) {
15678 +                       usb_ep_free_request (ep, req);
15679 +                       req = NULL;
15680 +               }
15681 +       }
15682 +       return req;
15683 +}
15684 +
15685 +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
15686 +{
15687 +       if (req->buf)
15688 +               usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
15689 +       usb_ep_free_request (ep, req);
15690 +}
15691 +
15692 +/*-------------------------------------------------------------------------*/
15693 +
15694 +/* optionally require specific source/sink data patterns  */
15695 +
15696 +static int
15697 +check_read_data (
15698 +       struct zero_dev         *dev,
15699 +       struct usb_ep           *ep,
15700 +       struct usb_request      *req
15701 +)
15702 +{
15703 +       unsigned        i;
15704 +       u8              *buf = req->buf;
15705 +
15706 +       for (i = 0; i < req->actual; i++, buf++) {
15707 +               switch (pattern) {
15708 +               /* all-zeroes has no synchronization issues */
15709 +               case 0:
15710 +                       if (*buf == 0)
15711 +                               continue;
15712 +                       break;
15713 +               /* mod63 stays in sync with short-terminated transfers,
15714 +                * or otherwise when host and gadget agree on how large
15715 +                * each usb transfer request should be.  resync is done
15716 +                * with set_interface or set_config.
15717 +                */
15718 +               case 1:
15719 +                       if (*buf == (u8)(i % 63))
15720 +                               continue;
15721 +                       break;
15722 +               }
15723 +               ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
15724 +               usb_ep_set_halt (ep);
15725 +               return -EINVAL;
15726 +       }
15727 +       return 0;
15728 +}
15729 +
15730 +/*-------------------------------------------------------------------------*/
15731 +
15732 +static void zero_reset_config (struct zero_dev *dev)
15733 +{
15734 +       if (dev->config == 0)
15735 +               return;
15736 +
15737 +       DBG (dev, "reset config\n");
15738 +
15739 +       /* just disable endpoints, forcing completion of pending i/o.
15740 +        * all our completion handlers free their requests in this case.
15741 +        */
15742 +       if (dev->in_ep) {
15743 +               usb_ep_disable (dev->in_ep);
15744 +               dev->in_ep = NULL;
15745 +       }
15746 +       if (dev->out_ep) {
15747 +               usb_ep_disable (dev->out_ep);
15748 +               dev->out_ep = NULL;
15749 +       }
15750 +       dev->config = 0;
15751 +       del_timer (&dev->resume);
15752 +}
15753 +
15754 +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
15755 +
15756 +static void
15757 +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
15758 +{
15759 +       struct zero_dev *dev = ep->driver_data;
15760 +       int             status = req->status;
15761 +       int i, j;
15762 +
15763 +       switch (status) {
15764 +
15765 +       case 0:                         /* normal completion? */
15766 +               //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
15767 +               for (i=0, j=rbuf_start; i<req->actual; i++) {
15768 +                       //printk ("%02x ", ((__u8*)req->buf)[i]);
15769 +                       rbuf[j] = ((__u8*)req->buf)[i];
15770 +                       j++;
15771 +                       if (j >= RBUF_LEN) j=0;
15772 +               }
15773 +               rbuf_start = j;
15774 +               //printk ("\n\n");
15775 +
15776 +               if (rbuf_len < RBUF_LEN) {
15777 +                       rbuf_len += req->actual;
15778 +                       if (rbuf_len > RBUF_LEN) {
15779 +                               rbuf_len = RBUF_LEN;
15780 +                       }
15781 +               }
15782 +
15783 +               break;
15784 +
15785 +       /* this endpoint is normally active while we're configured */
15786 +       case -ECONNABORTED:             /* hardware forced ep reset */
15787 +       case -ECONNRESET:               /* request dequeued */
15788 +       case -ESHUTDOWN:                /* disconnect from host */
15789 +               VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
15790 +                               req->actual, req->length);
15791 +               if (ep == dev->out_ep)
15792 +                       check_read_data (dev, ep, req);
15793 +               free_ep_req (ep, req);
15794 +               return;
15795 +
15796 +       case -EOVERFLOW:                /* buffer overrun on read means that
15797 +                                        * we didn't provide a big enough
15798 +                                        * buffer.
15799 +                                        */
15800 +       default:
15801 +#if 1
15802 +               DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
15803 +                               status, req->actual, req->length);
15804 +#endif
15805 +       case -EREMOTEIO:                /* short read */
15806 +               break;
15807 +       }
15808 +
15809 +       status = usb_ep_queue (ep, req, GFP_ATOMIC);
15810 +       if (status) {
15811 +               ERROR (dev, "kill %s:  resubmit %d bytes --> %d\n",
15812 +                               ep->name, req->length, status);
15813 +               usb_ep_set_halt (ep);
15814 +               /* FIXME recover later ... somehow */
15815 +       }
15816 +}
15817 +
15818 +static struct usb_request *
15819 +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
15820 +{
15821 +       struct usb_request      *req;
15822 +       int                     status;
15823 +
15824 +       req = alloc_ep_req (ep, 512);
15825 +       if (!req)
15826 +               return NULL;
15827 +
15828 +       req->complete = zero_isoc_complete;
15829 +
15830 +       status = usb_ep_queue (ep, req, gfp_flags);
15831 +       if (status) {
15832 +               struct zero_dev *dev = ep->driver_data;
15833 +
15834 +               ERROR (dev, "start %s --> %d\n", ep->name, status);
15835 +               free_ep_req (ep, req);
15836 +               req = NULL;
15837 +       }
15838 +
15839 +       return req;
15840 +}
15841 +
15842 +/* change our operational config.  this code must agree with the code
15843 + * that returns config descriptors, and altsetting code.
15844 + *
15845 + * it's also responsible for power management interactions. some
15846 + * configurations might not work with our current power sources.
15847 + *
15848 + * note that some device controller hardware will constrain what this
15849 + * code can do, perhaps by disallowing more than one configuration or
15850 + * by limiting configuration choices (like the pxa2xx).
15851 + */
15852 +static int
15853 +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
15854 +{
15855 +       int                     result = 0;
15856 +       struct usb_gadget       *gadget = dev->gadget;
15857 +       const struct usb_endpoint_descriptor    *d;
15858 +       struct usb_ep           *ep;
15859 +
15860 +       if (number == dev->config)
15861 +               return 0;
15862 +
15863 +       zero_reset_config (dev);
15864 +
15865 +       gadget_for_each_ep (ep, gadget) {
15866 +
15867 +               if (strcmp (ep->name, "ep4") == 0) {
15868 +
15869 +                       d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
15870 +                       result = usb_ep_enable (ep, d);
15871 +
15872 +                       if (result == 0) {
15873 +                               ep->driver_data = dev;
15874 +                               dev->in_ep = ep;
15875 +
15876 +                               if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
15877 +
15878 +                                       dev->in_ep = ep;
15879 +                                       continue;
15880 +                               }
15881 +
15882 +                               usb_ep_disable (ep);
15883 +                               result = -EIO;
15884 +                       }
15885 +               }
15886 +
15887 +       }
15888 +
15889 +       dev->config = number;
15890 +       return result;
15891 +}
15892 +
15893 +/*-------------------------------------------------------------------------*/
15894 +
15895 +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
15896 +{
15897 +       if (req->status || req->actual != req->length)
15898 +               DBG ((struct zero_dev *) ep->driver_data,
15899 +                               "setup complete --> %d, %d/%d\n",
15900 +                               req->status, req->actual, req->length);
15901 +}
15902 +
15903 +/*
15904 + * The setup() callback implements all the ep0 functionality that's
15905 + * not handled lower down, in hardware or the hardware driver (like
15906 + * device and endpoint feature flags, and their status).  It's all
15907 + * housekeeping for the gadget function we're implementing.  Most of
15908 + * the work is in config-specific setup.
15909 + */
15910 +static int
15911 +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
15912 +{
15913 +       struct zero_dev         *dev = get_gadget_data (gadget);
15914 +       struct usb_request      *req = dev->req;
15915 +       int                     value = -EOPNOTSUPP;
15916 +
15917 +       /* usually this stores reply data in the pre-allocated ep0 buffer,
15918 +        * but config change events will reconfigure hardware.
15919 +        */
15920 +       req->zero = 0;
15921 +       switch (ctrl->bRequest) {
15922 +
15923 +       case USB_REQ_GET_DESCRIPTOR:
15924 +
15925 +               switch (ctrl->wValue >> 8) {
15926 +
15927 +               case USB_DT_DEVICE:
15928 +                       value = min (ctrl->wLength, (u16) sizeof device_desc);
15929 +                       memcpy (req->buf, &device_desc, value);
15930 +                       break;
15931 +#ifdef CONFIG_USB_GADGET_DUALSPEED
15932 +               case USB_DT_DEVICE_QUALIFIER:
15933 +                       if (!gadget->is_dualspeed)
15934 +                               break;
15935 +                       value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
15936 +                       memcpy (req->buf, &dev_qualifier, value);
15937 +                       break;
15938 +
15939 +               case USB_DT_OTHER_SPEED_CONFIG:
15940 +                       if (!gadget->is_dualspeed)
15941 +                               break;
15942 +                       // FALLTHROUGH
15943 +#endif /* CONFIG_USB_GADGET_DUALSPEED */
15944 +               case USB_DT_CONFIG:
15945 +                       value = config_buf (gadget, req->buf,
15946 +                                       ctrl->wValue >> 8,
15947 +                                       ctrl->wValue & 0xff);
15948 +                       if (value >= 0)
15949 +                               value = min (ctrl->wLength, (u16) value);
15950 +                       break;
15951 +
15952 +               case USB_DT_STRING:
15953 +                       /* wIndex == language code.
15954 +                        * this driver only handles one language, you can
15955 +                        * add string tables for other languages, using
15956 +                        * any UTF-8 characters
15957 +                        */
15958 +                       value = usb_gadget_get_string (&stringtab,
15959 +                                       ctrl->wValue & 0xff, req->buf);
15960 +                       if (value >= 0) {
15961 +                               value = min (ctrl->wLength, (u16) value);
15962 +                       }
15963 +                       break;
15964 +               }
15965 +               break;
15966 +
15967 +       /* currently two configs, two speeds */
15968 +       case USB_REQ_SET_CONFIGURATION:
15969 +               if (ctrl->bRequestType != 0)
15970 +                       goto unknown;
15971 +
15972 +               spin_lock (&dev->lock);
15973 +               value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
15974 +               spin_unlock (&dev->lock);
15975 +               break;
15976 +       case USB_REQ_GET_CONFIGURATION:
15977 +               if (ctrl->bRequestType != USB_DIR_IN)
15978 +                       goto unknown;
15979 +               *(u8 *)req->buf = dev->config;
15980 +               value = min (ctrl->wLength, (u16) 1);
15981 +               break;
15982 +
15983 +       /* until we add altsetting support, or other interfaces,
15984 +        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
15985 +        * and already killed pending endpoint I/O.
15986 +        */
15987 +       case USB_REQ_SET_INTERFACE:
15988 +
15989 +               if (ctrl->bRequestType != USB_RECIP_INTERFACE)
15990 +                       goto unknown;
15991 +               spin_lock (&dev->lock);
15992 +               if (dev->config) {
15993 +                       u8              config = dev->config;
15994 +
15995 +                       /* resets interface configuration, forgets about
15996 +                        * previous transaction state (queued bufs, etc)
15997 +                        * and re-inits endpoint state (toggle etc)
15998 +                        * no response queued, just zero status == success.
15999 +                        * if we had more than one interface we couldn't
16000 +                        * use this "reset the config" shortcut.
16001 +                        */
16002 +                       zero_reset_config (dev);
16003 +                       zero_set_config (dev, config, GFP_ATOMIC);
16004 +                       value = 0;
16005 +               }
16006 +               spin_unlock (&dev->lock);
16007 +               break;
16008 +       case USB_REQ_GET_INTERFACE:
16009 +               if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
16010 +                       value = ctrl->wLength;
16011 +                       break;
16012 +               }
16013 +               else {
16014 +                       if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
16015 +                               goto unknown;
16016 +                       if (!dev->config)
16017 +                               break;
16018 +                       if (ctrl->wIndex != 0) {
16019 +                               value = -EDOM;
16020 +                               break;
16021 +                       }
16022 +                       *(u8 *)req->buf = 0;
16023 +                       value = min (ctrl->wLength, (u16) 1);
16024 +               }
16025 +               break;
16026 +
16027 +       /*
16028 +        * These are the same vendor-specific requests supported by
16029 +        * Intel's USB 2.0 compliance test devices.  We exceed that
16030 +        * device spec by allowing multiple-packet requests.
16031 +        */
16032 +       case 0x5b:      /* control WRITE test -- fill the buffer */
16033 +               if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
16034 +                       goto unknown;
16035 +               if (ctrl->wValue || ctrl->wIndex)
16036 +                       break;
16037 +               /* just read that many bytes into the buffer */
16038 +               if (ctrl->wLength > USB_BUFSIZ)
16039 +                       break;
16040 +               value = ctrl->wLength;
16041 +               break;
16042 +       case 0x5c:      /* control READ test -- return the buffer */
16043 +               if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
16044 +                       goto unknown;
16045 +               if (ctrl->wValue || ctrl->wIndex)
16046 +                       break;
16047 +               /* expect those bytes are still in the buffer; send back */
16048 +               if (ctrl->wLength > USB_BUFSIZ
16049 +                               || ctrl->wLength != req->length)
16050 +                       break;
16051 +               value = ctrl->wLength;
16052 +               break;
16053 +
16054 +       case 0x01: // SET_CUR
16055 +       case 0x02:
16056 +       case 0x03:
16057 +       case 0x04:
16058 +       case 0x05:
16059 +               value = ctrl->wLength;
16060 +               break;
16061 +       case 0x81:
16062 +               switch (ctrl->wValue) {
16063 +               case 0x0201:
16064 +               case 0x0202:
16065 +                       ((u8*)req->buf)[0] = 0x00;
16066 +                       ((u8*)req->buf)[1] = 0xe3;
16067 +                       break;
16068 +               case 0x0300:
16069 +               case 0x0500:
16070 +                       ((u8*)req->buf)[0] = 0x00;
16071 +                       break;
16072 +               }
16073 +               //((u8*)req->buf)[0] = 0x81;
16074 +               //((u8*)req->buf)[1] = 0x81;
16075 +               value = ctrl->wLength;
16076 +               break;
16077 +       case 0x82:
16078 +               switch (ctrl->wValue) {
16079 +               case 0x0201:
16080 +               case 0x0202:
16081 +                       ((u8*)req->buf)[0] = 0x00;
16082 +                       ((u8*)req->buf)[1] = 0xc3;
16083 +                       break;
16084 +               case 0x0300:
16085 +               case 0x0500:
16086 +                       ((u8*)req->buf)[0] = 0x00;
16087 +                       break;
16088 +               }
16089 +               //((u8*)req->buf)[0] = 0x82;
16090 +               //((u8*)req->buf)[1] = 0x82;
16091 +               value = ctrl->wLength;
16092 +               break;
16093 +       case 0x83:
16094 +               switch (ctrl->wValue) {
16095 +               case 0x0201:
16096 +               case 0x0202:
16097 +                       ((u8*)req->buf)[0] = 0x00;
16098 +                       ((u8*)req->buf)[1] = 0x00;
16099 +                       break;
16100 +               case 0x0300:
16101 +                       ((u8*)req->buf)[0] = 0x60;
16102 +                       break;
16103 +               case 0x0500:
16104 +                       ((u8*)req->buf)[0] = 0x18;
16105 +                       break;
16106 +               }
16107 +               //((u8*)req->buf)[0] = 0x83;
16108 +               //((u8*)req->buf)[1] = 0x83;
16109 +               value = ctrl->wLength;
16110 +               break;
16111 +       case 0x84:
16112 +               switch (ctrl->wValue) {
16113 +               case 0x0201:
16114 +               case 0x0202:
16115 +                       ((u8*)req->buf)[0] = 0x00;
16116 +                       ((u8*)req->buf)[1] = 0x01;
16117 +                       break;
16118 +               case 0x0300:
16119 +               case 0x0500:
16120 +                       ((u8*)req->buf)[0] = 0x08;
16121 +                       break;
16122 +               }
16123 +               //((u8*)req->buf)[0] = 0x84;
16124 +               //((u8*)req->buf)[1] = 0x84;
16125 +               value = ctrl->wLength;
16126 +               break;
16127 +       case 0x85:
16128 +               ((u8*)req->buf)[0] = 0x85;
16129 +               ((u8*)req->buf)[1] = 0x85;
16130 +               value = ctrl->wLength;
16131 +               break;
16132 +
16133 +
16134 +       default:
16135 +unknown:
16136 +               printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
16137 +                       ctrl->bRequestType, ctrl->bRequest,
16138 +                       ctrl->wValue, ctrl->wIndex, ctrl->wLength);
16139 +       }
16140 +
16141 +       /* respond with data transfer before status phase? */
16142 +       if (value >= 0) {
16143 +               req->length = value;
16144 +               req->zero = value < ctrl->wLength
16145 +                               && (value % gadget->ep0->maxpacket) == 0;
16146 +               value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
16147 +               if (value < 0) {
16148 +                       DBG (dev, "ep_queue < 0 --> %d\n", value);
16149 +                       req->status = 0;
16150 +                       zero_setup_complete (gadget->ep0, req);
16151 +               }
16152 +       }
16153 +
16154 +       /* device either stalls (value < 0) or reports success */
16155 +       return value;
16156 +}
16157 +
16158 +static void
16159 +zero_disconnect (struct usb_gadget *gadget)
16160 +{
16161 +       struct zero_dev         *dev = get_gadget_data (gadget);
16162 +       unsigned long           flags;
16163 +
16164 +       spin_lock_irqsave (&dev->lock, flags);
16165 +       zero_reset_config (dev);
16166 +
16167 +       /* a more significant application might have some non-usb
16168 +        * activities to quiesce here, saving resources like power
16169 +        * or pushing the notification up a network stack.
16170 +        */
16171 +       spin_unlock_irqrestore (&dev->lock, flags);
16172 +
16173 +       /* next we may get setup() calls to enumerate new connections;
16174 +        * or an unbind() during shutdown (including removing module).
16175 +        */
16176 +}
16177 +
16178 +static void
16179 +zero_autoresume (unsigned long _dev)
16180 +{
16181 +       struct zero_dev *dev = (struct zero_dev *) _dev;
16182 +       int             status;
16183 +
16184 +       /* normally the host would be woken up for something
16185 +        * more significant than just a timer firing...
16186 +        */
16187 +       if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
16188 +               status = usb_gadget_wakeup (dev->gadget);
16189 +               DBG (dev, "wakeup --> %d\n", status);
16190 +       }
16191 +}
16192 +
16193 +/*-------------------------------------------------------------------------*/
16194 +
16195 +static void
16196 +zero_unbind (struct usb_gadget *gadget)
16197 +{
16198 +       struct zero_dev         *dev = get_gadget_data (gadget);
16199 +
16200 +       DBG (dev, "unbind\n");
16201 +
16202 +       /* we've already been disconnected ... no i/o is active */
16203 +       if (dev->req)
16204 +               free_ep_req (gadget->ep0, dev->req);
16205 +       del_timer_sync (&dev->resume);
16206 +       kfree (dev);
16207 +       set_gadget_data (gadget, NULL);
16208 +}
16209 +
16210 +static int
16211 +zero_bind (struct usb_gadget *gadget)
16212 +{
16213 +       struct zero_dev         *dev;
16214 +       //struct usb_ep         *ep;
16215 +
16216 +       printk("binding\n");
16217 +       /*
16218 +        * DRIVER POLICY CHOICE:  you may want to do this differently.
16219 +        * One thing to avoid is reusing a bcdDevice revision code
16220 +        * with different host-visible configurations or behavior
16221 +        * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
16222 +        */
16223 +       //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
16224 +
16225 +
16226 +       /* ok, we made sense of the hardware ... */
16227 +       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
16228 +       if (!dev)
16229 +               return -ENOMEM;
16230 +       memset (dev, 0, sizeof *dev);
16231 +       spin_lock_init (&dev->lock);
16232 +       dev->gadget = gadget;
16233 +       set_gadget_data (gadget, dev);
16234 +
16235 +       /* preallocate control response and buffer */
16236 +       dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
16237 +       if (!dev->req)
16238 +               goto enomem;
16239 +       dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
16240 +                               &dev->req->dma, GFP_KERNEL);
16241 +       if (!dev->req->buf)
16242 +               goto enomem;
16243 +
16244 +       dev->req->complete = zero_setup_complete;
16245 +
16246 +       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
16247 +
16248 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16249 +       /* assume ep0 uses the same value for both speeds ... */
16250 +       dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
16251 +
16252 +       /* and that all endpoints are dual-speed */
16253 +       //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
16254 +       //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
16255 +#endif
16256 +
16257 +       usb_gadget_set_selfpowered (gadget);
16258 +
16259 +       init_timer (&dev->resume);
16260 +       dev->resume.function = zero_autoresume;
16261 +       dev->resume.data = (unsigned long) dev;
16262 +
16263 +       gadget->ep0->driver_data = dev;
16264 +
16265 +       INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
16266 +       INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
16267 +               EP_OUT_NAME, EP_IN_NAME);
16268 +
16269 +       snprintf (manufacturer, sizeof manufacturer,
16270 +               UTS_SYSNAME " " UTS_RELEASE " with %s",
16271 +               gadget->name);
16272 +
16273 +       return 0;
16274 +
16275 +enomem:
16276 +       zero_unbind (gadget);
16277 +       return -ENOMEM;
16278 +}
16279 +
16280 +/*-------------------------------------------------------------------------*/
16281 +
16282 +static void
16283 +zero_suspend (struct usb_gadget *gadget)
16284 +{
16285 +       struct zero_dev         *dev = get_gadget_data (gadget);
16286 +
16287 +       if (gadget->speed == USB_SPEED_UNKNOWN)
16288 +               return;
16289 +
16290 +       if (autoresume) {
16291 +               mod_timer (&dev->resume, jiffies + (HZ * autoresume));
16292 +               DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
16293 +       } else
16294 +               DBG (dev, "suspend\n");
16295 +}
16296 +
16297 +static void
16298 +zero_resume (struct usb_gadget *gadget)
16299 +{
16300 +       struct zero_dev         *dev = get_gadget_data (gadget);
16301 +
16302 +       DBG (dev, "resume\n");
16303 +       del_timer (&dev->resume);
16304 +}
16305 +
16306 +
16307 +/*-------------------------------------------------------------------------*/
16308 +
16309 +static struct usb_gadget_driver zero_driver = {
16310 +#ifdef CONFIG_USB_GADGET_DUALSPEED
16311 +       .speed          = USB_SPEED_HIGH,
16312 +#else
16313 +       .speed          = USB_SPEED_FULL,
16314 +#endif
16315 +       .function       = (char *) longname,
16316 +       .bind           = zero_bind,
16317 +       .unbind         = zero_unbind,
16318 +
16319 +       .setup          = zero_setup,
16320 +       .disconnect     = zero_disconnect,
16321 +
16322 +       .suspend        = zero_suspend,
16323 +       .resume         = zero_resume,
16324 +
16325 +       .driver         = {
16326 +               .name           = (char *) shortname,
16327 +               // .shutdown = ...
16328 +               // .suspend = ...
16329 +               // .resume = ...
16330 +       },
16331 +};
16332 +
16333 +MODULE_AUTHOR ("David Brownell");
16334 +MODULE_LICENSE ("Dual BSD/GPL");
16335 +
16336 +static struct proc_dir_entry *pdir, *pfile;
16337 +
16338 +static int isoc_read_data (char *page, char **start,
16339 +                          off_t off, int count,
16340 +                          int *eof, void *data)
16341 +{
16342 +       int i;
16343 +       static int c = 0;
16344 +       static int done = 0;
16345 +       static int s = 0;
16346 +
16347 +/*
16348 +       printk ("\ncount: %d\n", count);
16349 +       printk ("rbuf_start: %d\n", rbuf_start);
16350 +       printk ("rbuf_len: %d\n", rbuf_len);
16351 +       printk ("off: %d\n", off);
16352 +       printk ("start: %p\n\n", *start);
16353 +*/
16354 +       if (done) {
16355 +               c = 0;
16356 +               done = 0;
16357 +               *eof = 1;
16358 +               return 0;
16359 +       }
16360 +
16361 +       if (c == 0) {
16362 +               if (rbuf_len == RBUF_LEN)
16363 +                       s = rbuf_start;
16364 +               else s = 0;
16365 +       }
16366 +
16367 +       for (i=0; i<count && c<rbuf_len; i++, c++) {
16368 +               page[i] = rbuf[(c+s) % RBUF_LEN];
16369 +       }
16370 +       *start = page;
16371 +
16372 +       if (c >= rbuf_len) {
16373 +               *eof = 1;
16374 +               done = 1;
16375 +       }
16376 +
16377 +
16378 +       return i;
16379 +}
16380 +
16381 +static int __init init (void)
16382 +{
16383 +
16384 +       int retval = 0;
16385 +
16386 +       pdir = proc_mkdir("isoc_test", NULL);
16387 +       if(pdir == NULL) {
16388 +               retval = -ENOMEM;
16389 +               printk("Error creating dir\n");
16390 +               goto done;
16391 +       }
16392 +       pdir->owner = THIS_MODULE;
16393 +
16394 +       pfile = create_proc_read_entry("isoc_data",
16395 +                                      0444, pdir,
16396 +                                      isoc_read_data,
16397 +                                      NULL);
16398 +       if (pfile == NULL) {
16399 +               retval = -ENOMEM;
16400 +               printk("Error creating file\n");
16401 +               goto no_file;
16402 +       }
16403 +       pfile->owner = THIS_MODULE;
16404 +
16405 +       return usb_gadget_register_driver (&zero_driver);
16406 +
16407 + no_file:
16408 +       remove_proc_entry("isoc_data", NULL);
16409 + done:
16410 +       return retval;
16411 +}
16412 +module_init (init);
16413 +
16414 +static void __exit cleanup (void)
16415 +{
16416 +
16417 +       usb_gadget_unregister_driver (&zero_driver);
16418 +
16419 +       remove_proc_entry("isoc_data", pdir);
16420 +       remove_proc_entry("isoc_test", NULL);
16421 +}
16422 +module_exit (cleanup);
16423 --- /dev/null
16424 +++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
16425 @@ -0,0 +1,142 @@
16426 +/* ==========================================================================
16427 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16428 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16429 + * otherwise expressly agreed to in writing between Synopsys and you.
16430 + *
16431 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16432 + * any End User Software License Agreement or Agreement for Licensed Product
16433 + * with Synopsys or any supplement thereto. You are permitted to use and
16434 + * redistribute this Software in source and binary forms, with or without
16435 + * modification, provided that redistributions of source code must retain this
16436 + * notice. You may not view, use, disclose, copy or distribute this file or
16437 + * any information contained herein except pursuant to this license grant from
16438 + * Synopsys. If you do not agree with this notice, including the disclaimer
16439 + * below, then you are not authorized to use the Software.
16440 + *
16441 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16442 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16443 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16444 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16445 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16446 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16447 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16448 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16449 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16450 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16451 + * DAMAGE.
16452 + * ========================================================================== */
16453 +
16454 +#if !defined(__DWC_CFI_COMMON_H__)
16455 +#define __DWC_CFI_COMMON_H__
16456 +
16457 +//#include <linux/types.h>
16458 +
16459 +/**
16460 + * @file
16461 + *
16462 + * This file contains the CFI specific common constants, interfaces
16463 + * (functions and macros) and structures for Linux. No PCD specific
16464 + * data structure or definition is to be included in this file.
16465 + *
16466 + */
16467 +
16468 +/** This is a request for all Core Features */
16469 +#define VEN_CORE_GET_FEATURES          0xB1
16470 +
16471 +/** This is a request to get the value of a specific Core Feature */
16472 +#define VEN_CORE_GET_FEATURE           0xB2
16473 +
16474 +/** This command allows the host to set the value of a specific Core Feature */
16475 +#define VEN_CORE_SET_FEATURE           0xB3
16476 +
16477 +/** This command allows the host to set the default values of
16478 + * either all or any specific Core Feature
16479 + */
16480 +#define VEN_CORE_RESET_FEATURES                0xB4
16481 +
16482 +/** This command forces the PCD to write the deferred values of a Core Features */
16483 +#define VEN_CORE_ACTIVATE_FEATURES     0xB5
16484 +
16485 +/** This request reads a DWORD value from a register at the specified offset */
16486 +#define VEN_CORE_READ_REGISTER         0xB6
16487 +
16488 +/** This request writes a DWORD value into a register at the specified offset */
16489 +#define VEN_CORE_WRITE_REGISTER                0xB7
16490 +
16491 +/** This structure is the header of the Core Features dataset returned to
16492 + *  the Host
16493 + */
16494 +struct cfi_all_features_header {
16495 +/** The features header structure length is */
16496 +#define CFI_ALL_FEATURES_HDR_LEN               8
16497 +       /**
16498 +        * The total length of the features dataset returned to the Host
16499 +        */
16500 +       uint16_t wTotalLen;
16501 +
16502 +       /**
16503 +        * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
16504 +        * This field identifies the version of the CFI Specification with which
16505 +        * the device is compliant.
16506 +        */
16507 +       uint16_t wVersion;
16508 +
16509 +       /** The ID of the Core */
16510 +       uint16_t wCoreID;
16511 +#define CFI_CORE_ID_UDC                1
16512 +#define CFI_CORE_ID_OTG                2
16513 +#define CFI_CORE_ID_WUDEV      3
16514 +
16515 +       /** Number of features returned by VEN_CORE_GET_FEATURES request */
16516 +       uint16_t wNumFeatures;
16517 +} UPACKED;
16518 +
16519 +typedef struct cfi_all_features_header cfi_all_features_header_t;
16520 +
16521 +/** This structure is a header of the Core Feature descriptor dataset returned to
16522 + *  the Host after the VEN_CORE_GET_FEATURES request
16523 + */
16524 +struct cfi_feature_desc_header {
16525 +#define CFI_FEATURE_DESC_HDR_LEN       8
16526 +
16527 +       /** The feature ID */
16528 +       uint16_t wFeatureID;
16529 +
16530 +       /** Length of this feature descriptor in bytes - including the
16531 +        * length of the feature name string
16532 +        */
16533 +       uint16_t wLength;
16534 +
16535 +       /** The data length of this feature in bytes */
16536 +       uint16_t wDataLength;
16537 +
16538 +       /**
16539 +        * Attributes of this features
16540 +        * D0: Access rights
16541 +        * 0 - Read/Write
16542 +        * 1 - Read only
16543 +        */
16544 +       uint8_t bmAttributes;
16545 +#define CFI_FEATURE_ATTR_RO            1
16546 +#define CFI_FEATURE_ATTR_RW            0
16547 +
16548 +       /** Length of the feature name in bytes */
16549 +       uint8_t bNameLen;
16550 +
16551 +       /** The feature name buffer */
16552 +       //uint8_t *name;
16553 +} UPACKED;
16554 +
16555 +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
16556 +
16557 +/**
16558 + * This structure describes a NULL terminated string referenced by its id field.
16559 + * It is very similar to usb_string structure but has the id field type set to 16-bit.
16560 + */
16561 +struct cfi_string {
16562 +       uint16_t id;
16563 +       const uint8_t *s;
16564 +};
16565 +typedef struct cfi_string cfi_string_t;
16566 +
16567 +#endif
16568 --- /dev/null
16569 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
16570 @@ -0,0 +1,854 @@
16571 +/* ==========================================================================
16572 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
16573 + * $Revision: #12 $
16574 + * $Date: 2011/10/26 $
16575 + * $Change: 1873028 $
16576 + *
16577 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
16578 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
16579 + * otherwise expressly agreed to in writing between Synopsys and you.
16580 + *
16581 + * The Software IS NOT an item of Licensed Software or Licensed Product under
16582 + * any End User Software License Agreement or Agreement for Licensed Product
16583 + * with Synopsys or any supplement thereto. You are permitted to use and
16584 + * redistribute this Software in source and binary forms, with or without
16585 + * modification, provided that redistributions of source code must retain this
16586 + * notice. You may not view, use, disclose, copy or distribute this file or
16587 + * any information contained herein except pursuant to this license grant from
16588 + * Synopsys. If you do not agree with this notice, including the disclaimer
16589 + * below, then you are not authorized to use the Software.
16590 + *
16591 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
16592 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16593 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16594 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
16595 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16596 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16597 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
16598 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16599 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16600 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16601 + * DAMAGE.
16602 + * ========================================================================== */
16603 +
16604 +#include "dwc_os.h"
16605 +#include "dwc_otg_regs.h"
16606 +#include "dwc_otg_cil.h"
16607 +#include "dwc_otg_adp.h"
16608 +
16609 +/** @file
16610 + *
16611 + * This file contains the most of the Attach Detect Protocol implementation for
16612 + * the driver to support OTG Rev2.0.
16613 + *
16614 + */
16615 +
16616 +void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
16617 +{
16618 +       adpctl_data_t adpctl;
16619 +
16620 +       adpctl.d32 = value;
16621 +       adpctl.b.ar = 0x2;
16622 +
16623 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16624 +
16625 +       while (adpctl.b.ar) {
16626 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16627 +       }
16628 +
16629 +}
16630 +
16631 +/**
16632 + * Function is called to read ADP registers
16633 + */
16634 +uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
16635 +{
16636 +       adpctl_data_t adpctl;
16637 +
16638 +       adpctl.d32 = 0;
16639 +       adpctl.b.ar = 0x1;
16640 +
16641 +       DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
16642 +
16643 +       while (adpctl.b.ar) {
16644 +               adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
16645 +       }
16646 +
16647 +       return adpctl.d32;
16648 +}
16649 +
16650 +/**
16651 + * Function is called to read ADPCTL register and filter Write-clear bits
16652 + */
16653 +uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
16654 +{
16655 +       adpctl_data_t adpctl;
16656 +
16657 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16658 +       adpctl.b.adp_tmout_int = 0;
16659 +       adpctl.b.adp_prb_int = 0;
16660 +       adpctl.b.adp_tmout_int = 0;
16661 +
16662 +       return adpctl.d32;
16663 +}
16664 +
16665 +/**
16666 + * Function is called to write ADP registers
16667 + */
16668 +void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
16669 +                           uint32_t set)
16670 +{
16671 +       dwc_otg_adp_write_reg(core_if,
16672 +                             (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
16673 +}
16674 +
16675 +static void adp_sense_timeout(void *ptr)
16676 +{
16677 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16678 +       core_if->adp.sense_timer_started = 0;
16679 +       DWC_PRINTF("ADP SENSE TIMEOUT\n");
16680 +       if (core_if->adp_enable) {
16681 +               dwc_otg_adp_sense_stop(core_if);
16682 +               dwc_otg_adp_probe_start(core_if);
16683 +       }
16684 +}
16685 +
16686 +/**
16687 + * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
16688 + */
16689 +static void adp_vbuson_timeout(void *ptr)
16690 +{
16691 +       gpwrdn_data_t gpwrdn;
16692 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
16693 +       hprt0_data_t hprt0 = {.d32 = 0 };
16694 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
16695 +       DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
16696 +       if (core_if) {
16697 +               core_if->adp.vbuson_timer_started = 0;
16698 +               /* Turn off vbus */
16699 +               hprt0.b.prtpwr = 1;
16700 +               DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
16701 +               gpwrdn.d32 = 0;
16702 +
16703 +               /* Power off the core */
16704 +               if (core_if->power_down == 2) {
16705 +                       /* Enable Wakeup Logic */
16706 +//                      gpwrdn.b.wkupactiv = 1;
16707 +                       gpwrdn.b.pmuactv = 0;
16708 +                       gpwrdn.b.pwrdnrstn = 1;
16709 +                       gpwrdn.b.pwrdnclmp = 1;
16710 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16711 +                                        gpwrdn.d32);
16712 +
16713 +                       /* Suspend the Phy Clock */
16714 +                       pcgcctl.b.stoppclk = 1;
16715 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
16716 +
16717 +                       /* Switch on VDD */
16718 +//                      gpwrdn.b.wkupactiv = 1;
16719 +                       gpwrdn.b.pmuactv = 1;
16720 +                       gpwrdn.b.pwrdnrstn = 1;
16721 +                       gpwrdn.b.pwrdnclmp = 1;
16722 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
16723 +                                        gpwrdn.d32);
16724 +               } else {
16725 +                       /* Enable Power Down Logic */
16726 +                       gpwrdn.b.pmuintsel = 1;
16727 +                       gpwrdn.b.pmuactv = 1;
16728 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16729 +               }
16730 +
16731 +               /* Power off the core */
16732 +               if (core_if->power_down == 2) {
16733 +                       gpwrdn.d32 = 0;
16734 +                       gpwrdn.b.pwrdnswtch = 1;
16735 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
16736 +                                        gpwrdn.d32, 0);
16737 +               }
16738 +
16739 +               /* Unmask SRP detected interrupt from Power Down Logic */
16740 +               gpwrdn.d32 = 0;
16741 +               gpwrdn.b.srp_det_msk = 1;
16742 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16743 +
16744 +               dwc_otg_adp_probe_start(core_if);
16745 +               dwc_otg_dump_global_registers(core_if);
16746 +               dwc_otg_dump_host_registers(core_if);
16747 +       }
16748 +
16749 +}
16750 +
16751 +/**
16752 + * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
16753 + * not asserted within 1.1 seconds.
16754 + *
16755 + * @param core_if the pointer to core_if strucure.
16756 + */
16757 +void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
16758 +{
16759 +       core_if->adp.vbuson_timer_started = 1;
16760 +       if (core_if->adp.vbuson_timer)
16761 +       {
16762 +               DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
16763 +               /* 1.1 secs + 60ms necessary for cil_hcd_start*/
16764 +               DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
16765 +       } else {
16766 +               DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
16767 +       }
16768 +}
16769 +
16770 +#if 0
16771 +/**
16772 + * Masks all DWC OTG core interrupts
16773 + *
16774 + */
16775 +static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
16776 +{
16777 +       int i;
16778 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
16779 +
16780 +       /* Mask Host Interrupts */
16781 +
16782 +       /* Clear and disable HCINTs */
16783 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
16784 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
16785 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
16786 +
16787 +       }
16788 +
16789 +       /* Clear and disable HAINT */
16790 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
16791 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
16792 +
16793 +       /* Mask Device Interrupts */
16794 +       if (!core_if->multiproc_int_enable) {
16795 +               /* Clear and disable IN Endpoint interrupts */
16796 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
16797 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
16798 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16799 +                                       diepint, 0xFFFFFFFF);
16800 +               }
16801 +
16802 +               /* Clear and disable OUT Endpoint interrupts */
16803 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
16804 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
16805 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16806 +                                       doepint, 0xFFFFFFFF);
16807 +               }
16808 +
16809 +               /* Clear and disable DAINT */
16810 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
16811 +                               0xFFFFFFFF);
16812 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
16813 +       } else {
16814 +               for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
16815 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16816 +                                       diepeachintmsk[i], 0);
16817 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
16818 +                                       diepint, 0xFFFFFFFF);
16819 +               }
16820 +
16821 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
16822 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
16823 +                                       doepeachintmsk[i], 0);
16824 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
16825 +                                       doepint, 0xFFFFFFFF);
16826 +               }
16827 +
16828 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
16829 +                               0);
16830 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
16831 +                               0xFFFFFFFF);
16832 +
16833 +       }
16834 +
16835 +       /* Disable interrupts */
16836 +       ahbcfg.b.glblintrmsk = 1;
16837 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
16838 +
16839 +       /* Disable all interrupts. */
16840 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
16841 +
16842 +       /* Clear any pending interrupts */
16843 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
16844 +
16845 +       /* Clear any pending OTG Interrupts */
16846 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
16847 +}
16848 +
16849 +/**
16850 + * Unmask Port Connection Detected interrupt
16851 + *
16852 + */
16853 +static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
16854 +{
16855 +       gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
16856 +
16857 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
16858 +}
16859 +#endif
16860 +
16861 +/**
16862 + * Starts the ADP Probing
16863 + *
16864 + * @param core_if the pointer to core_if structure.
16865 + */
16866 +uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
16867 +{
16868 +
16869 +       adpctl_data_t adpctl = {.d32 = 0};
16870 +       gpwrdn_data_t gpwrdn;
16871 +#if 0
16872 +       adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
16873 +                                                               .b.adp_sns_int = 1, b.adp_tmout_int};
16874 +#endif
16875 +       dwc_otg_disable_global_interrupts(core_if);
16876 +       DWC_PRINTF("ADP Probe Start\n");
16877 +       core_if->adp.probe_enabled = 1;
16878 +
16879 +       adpctl.b.adpres = 1;
16880 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16881 +
16882 +       while (adpctl.b.adpres) {
16883 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16884 +       }
16885 +
16886 +       adpctl.d32 = 0;
16887 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
16888 +
16889 +       /* In Host mode unmask SRP detected interrupt */
16890 +       gpwrdn.d32 = 0;
16891 +       gpwrdn.b.sts_chngint_msk = 1;
16892 +       if (!gpwrdn.b.idsts) {
16893 +               gpwrdn.b.srp_det_msk = 1;
16894 +       }
16895 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
16896 +
16897 +       adpctl.b.adp_tmout_int_msk = 1;
16898 +       adpctl.b.adp_prb_int_msk = 1;
16899 +       adpctl.b.prb_dschg = 1;
16900 +       adpctl.b.prb_delta = 1;
16901 +       adpctl.b.prb_per = 1;
16902 +       adpctl.b.adpen = 1;
16903 +       adpctl.b.enaprb = 1;
16904 +
16905 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16906 +       DWC_PRINTF("ADP Probe Finish\n");
16907 +       return 0;
16908 +}
16909 +
16910 +/**
16911 + * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
16912 + * within 3 seconds.
16913 + *
16914 + * @param core_if the pointer to core_if strucure.
16915 + */
16916 +void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
16917 +{
16918 +       core_if->adp.sense_timer_started = 1;
16919 +       DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
16920 +}
16921 +
16922 +/**
16923 + * Starts the ADP Sense
16924 + *
16925 + * @param core_if the pointer to core_if strucure.
16926 + */
16927 +uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
16928 +{
16929 +       adpctl_data_t adpctl;
16930 +
16931 +       DWC_PRINTF("ADP Sense Start\n");
16932 +
16933 +       /* Unmask ADP sense interrupt and mask all other from the core */
16934 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16935 +       adpctl.b.adp_sns_int_msk = 1;
16936 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16937 +       dwc_otg_disable_global_interrupts(core_if); // vahrama
16938 +
16939 +       /* Set ADP reset bit*/
16940 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16941 +       adpctl.b.adpres = 1;
16942 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16943 +
16944 +       while (adpctl.b.adpres) {
16945 +               adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16946 +       }
16947 +
16948 +       adpctl.b.adpres = 0;
16949 +       adpctl.b.adpen = 1;
16950 +       adpctl.b.enasns = 1;
16951 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16952 +
16953 +       dwc_otg_adp_sense_timer_start(core_if);
16954 +
16955 +       return 0;
16956 +}
16957 +
16958 +/**
16959 + * Stops the ADP Probing
16960 + *
16961 + * @param core_if the pointer to core_if strucure.
16962 + */
16963 +uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
16964 +{
16965 +
16966 +       adpctl_data_t adpctl;
16967 +       DWC_PRINTF("Stop ADP probe\n");
16968 +       core_if->adp.probe_enabled = 0;
16969 +       core_if->adp.probe_counter = 0;
16970 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
16971 +
16972 +       adpctl.b.adpen = 0;
16973 +       adpctl.b.adp_prb_int = 1;
16974 +       adpctl.b.adp_tmout_int = 1;
16975 +       adpctl.b.adp_sns_int = 1;
16976 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16977 +
16978 +       return 0;
16979 +}
16980 +
16981 +/**
16982 + * Stops the ADP Sensing
16983 + *
16984 + * @param core_if the pointer to core_if strucure.
16985 + */
16986 +uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
16987 +{
16988 +       adpctl_data_t adpctl;
16989 +
16990 +       core_if->adp.sense_enabled = 0;
16991 +
16992 +       adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
16993 +       adpctl.b.enasns = 0;
16994 +       adpctl.b.adp_sns_int = 1;
16995 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
16996 +
16997 +       return 0;
16998 +}
16999 +
17000 +/**
17001 + * Called to turn on the VBUS after initial ADP probe in host mode.
17002 + * If port power was already enabled in cil_hcd_start function then
17003 + * only schedule a timer.
17004 + *
17005 + * @param core_if the pointer to core_if structure.
17006 + */
17007 +void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
17008 +{
17009 +       hprt0_data_t hprt0 = {.d32 = 0 };
17010 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
17011 +       DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
17012 +
17013 +       if (hprt0.b.prtpwr == 0) {
17014 +               hprt0.b.prtpwr = 1;
17015 +               //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17016 +       }
17017 +
17018 +       dwc_otg_adp_vbuson_timer_start(core_if);
17019 +}
17020 +
17021 +/**
17022 + * Called right after driver is loaded
17023 + * to perform initial actions for ADP
17024 + *
17025 + * @param core_if the pointer to core_if structure.
17026 + * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
17027 + */
17028 +void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
17029 +{
17030 +       gpwrdn_data_t gpwrdn;
17031 +
17032 +       DWC_PRINTF("ADP Initial Start\n");
17033 +       core_if->adp.adp_started = 1;
17034 +
17035 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17036 +       dwc_otg_disable_global_interrupts(core_if);
17037 +       if (is_host) {
17038 +               DWC_PRINTF("HOST MODE\n");
17039 +               /* Enable Power Down Logic Interrupt*/
17040 +               gpwrdn.d32 = 0;
17041 +               gpwrdn.b.pmuintsel = 1;
17042 +               gpwrdn.b.pmuactv = 1;
17043 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17044 +               /* Initialize first ADP probe to obtain Ramp Time value */
17045 +               core_if->adp.initial_probe = 1;
17046 +               dwc_otg_adp_probe_start(core_if);
17047 +       } else {
17048 +               gotgctl_data_t gotgctl;
17049 +               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17050 +               DWC_PRINTF("DEVICE MODE\n");
17051 +               if (gotgctl.b.bsesvld == 0) {
17052 +                       /* Enable Power Down Logic Interrupt*/
17053 +                       gpwrdn.d32 = 0;
17054 +                       DWC_PRINTF("VBUS is not valid - start ADP probe\n");
17055 +                       gpwrdn.b.pmuintsel = 1;
17056 +                       gpwrdn.b.pmuactv = 1;
17057 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
17058 +                       core_if->adp.initial_probe = 1;
17059 +                       dwc_otg_adp_probe_start(core_if);
17060 +               } else {
17061 +                       DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
17062 +                       core_if->op_state = B_PERIPHERAL;
17063 +                       dwc_otg_core_init(core_if);
17064 +                       dwc_otg_enable_global_interrupts(core_if);
17065 +                       cil_pcd_start(core_if);
17066 +                       dwc_otg_dump_global_registers(core_if);
17067 +                       dwc_otg_dump_dev_registers(core_if);
17068 +               }
17069 +       }
17070 +}
17071 +
17072 +void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
17073 +{
17074 +       core_if->adp.adp_started = 0;
17075 +       core_if->adp.initial_probe = 0;
17076 +       core_if->adp.probe_timer_values[0] = -1;
17077 +       core_if->adp.probe_timer_values[1] = -1;
17078 +       core_if->adp.probe_enabled = 0;
17079 +       core_if->adp.sense_enabled = 0;
17080 +       core_if->adp.sense_timer_started = 0;
17081 +       core_if->adp.vbuson_timer_started = 0;
17082 +       core_if->adp.probe_counter = 0;
17083 +       core_if->adp.gpwrdn = 0;
17084 +       core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
17085 +       /* Initialize timers */
17086 +       core_if->adp.sense_timer =
17087 +           DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
17088 +       core_if->adp.vbuson_timer =
17089 +           DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
17090 +       if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
17091 +       {
17092 +               DWC_ERROR("Could not allocate memory for ADP timers\n");
17093 +       }
17094 +}
17095 +
17096 +void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
17097 +{
17098 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
17099 +       gpwrdn.b.pmuintsel = 1;
17100 +       gpwrdn.b.pmuactv = 1;
17101 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17102 +
17103 +       if (core_if->adp.probe_enabled)
17104 +               dwc_otg_adp_probe_stop(core_if);
17105 +       if (core_if->adp.sense_enabled)
17106 +               dwc_otg_adp_sense_stop(core_if);
17107 +       if (core_if->adp.sense_timer_started)
17108 +               DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17109 +       if (core_if->adp.vbuson_timer_started)
17110 +               DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
17111 +       DWC_TIMER_FREE(core_if->adp.sense_timer);
17112 +       DWC_TIMER_FREE(core_if->adp.vbuson_timer);
17113 +}
17114 +
17115 +/////////////////////////////////////////////////////////////////////
17116 +////////////// ADP Interrupt Handlers ///////////////////////////////
17117 +/////////////////////////////////////////////////////////////////////
17118 +/**
17119 + * This function sets Ramp Timer values
17120 + */
17121 +static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
17122 +{
17123 +       if (core_if->adp.probe_timer_values[0] == -1) {
17124 +               core_if->adp.probe_timer_values[0] = val;
17125 +               core_if->adp.probe_timer_values[1] = -1;
17126 +               return 1;
17127 +       } else {
17128 +               core_if->adp.probe_timer_values[1] =
17129 +                   core_if->adp.probe_timer_values[0];
17130 +               core_if->adp.probe_timer_values[0] = val;
17131 +               return 0;
17132 +       }
17133 +}
17134 +
17135 +/**
17136 + * This function compares Ramp Timer values
17137 + */
17138 +static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
17139 +{
17140 +       uint32_t diff;
17141 +       if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
17142 +                       diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
17143 +       else
17144 +                       diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];
17145 +       if(diff < 2) {
17146 +               return 0;
17147 +       } else {
17148 +               return 1;
17149 +       }
17150 +}
17151 +
17152 +/**
17153 + * This function handles ADP Probe Interrupts
17154 + */
17155 +static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
17156 +                                                uint32_t val)
17157 +{
17158 +       adpctl_data_t adpctl = {.d32 = 0 };
17159 +       gpwrdn_data_t gpwrdn, temp;
17160 +       adpctl.d32 = val;
17161 +
17162 +       temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17163 +       core_if->adp.probe_counter++;
17164 +       core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17165 +       if (adpctl.b.rtim == 0 && !temp.b.idsts){
17166 +               DWC_PRINTF("RTIM value is 0\n");
17167 +               goto exit;
17168 +       }
17169 +       if (set_timer_value(core_if, adpctl.b.rtim) &&
17170 +           core_if->adp.initial_probe) {
17171 +               core_if->adp.initial_probe = 0;
17172 +               dwc_otg_adp_probe_stop(core_if);
17173 +               gpwrdn.d32 = 0;
17174 +               gpwrdn.b.pmuactv = 1;
17175 +               gpwrdn.b.pmuintsel = 1;
17176 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17177 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
17178 +
17179 +               /* check which value is for device mode and which for Host mode */
17180 +               if (!temp.b.idsts) {    /* considered host mode value is 0 */
17181 +                       /*
17182 +                        * Turn on VBUS after initial ADP probe.
17183 +                        */
17184 +                       core_if->op_state = A_HOST;
17185 +                       dwc_otg_enable_global_interrupts(core_if);
17186 +                       DWC_SPINUNLOCK(core_if->lock);
17187 +                       cil_hcd_start(core_if);
17188 +                       dwc_otg_adp_turnon_vbus(core_if);
17189 +                       DWC_SPINLOCK(core_if->lock);
17190 +               } else {
17191 +                       /*
17192 +                        * Initiate SRP after initial ADP probe.
17193 +                        */
17194 +                       dwc_otg_enable_global_interrupts(core_if);
17195 +                       dwc_otg_initiate_srp(core_if);
17196 +               }
17197 +       } else if (core_if->adp.probe_counter > 2){
17198 +               gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17199 +               if (compare_timer_values(core_if)) {
17200 +                       DWC_PRINTF("Difference in timer values !!! \n");
17201 +//                      core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
17202 +                       dwc_otg_adp_probe_stop(core_if);
17203 +
17204 +                       /* Power on the core */
17205 +                       if (core_if->power_down == 2) {
17206 +                               gpwrdn.b.pwrdnswtch = 1;
17207 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17208 +                                                gpwrdn, 0, gpwrdn.d32);
17209 +                       }
17210 +
17211 +                       /* check which value is for device mode and which for Host mode */
17212 +                       if (!temp.b.idsts) {    /* considered host mode value is 0 */
17213 +                               /* Disable Interrupt from Power Down Logic */
17214 +                               gpwrdn.d32 = 0;
17215 +                               gpwrdn.b.pmuintsel = 1;
17216 +                               gpwrdn.b.pmuactv = 1;
17217 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17218 +                                                gpwrdn, gpwrdn.d32, 0);
17219 +
17220 +                               /*
17221 +                                * Initialize the Core for Host mode.
17222 +                                */
17223 +                               core_if->op_state = A_HOST;
17224 +                               dwc_otg_core_init(core_if);
17225 +                               dwc_otg_enable_global_interrupts(core_if);
17226 +                               cil_hcd_start(core_if);
17227 +                       } else {
17228 +                               gotgctl_data_t gotgctl;
17229 +                               /* Mask SRP detected interrupt from Power Down Logic */
17230 +                               gpwrdn.d32 = 0;
17231 +                               gpwrdn.b.srp_det_msk = 1;
17232 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17233 +                                                gpwrdn, gpwrdn.d32, 0);
17234 +
17235 +                               /* Disable Power Down Logic */
17236 +                               gpwrdn.d32 = 0;
17237 +                               gpwrdn.b.pmuintsel = 1;
17238 +                               gpwrdn.b.pmuactv = 1;
17239 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17240 +                                                gpwrdn, gpwrdn.d32, 0);
17241 +
17242 +                               /*
17243 +                                * Initialize the Core for Device mode.
17244 +                                */
17245 +                               core_if->op_state = B_PERIPHERAL;
17246 +                               dwc_otg_core_init(core_if);
17247 +                               dwc_otg_enable_global_interrupts(core_if);
17248 +                               cil_pcd_start(core_if);
17249 +
17250 +                               gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
17251 +                               if (!gotgctl.b.bsesvld) {
17252 +                                       dwc_otg_initiate_srp(core_if);
17253 +                               }
17254 +                       }
17255 +               }
17256 +               if (core_if->power_down == 2) {
17257 +                       if (gpwrdn.b.bsessvld) {
17258 +                               /* Mask SRP detected interrupt from Power Down Logic */
17259 +                               gpwrdn.d32 = 0;
17260 +                               gpwrdn.b.srp_det_msk = 1;
17261 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17262 +
17263 +                               /* Disable Power Down Logic */
17264 +                               gpwrdn.d32 = 0;
17265 +                               gpwrdn.b.pmuactv = 1;
17266 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
17267 +
17268 +                               /*
17269 +                                * Initialize the Core for Device mode.
17270 +                                */
17271 +                               core_if->op_state = B_PERIPHERAL;
17272 +                               dwc_otg_core_init(core_if);
17273 +                               dwc_otg_enable_global_interrupts(core_if);
17274 +                               cil_pcd_start(core_if);
17275 +                       }
17276 +               }
17277 +       }
17278 +exit:
17279 +       /* Clear interrupt */
17280 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17281 +       adpctl.b.adp_prb_int = 1;
17282 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17283 +
17284 +       return 0;
17285 +}
17286 +
17287 +/**
17288 + * This function hadles ADP Sense Interrupt
17289 + */
17290 +static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
17291 +{
17292 +       adpctl_data_t adpctl;
17293 +       /* Stop ADP Sense timer */
17294 +       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
17295 +
17296 +       /* Restart ADP Sense timer */
17297 +       dwc_otg_adp_sense_timer_start(core_if);
17298 +
17299 +       /* Clear interrupt */
17300 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17301 +       adpctl.b.adp_sns_int = 1;
17302 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17303 +
17304 +       return 0;
17305 +}
17306 +
17307 +/**
17308 + * This function handles ADP Probe Interrupts
17309 + */
17310 +static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
17311 +                                                uint32_t val)
17312 +{
17313 +       adpctl_data_t adpctl = {.d32 = 0 };
17314 +       adpctl.d32 = val;
17315 +       set_timer_value(core_if, adpctl.b.rtim);
17316 +
17317 +       /* Clear interrupt */
17318 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17319 +       adpctl.b.adp_tmout_int = 1;
17320 +       dwc_otg_adp_write_reg(core_if, adpctl.d32);
17321 +
17322 +       return 0;
17323 +}
17324 +
17325 +/**
17326 + * ADP Interrupt handler.
17327 + *
17328 + */
17329 +int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
17330 +{
17331 +       int retval = 0;
17332 +       adpctl_data_t adpctl = {.d32 = 0};
17333 +
17334 +       adpctl.d32 = dwc_otg_adp_read_reg(core_if);
17335 +       DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
17336 +
17337 +       if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
17338 +               DWC_PRINTF("ADP Sense interrupt\n");
17339 +               retval |= dwc_otg_adp_handle_sns_intr(core_if);
17340 +       }
17341 +       if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
17342 +               DWC_PRINTF("ADP timeout interrupt\n");
17343 +               retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
17344 +       }
17345 +       if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
17346 +               DWC_PRINTF("ADP Probe interrupt\n");
17347 +               adpctl.b.adp_prb_int = 1;
17348 +               retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
17349 +       }
17350 +
17351 +//     dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
17352 +       //dwc_otg_adp_write_reg(core_if, adpctl.d32);
17353 +       DWC_PRINTF("RETURN FROM ADP ISR\n");
17354 +
17355 +       return retval;
17356 +}
17357 +
17358 +/**
17359 + *
17360 + * @param core_if Programming view of DWC_otg controller.
17361 + */
17362 +int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
17363 +{
17364 +
17365 +#ifndef DWC_HOST_ONLY
17366 +       hprt0_data_t hprt0;
17367 +       gpwrdn_data_t gpwrdn;
17368 +       DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
17369 +
17370 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
17371 +       /* check which value is for device mode and which for Host mode */
17372 +       if (!gpwrdn.b.idsts) {  /* considered host mode value is 0 */
17373 +               DWC_PRINTF("SRP: Host mode\n");
17374 +
17375 +               if (core_if->adp_enable) {
17376 +                       dwc_otg_adp_probe_stop(core_if);
17377 +
17378 +                       /* Power on the core */
17379 +                       if (core_if->power_down == 2) {
17380 +                               gpwrdn.b.pwrdnswtch = 1;
17381 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17382 +                                                gpwrdn, 0, gpwrdn.d32);
17383 +                       }
17384 +
17385 +                       core_if->op_state = A_HOST;
17386 +                       dwc_otg_core_init(core_if);
17387 +                       dwc_otg_enable_global_interrupts(core_if);
17388 +                       cil_hcd_start(core_if);
17389 +               }
17390 +
17391 +               /* Turn on the port power bit. */
17392 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
17393 +               hprt0.b.prtpwr = 1;
17394 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
17395 +
17396 +               /* Start the Connection timer. So a message can be displayed
17397 +                * if connect does not occur within 10 seconds. */
17398 +               cil_hcd_session_start(core_if);
17399 +       } else {
17400 +               DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
17401 +               if (core_if->adp_enable) {
17402 +                       dwc_otg_adp_probe_stop(core_if);
17403 +
17404 +                       /* Power on the core */
17405 +                       if (core_if->power_down == 2) {
17406 +                               gpwrdn.b.pwrdnswtch = 1;
17407 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
17408 +                                                gpwrdn, 0, gpwrdn.d32);
17409 +                       }
17410 +
17411 +                       gpwrdn.d32 = 0;
17412 +                       gpwrdn.b.pmuactv = 0;
17413 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
17414 +                                        gpwrdn.d32);
17415 +
17416 +                       core_if->op_state = B_PERIPHERAL;
17417 +                       dwc_otg_core_init(core_if);
17418 +                       dwc_otg_enable_global_interrupts(core_if);
17419 +                       cil_pcd_start(core_if);
17420 +               }
17421 +       }
17422 +#endif
17423 +       return 1;
17424 +}
17425 --- /dev/null
17426 +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
17427 @@ -0,0 +1,80 @@
17428 +/* ==========================================================================
17429 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
17430 + * $Revision: #7 $
17431 + * $Date: 2011/10/24 $
17432 + * $Change: 1871159 $
17433 + *
17434 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17435 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17436 + * otherwise expressly agreed to in writing between Synopsys and you.
17437 + *
17438 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17439 + * any End User Software License Agreement or Agreement for Licensed Product
17440 + * with Synopsys or any supplement thereto. You are permitted to use and
17441 + * redistribute this Software in source and binary forms, with or without
17442 + * modification, provided that redistributions of source code must retain this
17443 + * notice. You may not view, use, disclose, copy or distribute this file or
17444 + * any information contained herein except pursuant to this license grant from
17445 + * Synopsys. If you do not agree with this notice, including the disclaimer
17446 + * below, then you are not authorized to use the Software.
17447 + *
17448 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17449 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17450 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17451 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17452 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17453 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17454 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17455 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17456 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17457 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17458 + * DAMAGE.
17459 + * ========================================================================== */
17460 +
17461 +#ifndef __DWC_OTG_ADP_H__
17462 +#define __DWC_OTG_ADP_H__
17463 +
17464 +/**
17465 + * @file
17466 + *
17467 + * This file contains the Attach Detect Protocol interfaces and defines
17468 + * (functions) and structures for Linux.
17469 + *
17470 + */
17471 +
17472 +#define DWC_OTG_ADP_UNATTACHED 0
17473 +#define DWC_OTG_ADP_ATTACHED   1
17474 +#define DWC_OTG_ADP_UNKOWN     2
17475 +
17476 +typedef struct dwc_otg_adp {
17477 +       uint32_t adp_started;
17478 +       uint32_t initial_probe;
17479 +       int32_t probe_timer_values[2];
17480 +       uint32_t probe_enabled;
17481 +       uint32_t sense_enabled;
17482 +       dwc_timer_t *sense_timer;
17483 +       uint32_t sense_timer_started;
17484 +       dwc_timer_t *vbuson_timer;
17485 +       uint32_t vbuson_timer_started;
17486 +       uint32_t attached;
17487 +       uint32_t probe_counter;
17488 +       uint32_t gpwrdn;
17489 +} dwc_otg_adp_t;
17490 +
17491 +/**
17492 + * Attach Detect Protocol functions
17493 + */
17494 +
17495 +extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);
17496 +extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);
17497 +extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);
17498 +extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
17499 +extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
17500 +extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
17501 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
17502 +extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
17503 +extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
17504 +extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
17505 +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
17506 +
17507 +#endif //__DWC_OTG_ADP_H__
17508 --- /dev/null
17509 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
17510 @@ -0,0 +1,1210 @@
17511 +/* ==========================================================================
17512 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
17513 + * $Revision: #44 $
17514 + * $Date: 2010/11/29 $
17515 + * $Change: 1636033 $
17516 + *
17517 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
17518 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
17519 + * otherwise expressly agreed to in writing between Synopsys and you.
17520 + *
17521 + * The Software IS NOT an item of Licensed Software or Licensed Product under
17522 + * any End User Software License Agreement or Agreement for Licensed Product
17523 + * with Synopsys or any supplement thereto. You are permitted to use and
17524 + * redistribute this Software in source and binary forms, with or without
17525 + * modification, provided that redistributions of source code must retain this
17526 + * notice. You may not view, use, disclose, copy or distribute this file or
17527 + * any information contained herein except pursuant to this license grant from
17528 + * Synopsys. If you do not agree with this notice, including the disclaimer
17529 + * below, then you are not authorized to use the Software.
17530 + *
17531 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
17532 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17533 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17534 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
17535 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17536 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17537 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17538 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17539 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17540 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17541 + * DAMAGE.
17542 + * ========================================================================== */
17543 +
17544 +/** @file
17545 + *
17546 + * The diagnostic interface will provide access to the controller for
17547 + * bringing up the hardware and testing.  The Linux driver attributes
17548 + * feature will be used to provide the Linux Diagnostic
17549 + * Interface. These attributes are accessed through sysfs.
17550 + */
17551 +
17552 +/** @page "Linux Module Attributes"
17553 + *
17554 + * The Linux module attributes feature is used to provide the Linux
17555 + * Diagnostic Interface.  These attributes are accessed through sysfs.
17556 + * The diagnostic interface will provide access to the controller for
17557 + * bringing up the hardware and testing.
17558 +
17559 + The following table shows the attributes.
17560 + <table>
17561 + <tr>
17562 + <td><b> Name</b></td>
17563 + <td><b> Description</b></td>
17564 + <td><b> Access</b></td>
17565 + </tr>
17566 +
17567 + <tr>
17568 + <td> mode </td>
17569 + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
17570 + <td> Read</td>
17571 + </tr>
17572 +
17573 + <tr>
17574 + <td> hnpcapable </td>
17575 + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
17576 + Read returns the current value.</td>
17577 + <td> Read/Write</td>
17578 + </tr>
17579 +
17580 + <tr>
17581 + <td> srpcapable </td>
17582 + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
17583 + Read returns the current value.</td>
17584 + <td> Read/Write</td>
17585 + </tr>
17586 +
17587 + <tr>
17588 + <td> hsic_connect </td>
17589 + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
17590 + Read returns the current value.</td>
17591 + <td> Read/Write</td>
17592 + </tr>
17593 +
17594 + <tr>
17595 + <td> inv_sel_hsic </td>
17596 + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
17597 + Read returns the current value.</td>
17598 + <td> Read/Write</td>
17599 + </tr>
17600 +
17601 + <tr>
17602 + <td> hnp </td>
17603 + <td> Initiates the Host Negotiation Protocol.  Read returns the status.</td>
17604 + <td> Read/Write</td>
17605 + </tr>
17606 +
17607 + <tr>
17608 + <td> srp </td>
17609 + <td> Initiates the Session Request Protocol.  Read returns the status.</td>
17610 + <td> Read/Write</td>
17611 + </tr>
17612 +
17613 + <tr>
17614 + <td> buspower </td>
17615 + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
17616 + <td> Read/Write</td>
17617 + </tr>
17618 +
17619 + <tr>
17620 + <td> bussuspend </td>
17621 + <td> Suspends the USB bus.</td>
17622 + <td> Read/Write</td>
17623 + </tr>
17624 +
17625 + <tr>
17626 + <td> busconnected </td>
17627 + <td> Gets the connection status of the bus</td>
17628 + <td> Read</td>
17629 + </tr>
17630 +
17631 + <tr>
17632 + <td> gotgctl </td>
17633 + <td> Gets or sets the Core Control Status Register.</td>
17634 + <td> Read/Write</td>
17635 + </tr>
17636 +
17637 + <tr>
17638 + <td> gusbcfg </td>
17639 + <td> Gets or sets the Core USB Configuration Register</td>
17640 + <td> Read/Write</td>
17641 + </tr>
17642 +
17643 + <tr>
17644 + <td> grxfsiz </td>
17645 + <td> Gets or sets the Receive FIFO Size Register</td>
17646 + <td> Read/Write</td>
17647 + </tr>
17648 +
17649 + <tr>
17650 + <td> gnptxfsiz </td>
17651 + <td> Gets or sets the non-periodic Transmit Size Register</td>
17652 + <td> Read/Write</td>
17653 + </tr>
17654 +
17655 + <tr>
17656 + <td> gpvndctl </td>
17657 + <td> Gets or sets the PHY Vendor Control Register</td>
17658 + <td> Read/Write</td>
17659 + </tr>
17660 +
17661 + <tr>
17662 + <td> ggpio </td>
17663 + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
17664 + or sets the upper 16 bits.</td>
17665 + <td> Read/Write</td>
17666 + </tr>
17667 +
17668 + <tr>
17669 + <td> guid </td>
17670 + <td> Gets or sets the value of the User ID Register</td>
17671 + <td> Read/Write</td>
17672 + </tr>
17673 +
17674 + <tr>
17675 + <td> gsnpsid </td>
17676 + <td> Gets the value of the Synopsys ID Regester</td>
17677 + <td> Read</td>
17678 + </tr>
17679 +
17680 + <tr>
17681 + <td> devspeed </td>
17682 + <td> Gets or sets the device speed setting in the DCFG register</td>
17683 + <td> Read/Write</td>
17684 + </tr>
17685 +
17686 + <tr>
17687 + <td> enumspeed </td>
17688 + <td> Gets the device enumeration Speed.</td>
17689 + <td> Read</td>
17690 + </tr>
17691 +
17692 + <tr>
17693 + <td> hptxfsiz </td>
17694 + <td> Gets the value of the Host Periodic Transmit FIFO</td>
17695 + <td> Read</td>
17696 + </tr>
17697 +
17698 + <tr>
17699 + <td> hprt0 </td>
17700 + <td> Gets or sets the value in the Host Port Control and Status Register</td>
17701 + <td> Read/Write</td>
17702 + </tr>
17703 +
17704 + <tr>
17705 + <td> regoffset </td>
17706 + <td> Sets the register offset for the next Register Access</td>
17707 + <td> Read/Write</td>
17708 + </tr>
17709 +
17710 + <tr>
17711 + <td> regvalue </td>
17712 + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
17713 + <td> Read/Write</td>
17714 + </tr>
17715 +
17716 + <tr>
17717 + <td> remote_wakeup </td>
17718 + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
17719 + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
17720 + Wakeup signalling bit in the Device Control Register is set for 1
17721 + milli-second.</td>
17722 + <td> Read/Write</td>
17723 + </tr>
17724 +
17725 + <tr>
17726 + <td> rem_wakeup_pwrdn </td>
17727 + <td> On read, shows the status core - hibernated or not. On write, initiates
17728 + a remote wakeup of the device from Hibernation. </td>
17729 + <td> Read/Write</td>
17730 + </tr>
17731 +
17732 + <tr>
17733 + <td> mode_ch_tim_en </td>
17734 + <td> This bit is used to enable or disable the host core to wait for 200 PHY
17735 + clock cycles at the end of Resume to change the opmode signal to the PHY to 00
17736 + after Suspend or LPM. </td>
17737 + <td> Read/Write</td>
17738 + </tr>
17739 +
17740 + <tr>
17741 + <td> fr_interval </td>
17742 + <td> On read, shows the value of HFIR Frame Interval. On write, dynamically
17743 + reload HFIR register during runtime. The application can write a value to this
17744 + register only after the Port Enable bit of the Host Port Control and Status
17745 + register (HPRT.PrtEnaPort) has been set </td>
17746 + <td> Read/Write</td>
17747 + </tr>
17748 +
17749 + <tr>
17750 + <td> disconnect_us </td>
17751 + <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
17752 + which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>
17753 + <td> Read/Write</td>
17754 + </tr>
17755 +
17756 + <tr>
17757 + <td> regdump </td>
17758 + <td> Dumps the contents of core registers.</td>
17759 + <td> Read</td>
17760 + </tr>
17761 +
17762 + <tr>
17763 + <td> spramdump </td>
17764 + <td> Dumps the contents of core registers.</td>
17765 + <td> Read</td>
17766 + </tr>
17767 +
17768 + <tr>
17769 + <td> hcddump </td>
17770 + <td> Dumps the current HCD state.</td>
17771 + <td> Read</td>
17772 + </tr>
17773 +
17774 + <tr>
17775 + <td> hcd_frrem </td>
17776 + <td> Shows the average value of the Frame Remaining
17777 + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
17778 + occurs. This can be used to determine the average interrupt latency. Also
17779 + shows the average Frame Remaining value for start_transfer and the "a" and
17780 + "b" sample points. The "a" and "b" sample points may be used during debugging
17781 + bto determine how long it takes to execute a section of the HCD code.</td>
17782 + <td> Read</td>
17783 + </tr>
17784 +
17785 + <tr>
17786 + <td> rd_reg_test </td>
17787 + <td> Displays the time required to read the GNPTXFSIZ register many times
17788 + (the output shows the number of times the register is read).
17789 + <td> Read</td>
17790 + </tr>
17791 +
17792 + <tr>
17793 + <td> wr_reg_test </td>
17794 + <td> Displays the time required to write the GNPTXFSIZ register many times
17795 + (the output shows the number of times the register is written).
17796 + <td> Read</td>
17797 + </tr>
17798 +
17799 + <tr>
17800 + <td> lpm_response </td>
17801 + <td> Gets or sets lpm_response mode. Applicable only in device mode.
17802 + <td> Write</td>
17803 + </tr>
17804 +
17805 + <tr>
17806 + <td> sleep_status </td>
17807 + <td> Shows sleep status of device.
17808 + <td> Read</td>
17809 + </tr>
17810 +
17811 + </table>
17812 +
17813 + Example usage:
17814 + To get the current mode:
17815 + cat /sys/devices/lm0/mode
17816 +
17817 + To power down the USB:
17818 + echo 0 > /sys/devices/lm0/buspower
17819 + */
17820 +
17821 +#include "dwc_otg_os_dep.h"
17822 +#include "dwc_os.h"
17823 +#include "dwc_otg_driver.h"
17824 +#include "dwc_otg_attr.h"
17825 +#include "dwc_otg_core_if.h"
17826 +#include "dwc_otg_pcd_if.h"
17827 +#include "dwc_otg_hcd_if.h"
17828 +
17829 +/*
17830 + * MACROs for defining sysfs attribute
17831 + */
17832 +#ifdef LM_INTERFACE
17833 +
17834 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17835 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17836 +{ \
17837 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17838 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev);             \
17839 +       uint32_t val; \
17840 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17841 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17842 +}
17843 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17844 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17845 +                                       const char *buf, size_t count) \
17846 +{ \
17847 +       struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
17848 +       dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
17849 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17850 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17851 +       return count; \
17852 +}
17853 +
17854 +#elif defined(PCI_INTERFACE)
17855 +
17856 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17857 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17858 +{ \
17859 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);      \
17860 +       uint32_t val; \
17861 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17862 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17863 +}
17864 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17865 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17866 +                                       const char *buf, size_t count) \
17867 +{ \
17868 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17869 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17870 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17871 +       return count; \
17872 +}
17873 +
17874 +#elif defined(PLATFORM_INTERFACE)
17875 +
17876 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17877 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17878 +{ \
17879 +        struct platform_device *platform_dev = \
17880 +                container_of(_dev, struct platform_device, dev); \
17881 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev);  \
17882 +       uint32_t val; \
17883 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17884 +                    __func__, _dev, platform_dev, otg_dev); \
17885 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17886 +       return sprintf (buf, "%s = 0x%x\n", _string_, val); \
17887 +}
17888 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17889 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17890 +                                       const char *buf, size_t count) \
17891 +{ \
17892 +        struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17893 +        dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17894 +       uint32_t set = simple_strtoul(buf, NULL, 16); \
17895 +       dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
17896 +       return count; \
17897 +}
17898 +#endif
17899 +
17900 +/*
17901 + * MACROs for defining sysfs attribute for 32-bit registers
17902 + */
17903 +#ifdef LM_INTERFACE
17904 +#define DWC_OTG_DEVICE_ATTR_REG_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%08x\n", _string_, val); \
17912 +}
17913 +#define DWC_OTG_DEVICE_ATTR_REG_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 val = simple_strtoul(buf, NULL, 16); \
17920 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17921 +       return count; \
17922 +}
17923 +#elif defined(PCI_INTERFACE)
17924 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17925 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17926 +{ \
17927 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17928 +       uint32_t val; \
17929 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17930 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17931 +}
17932 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17933 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17934 +                                       const char *buf, size_t count) \
17935 +{ \
17936 +       dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);  \
17937 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
17938 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17939 +       return count; \
17940 +}
17941 +
17942 +#elif defined(PLATFORM_INTERFACE)
17943 +#include "dwc_otg_dbg.h"
17944 +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17945 +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
17946 +{ \
17947 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17948 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17949 +       uint32_t val; \
17950 +       DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
17951 +                    __func__, _dev, platform_dev, otg_dev); \
17952 +       val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
17953 +       return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
17954 +}
17955 +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17956 +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
17957 +                                       const char *buf, size_t count) \
17958 +{ \
17959 +       struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
17960 +       dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
17961 +       uint32_t val = simple_strtoul(buf, NULL, 16); \
17962 +       dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
17963 +       return count; \
17964 +}
17965 +
17966 +#endif
17967 +
17968 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
17969 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17970 +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
17971 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
17972 +
17973 +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
17974 +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
17975 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
17976 +
17977 +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
17978 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17979 +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
17980 +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
17981 +
17982 +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
17983 +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
17984 +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
17985 +
17986 +/** @name Functions for Show/Store of Attributes */
17987 +/**@{*/
17988 +
17989 +/**
17990 + * Helper function returning the otg_device structure of the given device
17991 + */
17992 +static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
17993 +{
17994 +        dwc_otg_device_t *otg_dev;
17995 +        DWC_OTG_GETDRVDEV(otg_dev, _dev);
17996 +        return otg_dev;
17997 +}
17998 +
17999 +/**
18000 + * Show the register offset of the Register Access.
18001 + */
18002 +static ssize_t regoffset_show(struct device *_dev,
18003 +                             struct device_attribute *attr, char *buf)
18004 +{
18005 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18006 +       return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
18007 +                       otg_dev->os_dep.reg_offset);
18008 +}
18009 +
18010 +/**
18011 + * Set the register offset for the next Register Access        Read/Write
18012 + */
18013 +static ssize_t regoffset_store(struct device *_dev,
18014 +                              struct device_attribute *attr,
18015 +                              const char *buf, size_t count)
18016 +{
18017 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18018 +       uint32_t offset = simple_strtoul(buf, NULL, 16);
18019 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
18020 +       if (offset < SZ_256K) {
18021 +#elif  defined(PCI_INTERFACE)
18022 +       if (offset < 0x00040000) {
18023 +#endif
18024 +               otg_dev->os_dep.reg_offset = offset;
18025 +       } else {
18026 +               dev_err(_dev, "invalid offset\n");
18027 +       }
18028 +
18029 +       return count;
18030 +}
18031 +
18032 +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
18033 +
18034 +/**
18035 + * Show the value of the register at the offset in the reg_offset
18036 + * attribute.
18037 + */
18038 +static ssize_t regvalue_show(struct device *_dev,
18039 +                            struct device_attribute *attr, char *buf)
18040 +{
18041 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18042 +       uint32_t val;
18043 +       volatile uint32_t *addr;
18044 +
18045 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18046 +               /* Calculate the address */
18047 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18048 +                                    (uint8_t *) otg_dev->os_dep.base);
18049 +               val = DWC_READ_REG32(addr);
18050 +               return snprintf(buf,
18051 +                               sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
18052 +                               "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,
18053 +                               val);
18054 +       } else {
18055 +               dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);
18056 +               return sprintf(buf, "invalid offset\n");
18057 +       }
18058 +}
18059 +
18060 +/**
18061 + * Store the value in the register at the offset in the reg_offset
18062 + * attribute.
18063 + *
18064 + */
18065 +static ssize_t regvalue_store(struct device *_dev,
18066 +                             struct device_attribute *attr,
18067 +                             const char *buf, size_t count)
18068 +{
18069 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18070 +       volatile uint32_t *addr;
18071 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18072 +       //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
18073 +       if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
18074 +               /* Calculate the address */
18075 +               addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
18076 +                                    (uint8_t *) otg_dev->os_dep.base);
18077 +               DWC_WRITE_REG32(addr, val);
18078 +       } else {
18079 +               dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
18080 +                       otg_dev->os_dep.reg_offset);
18081 +       }
18082 +       return count;
18083 +}
18084 +
18085 +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
18086 +
18087 +/*
18088 + * Attributes
18089 + */
18090 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
18091 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
18092 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");
18093 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
18094 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
18095 +
18096 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18097 +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
18098 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
18099 +
18100 +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
18101 +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
18102 +                            &(otg_dev->core_if->core_global_regs->gusbcfg),
18103 +                            "GUSBCFG");
18104 +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
18105 +                            &(otg_dev->core_if->core_global_regs->grxfsiz),
18106 +                            "GRXFSIZ");
18107 +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
18108 +                            &(otg_dev->core_if->core_global_regs->gnptxfsiz),
18109 +                            "GNPTXFSIZ");
18110 +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
18111 +                            &(otg_dev->core_if->core_global_regs->gpvndctl),
18112 +                            "GPVNDCTL");
18113 +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
18114 +                            &(otg_dev->core_if->core_global_regs->ggpio),
18115 +                            "GGPIO");
18116 +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
18117 +                            "GUID");
18118 +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
18119 +                            &(otg_dev->core_if->core_global_regs->gsnpsid),
18120 +                            "GSNPSID");
18121 +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
18122 +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
18123 +
18124 +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
18125 +                            &(otg_dev->core_if->core_global_regs->hptxfsiz),
18126 +                            "HPTXFSIZ");
18127 +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
18128 +
18129 +/**
18130 + * @todo Add code to initiate the HNP.
18131 + */
18132 +/**
18133 + * Show the HNP status bit
18134 + */
18135 +static ssize_t hnp_show(struct device *_dev,
18136 +                       struct device_attribute *attr, char *buf)
18137 +{
18138 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18139 +       return sprintf(buf, "HstNegScs = 0x%x\n",
18140 +                      dwc_otg_get_hnpstatus(otg_dev->core_if));
18141 +}
18142 +
18143 +/**
18144 + * Set the HNP Request bit
18145 + */
18146 +static ssize_t hnp_store(struct device *_dev,
18147 +                        struct device_attribute *attr,
18148 +                        const char *buf, size_t count)
18149 +{
18150 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18151 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18152 +       dwc_otg_set_hnpreq(otg_dev->core_if, in);
18153 +       return count;
18154 +}
18155 +
18156 +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
18157 +
18158 +/**
18159 + * @todo Add code to initiate the SRP.
18160 + */
18161 +/**
18162 + * Show the SRP status bit
18163 + */
18164 +static ssize_t srp_show(struct device *_dev,
18165 +                       struct device_attribute *attr, char *buf)
18166 +{
18167 +#ifndef DWC_HOST_ONLY
18168 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18169 +       return sprintf(buf, "SesReqScs = 0x%x\n",
18170 +                      dwc_otg_get_srpstatus(otg_dev->core_if));
18171 +#else
18172 +       return sprintf(buf, "Host Only Mode!\n");
18173 +#endif
18174 +}
18175 +
18176 +/**
18177 + * Set the SRP Request bit
18178 + */
18179 +static ssize_t srp_store(struct device *_dev,
18180 +                        struct device_attribute *attr,
18181 +                        const char *buf, size_t count)
18182 +{
18183 +#ifndef DWC_HOST_ONLY
18184 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18185 +       dwc_otg_pcd_initiate_srp(otg_dev->pcd);
18186 +#endif
18187 +       return count;
18188 +}
18189 +
18190 +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
18191 +
18192 +/**
18193 + * @todo Need to do more for power on/off?
18194 + */
18195 +/**
18196 + * Show the Bus Power status
18197 + */
18198 +static ssize_t buspower_show(struct device *_dev,
18199 +                            struct device_attribute *attr, char *buf)
18200 +{
18201 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18202 +       return sprintf(buf, "Bus Power = 0x%x\n",
18203 +                      dwc_otg_get_prtpower(otg_dev->core_if));
18204 +}
18205 +
18206 +/**
18207 + * Set the Bus Power status
18208 + */
18209 +static ssize_t buspower_store(struct device *_dev,
18210 +                             struct device_attribute *attr,
18211 +                             const char *buf, size_t count)
18212 +{
18213 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18214 +       uint32_t on = simple_strtoul(buf, NULL, 16);
18215 +       dwc_otg_set_prtpower(otg_dev->core_if, on);
18216 +       return count;
18217 +}
18218 +
18219 +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
18220 +
18221 +/**
18222 + * @todo Need to do more for suspend?
18223 + */
18224 +/**
18225 + * Show the Bus Suspend status
18226 + */
18227 +static ssize_t bussuspend_show(struct device *_dev,
18228 +                              struct device_attribute *attr, char *buf)
18229 +{
18230 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18231 +       return sprintf(buf, "Bus Suspend = 0x%x\n",
18232 +                      dwc_otg_get_prtsuspend(otg_dev->core_if));
18233 +}
18234 +
18235 +/**
18236 + * Set the Bus Suspend status
18237 + */
18238 +static ssize_t bussuspend_store(struct device *_dev,
18239 +                               struct device_attribute *attr,
18240 +                               const char *buf, size_t count)
18241 +{
18242 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18243 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18244 +       dwc_otg_set_prtsuspend(otg_dev->core_if, in);
18245 +       return count;
18246 +}
18247 +
18248 +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
18249 +
18250 +/**
18251 + * Show the Mode Change Ready Timer status
18252 + */
18253 +static ssize_t mode_ch_tim_en_show(struct device *_dev,
18254 +                                  struct device_attribute *attr, char *buf)
18255 +{
18256 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18257 +       return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
18258 +                      dwc_otg_get_mode_ch_tim(otg_dev->core_if));
18259 +}
18260 +
18261 +/**
18262 + * Set the Mode Change Ready Timer status
18263 + */
18264 +static ssize_t mode_ch_tim_en_store(struct device *_dev,
18265 +                                   struct device_attribute *attr,
18266 +                                   const char *buf, size_t count)
18267 +{
18268 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18269 +       uint32_t in = simple_strtoul(buf, NULL, 16);
18270 +       dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);
18271 +       return count;
18272 +}
18273 +
18274 +DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);
18275 +
18276 +/**
18277 + * Show the value of HFIR Frame Interval bitfield
18278 + */
18279 +static ssize_t fr_interval_show(struct device *_dev,
18280 +                               struct device_attribute *attr, char *buf)
18281 +{
18282 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18283 +       return sprintf(buf, "Frame Interval = 0x%x\n",
18284 +                      dwc_otg_get_fr_interval(otg_dev->core_if));
18285 +}
18286 +
18287 +/**
18288 + * Set the HFIR Frame Interval value
18289 + */
18290 +static ssize_t fr_interval_store(struct device *_dev,
18291 +                                struct device_attribute *attr,
18292 +                                const char *buf, size_t count)
18293 +{
18294 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18295 +       uint32_t in = simple_strtoul(buf, NULL, 10);
18296 +       dwc_otg_set_fr_interval(otg_dev->core_if, in);
18297 +       return count;
18298 +}
18299 +
18300 +DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);
18301 +
18302 +/**
18303 + * Show the status of Remote Wakeup.
18304 + */
18305 +static ssize_t remote_wakeup_show(struct device *_dev,
18306 +                                 struct device_attribute *attr, char *buf)
18307 +{
18308 +#ifndef DWC_HOST_ONLY
18309 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18310 +
18311 +       return sprintf(buf,
18312 +                      "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
18313 +                      dwc_otg_get_remotewakesig(otg_dev->core_if),
18314 +                      dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
18315 +                      dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
18316 +#else
18317 +       return sprintf(buf, "Host Only Mode!\n");
18318 +#endif /* DWC_HOST_ONLY */
18319 +}
18320 +
18321 +/**
18322 + * Initiate a remote wakeup of the host.  The Device control register
18323 + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
18324 + * flag is set.
18325 + *
18326 + */
18327 +static ssize_t remote_wakeup_store(struct device *_dev,
18328 +                                  struct device_attribute *attr,
18329 +                                  const char *buf, size_t count)
18330 +{
18331 +#ifndef DWC_HOST_ONLY
18332 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18333 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18334 +
18335 +       if (val & 1) {
18336 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
18337 +       } else {
18338 +               dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
18339 +       }
18340 +#endif /* DWC_HOST_ONLY */
18341 +       return count;
18342 +}
18343 +
18344 +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
18345 +           remote_wakeup_store);
18346 +
18347 +/**
18348 + * Show the whether core is hibernated or not.
18349 + */
18350 +static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
18351 +                                    struct device_attribute *attr, char *buf)
18352 +{
18353 +#ifndef DWC_HOST_ONLY
18354 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18355 +
18356 +       if (dwc_otg_get_core_state(otg_dev->core_if)) {
18357 +               DWC_PRINTF("Core is in hibernation\n");
18358 +       } else {
18359 +               DWC_PRINTF("Core is not in hibernation\n");
18360 +       }
18361 +#endif /* DWC_HOST_ONLY */
18362 +       return 0;
18363 +}
18364 +
18365 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
18366 +                                             int rem_wakeup, int reset);
18367 +
18368 +/**
18369 + * Initiate a remote wakeup of the device to exit from hibernation.
18370 + */
18371 +static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,
18372 +                                     struct device_attribute *attr,
18373 +                                     const char *buf, size_t count)
18374 +{
18375 +#ifndef DWC_HOST_ONLY
18376 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18377 +       dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
18378 +#endif
18379 +       return count;
18380 +}
18381 +
18382 +DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,
18383 +           rem_wakeup_pwrdn_store);
18384 +
18385 +static ssize_t disconnect_us(struct device *_dev,
18386 +                            struct device_attribute *attr,
18387 +                            const char *buf, size_t count)
18388 +{
18389 +
18390 +#ifndef DWC_HOST_ONLY
18391 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18392 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18393 +       DWC_PRINTF("The Passed value is %04x\n", val);
18394 +
18395 +       dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);
18396 +
18397 +#endif /* DWC_HOST_ONLY */
18398 +       return count;
18399 +}
18400 +
18401 +DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);
18402 +
18403 +/**
18404 + * Dump global registers and either host or device registers (depending on the
18405 + * current mode of the core).
18406 + */
18407 +static ssize_t regdump_show(struct device *_dev,
18408 +                           struct device_attribute *attr, char *buf)
18409 +{
18410 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18411 +
18412 +       dwc_otg_dump_global_registers(otg_dev->core_if);
18413 +       if (dwc_otg_is_host_mode(otg_dev->core_if)) {
18414 +               dwc_otg_dump_host_registers(otg_dev->core_if);
18415 +       } else {
18416 +               dwc_otg_dump_dev_registers(otg_dev->core_if);
18417 +
18418 +       }
18419 +       return sprintf(buf, "Register Dump\n");
18420 +}
18421 +
18422 +DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
18423 +
18424 +/**
18425 + * Dump global registers and either host or device registers (depending on the
18426 + * current mode of the core).
18427 + */
18428 +static ssize_t spramdump_show(struct device *_dev,
18429 +                             struct device_attribute *attr, char *buf)
18430 +{
18431 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18432 +
18433 +       dwc_otg_dump_spram(otg_dev->core_if);
18434 +
18435 +       return sprintf(buf, "SPRAM Dump\n");
18436 +}
18437 +
18438 +DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
18439 +
18440 +/**
18441 + * Dump the current hcd state.
18442 + */
18443 +static ssize_t hcddump_show(struct device *_dev,
18444 +                           struct device_attribute *attr, char *buf)
18445 +{
18446 +#ifndef DWC_DEVICE_ONLY
18447 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18448 +       dwc_otg_hcd_dump_state(otg_dev->hcd);
18449 +#endif /* DWC_DEVICE_ONLY */
18450 +       return sprintf(buf, "HCD Dump\n");
18451 +}
18452 +
18453 +DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
18454 +
18455 +/**
18456 + * Dump the average frame remaining at SOF. This can be used to
18457 + * determine average interrupt latency. Frame remaining is also shown for
18458 + * start transfer and two additional sample points.
18459 + */
18460 +static ssize_t hcd_frrem_show(struct device *_dev,
18461 +                             struct device_attribute *attr, char *buf)
18462 +{
18463 +#ifndef DWC_DEVICE_ONLY
18464 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18465 +
18466 +       dwc_otg_hcd_dump_frrem(otg_dev->hcd);
18467 +#endif /* DWC_DEVICE_ONLY */
18468 +       return sprintf(buf, "HCD Dump Frame Remaining\n");
18469 +}
18470 +
18471 +DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
18472 +
18473 +/**
18474 + * Displays the time required to read the GNPTXFSIZ register many times (the
18475 + * output shows the number of times the register is read).
18476 + */
18477 +#define RW_REG_COUNT 10000000
18478 +#define MSEC_PER_JIFFIE 1000/HZ
18479 +static ssize_t rd_reg_test_show(struct device *_dev,
18480 +                               struct device_attribute *attr, char *buf)
18481 +{
18482 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18483 +       int i;
18484 +       int time;
18485 +       int start_jiffies;
18486 +
18487 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18488 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18489 +       start_jiffies = jiffies;
18490 +       for (i = 0; i < RW_REG_COUNT; i++) {
18491 +               dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18492 +       }
18493 +       time = jiffies - start_jiffies;
18494 +       return sprintf(buf,
18495 +                      "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18496 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18497 +}
18498 +
18499 +DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
18500 +
18501 +/**
18502 + * Displays the time required to write the GNPTXFSIZ register many times (the
18503 + * output shows the number of times the register is written).
18504 + */
18505 +static ssize_t wr_reg_test_show(struct device *_dev,
18506 +                               struct device_attribute *attr, char *buf)
18507 +{
18508 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18509 +       uint32_t reg_val;
18510 +       int i;
18511 +       int time;
18512 +       int start_jiffies;
18513 +
18514 +       printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
18515 +              HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
18516 +       reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
18517 +       start_jiffies = jiffies;
18518 +       for (i = 0; i < RW_REG_COUNT; i++) {
18519 +               dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
18520 +       }
18521 +       time = jiffies - start_jiffies;
18522 +       return sprintf(buf,
18523 +                      "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
18524 +                      RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
18525 +}
18526 +
18527 +DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
18528 +
18529 +#ifdef CONFIG_USB_DWC_OTG_LPM
18530 +
18531 +/**
18532 +* Show the lpm_response attribute.
18533 +*/
18534 +static ssize_t lpmresp_show(struct device *_dev,
18535 +                           struct device_attribute *attr, char *buf)
18536 +{
18537 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18538 +
18539 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
18540 +               return sprintf(buf, "** LPM is DISABLED **\n");
18541 +
18542 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18543 +               return sprintf(buf, "** Current mode is not device mode\n");
18544 +       }
18545 +       return sprintf(buf, "lpm_response = %d\n",
18546 +                      dwc_otg_get_lpmresponse(otg_dev->core_if));
18547 +}
18548 +
18549 +/**
18550 +* Store the lpm_response attribute.
18551 +*/
18552 +static ssize_t lpmresp_store(struct device *_dev,
18553 +                            struct device_attribute *attr,
18554 +                            const char *buf, size_t count)
18555 +{
18556 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18557 +       uint32_t val = simple_strtoul(buf, NULL, 16);
18558 +
18559 +       if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
18560 +               return 0;
18561 +       }
18562 +
18563 +       if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
18564 +               return 0;
18565 +       }
18566 +
18567 +       dwc_otg_set_lpmresponse(otg_dev->core_if, val);
18568 +       return count;
18569 +}
18570 +
18571 +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
18572 +
18573 +/**
18574 +* Show the sleep_status attribute.
18575 +*/
18576 +static ssize_t sleepstatus_show(struct device *_dev,
18577 +                               struct device_attribute *attr, char *buf)
18578 +{
18579 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18580 +       return sprintf(buf, "Sleep Status = %d\n",
18581 +                      dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
18582 +}
18583 +
18584 +/**
18585 + * Store the sleep_status attribure.
18586 + */
18587 +static ssize_t sleepstatus_store(struct device *_dev,
18588 +                                struct device_attribute *attr,
18589 +                                const char *buf, size_t count)
18590 +{
18591 +        dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
18592 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
18593 +
18594 +       if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
18595 +               if (dwc_otg_is_host_mode(core_if)) {
18596 +
18597 +                       DWC_PRINTF("Host initiated resume\n");
18598 +                       dwc_otg_set_prtresume(otg_dev->core_if, 1);
18599 +               }
18600 +       }
18601 +
18602 +       return count;
18603 +}
18604 +
18605 +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
18606 +           sleepstatus_store);
18607 +
18608 +#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
18609 +
18610 +/**@}*/
18611 +
18612 +/**
18613 + * Create the device files
18614 + */
18615 +void dwc_otg_attr_create(
18616 +#ifdef LM_INTERFACE
18617 +       struct lm_device *dev
18618 +#elif  defined(PCI_INTERFACE)
18619 +       struct pci_dev *dev
18620 +#elif  defined(PLATFORM_INTERFACE)
18621 +        struct platform_device *dev
18622 +#endif
18623 +    )
18624 +{
18625 +       int error;
18626 +
18627 +       error = device_create_file(&dev->dev, &dev_attr_regoffset);
18628 +       error = device_create_file(&dev->dev, &dev_attr_regvalue);
18629 +       error = device_create_file(&dev->dev, &dev_attr_mode);
18630 +       error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
18631 +       error = device_create_file(&dev->dev, &dev_attr_srpcapable);
18632 +       error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
18633 +       error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
18634 +       error = device_create_file(&dev->dev, &dev_attr_hnp);
18635 +       error = device_create_file(&dev->dev, &dev_attr_srp);
18636 +       error = device_create_file(&dev->dev, &dev_attr_buspower);
18637 +       error = device_create_file(&dev->dev, &dev_attr_bussuspend);
18638 +       error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18639 +       error = device_create_file(&dev->dev, &dev_attr_fr_interval);
18640 +       error = device_create_file(&dev->dev, &dev_attr_busconnected);
18641 +       error = device_create_file(&dev->dev, &dev_attr_gotgctl);
18642 +       error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
18643 +       error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
18644 +       error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
18645 +       error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
18646 +       error = device_create_file(&dev->dev, &dev_attr_ggpio);
18647 +       error = device_create_file(&dev->dev, &dev_attr_guid);
18648 +       error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
18649 +       error = device_create_file(&dev->dev, &dev_attr_devspeed);
18650 +       error = device_create_file(&dev->dev, &dev_attr_enumspeed);
18651 +       error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
18652 +       error = device_create_file(&dev->dev, &dev_attr_hprt0);
18653 +       error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
18654 +       error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18655 +       error = device_create_file(&dev->dev, &dev_attr_disconnect_us);
18656 +       error = device_create_file(&dev->dev, &dev_attr_regdump);
18657 +       error = device_create_file(&dev->dev, &dev_attr_spramdump);
18658 +       error = device_create_file(&dev->dev, &dev_attr_hcddump);
18659 +       error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
18660 +       error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
18661 +       error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
18662 +#ifdef CONFIG_USB_DWC_OTG_LPM
18663 +       error = device_create_file(&dev->dev, &dev_attr_lpm_response);
18664 +       error = device_create_file(&dev->dev, &dev_attr_sleep_status);
18665 +#endif
18666 +}
18667 +
18668 +/**
18669 + * Remove the device files
18670 + */
18671 +void dwc_otg_attr_remove(
18672 +#ifdef LM_INTERFACE
18673 +       struct lm_device *dev
18674 +#elif  defined(PCI_INTERFACE)
18675 +       struct pci_dev *dev
18676 +#elif  defined(PLATFORM_INTERFACE)
18677 +       struct platform_device *dev
18678 +#endif
18679 +    )
18680 +{
18681 +       device_remove_file(&dev->dev, &dev_attr_regoffset);
18682 +       device_remove_file(&dev->dev, &dev_attr_regvalue);
18683 +       device_remove_file(&dev->dev, &dev_attr_mode);
18684 +       device_remove_file(&dev->dev, &dev_attr_hnpcapable);
18685 +       device_remove_file(&dev->dev, &dev_attr_srpcapable);
18686 +       device_remove_file(&dev->dev, &dev_attr_hsic_connect);
18687 +       device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
18688 +       device_remove_file(&dev->dev, &dev_attr_hnp);
18689 +       device_remove_file(&dev->dev, &dev_attr_srp);
18690 +       device_remove_file(&dev->dev, &dev_attr_buspower);
18691 +       device_remove_file(&dev->dev, &dev_attr_bussuspend);
18692 +       device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);
18693 +       device_remove_file(&dev->dev, &dev_attr_fr_interval);
18694 +       device_remove_file(&dev->dev, &dev_attr_busconnected);
18695 +       device_remove_file(&dev->dev, &dev_attr_gotgctl);
18696 +       device_remove_file(&dev->dev, &dev_attr_gusbcfg);
18697 +       device_remove_file(&dev->dev, &dev_attr_grxfsiz);
18698 +       device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
18699 +       device_remove_file(&dev->dev, &dev_attr_gpvndctl);
18700 +       device_remove_file(&dev->dev, &dev_attr_ggpio);
18701 +       device_remove_file(&dev->dev, &dev_attr_guid);
18702 +       device_remove_file(&dev->dev, &dev_attr_gsnpsid);
18703 +       device_remove_file(&dev->dev, &dev_attr_devspeed);
18704 +       device_remove_file(&dev->dev, &dev_attr_enumspeed);
18705 +       device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
18706 +       device_remove_file(&dev->dev, &dev_attr_hprt0);
18707 +       device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
18708 +       device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
18709 +       device_remove_file(&dev->dev, &dev_attr_disconnect_us);
18710 +       device_remove_file(&dev->dev, &dev_attr_regdump);
18711 +       device_remove_file(&dev->dev, &dev_attr_spramdump);
18712 +       device_remove_file(&dev->dev, &dev_attr_hcddump);
18713 +       device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
18714 +       device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
18715 +       device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
18716 +#ifdef CONFIG_USB_DWC_OTG_LPM
18717 +       device_remove_file(&dev->dev, &dev_attr_lpm_response);
18718 +       device_remove_file(&dev->dev, &dev_attr_sleep_status);
18719 +#endif
18720 +}
18721 --- /dev/null
18722 +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
18723 @@ -0,0 +1,89 @@
18724 +/* ==========================================================================
18725 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
18726 + * $Revision: #13 $
18727 + * $Date: 2010/06/21 $
18728 + * $Change: 1532021 $
18729 + *
18730 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18731 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18732 + * otherwise expressly agreed to in writing between Synopsys and you.
18733 + *
18734 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18735 + * any End User Software License Agreement or Agreement for Licensed Product
18736 + * with Synopsys or any supplement thereto. You are permitted to use and
18737 + * redistribute this Software in source and binary forms, with or without
18738 + * modification, provided that redistributions of source code must retain this
18739 + * notice. You may not view, use, disclose, copy or distribute this file or
18740 + * any information contained herein except pursuant to this license grant from
18741 + * Synopsys. If you do not agree with this notice, including the disclaimer
18742 + * below, then you are not authorized to use the Software.
18743 + *
18744 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18745 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18746 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18747 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18748 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18749 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18750 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18751 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18752 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18753 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18754 + * DAMAGE.
18755 + * ========================================================================== */
18756 +
18757 +#if !defined(__DWC_OTG_ATTR_H__)
18758 +#define __DWC_OTG_ATTR_H__
18759 +
18760 +/** @file
18761 + * This file contains the interface to the Linux device attributes.
18762 + */
18763 +extern struct device_attribute dev_attr_regoffset;
18764 +extern struct device_attribute dev_attr_regvalue;
18765 +
18766 +extern struct device_attribute dev_attr_mode;
18767 +extern struct device_attribute dev_attr_hnpcapable;
18768 +extern struct device_attribute dev_attr_srpcapable;
18769 +extern struct device_attribute dev_attr_hnp;
18770 +extern struct device_attribute dev_attr_srp;
18771 +extern struct device_attribute dev_attr_buspower;
18772 +extern struct device_attribute dev_attr_bussuspend;
18773 +extern struct device_attribute dev_attr_mode_ch_tim_en;
18774 +extern struct device_attribute dev_attr_fr_interval;
18775 +extern struct device_attribute dev_attr_busconnected;
18776 +extern struct device_attribute dev_attr_gotgctl;
18777 +extern struct device_attribute dev_attr_gusbcfg;
18778 +extern struct device_attribute dev_attr_grxfsiz;
18779 +extern struct device_attribute dev_attr_gnptxfsiz;
18780 +extern struct device_attribute dev_attr_gpvndctl;
18781 +extern struct device_attribute dev_attr_ggpio;
18782 +extern struct device_attribute dev_attr_guid;
18783 +extern struct device_attribute dev_attr_gsnpsid;
18784 +extern struct device_attribute dev_attr_devspeed;
18785 +extern struct device_attribute dev_attr_enumspeed;
18786 +extern struct device_attribute dev_attr_hptxfsiz;
18787 +extern struct device_attribute dev_attr_hprt0;
18788 +#ifdef CONFIG_USB_DWC_OTG_LPM
18789 +extern struct device_attribute dev_attr_lpm_response;
18790 +extern struct device_attribute devi_attr_sleep_status;
18791 +#endif
18792 +
18793 +void dwc_otg_attr_create(
18794 +#ifdef LM_INTERFACE
18795 +                               struct lm_device *dev
18796 +#elif  defined(PCI_INTERFACE)
18797 +                               struct pci_dev *dev
18798 +#elif  defined(PLATFORM_INTERFACE)
18799 +       struct platform_device *dev
18800 +#endif
18801 +    );
18802 +
18803 +void dwc_otg_attr_remove(
18804 +#ifdef LM_INTERFACE
18805 +                               struct lm_device *dev
18806 +#elif  defined(PCI_INTERFACE)
18807 +                               struct pci_dev *dev
18808 +#elif  defined(PLATFORM_INTERFACE)
18809 +       struct platform_device *dev
18810 +#endif
18811 +    );
18812 +#endif
18813 --- /dev/null
18814 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
18815 @@ -0,0 +1,1876 @@
18816 +/* ==========================================================================
18817 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
18818 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
18819 + * otherwise expressly agreed to in writing between Synopsys and you.
18820 + *
18821 + * The Software IS NOT an item of Licensed Software or Licensed Product under
18822 + * any End User Software License Agreement or Agreement for Licensed Product
18823 + * with Synopsys or any supplement thereto. You are permitted to use and
18824 + * redistribute this Software in source and binary forms, with or without
18825 + * modification, provided that redistributions of source code must retain this
18826 + * notice. You may not view, use, disclose, copy or distribute this file or
18827 + * any information contained herein except pursuant to this license grant from
18828 + * Synopsys. If you do not agree with this notice, including the disclaimer
18829 + * below, then you are not authorized to use the Software.
18830 + *
18831 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
18832 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18833 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18834 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
18835 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18836 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18837 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
18838 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18839 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18840 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
18841 + * DAMAGE.
18842 + * ========================================================================== */
18843 +
18844 +/** @file
18845 + *
18846 + * This file contains the most of the CFI(Core Feature Interface)
18847 + * implementation for the OTG.
18848 + */
18849 +
18850 +#ifdef DWC_UTE_CFI
18851 +
18852 +#include "dwc_otg_pcd.h"
18853 +#include "dwc_otg_cfi.h"
18854 +
18855 +/** This definition should actually migrate to the Portability Library */
18856 +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
18857 +
18858 +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
18859 +
18860 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
18861 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
18862 +                                struct dwc_otg_pcd *pcd,
18863 +                                struct cfi_usb_ctrlrequest *ctrl_req);
18864 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
18865 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18866 +                            struct cfi_usb_ctrlrequest *req);
18867 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18868 +                                struct cfi_usb_ctrlrequest *req);
18869 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
18870 +                               struct cfi_usb_ctrlrequest *req);
18871 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
18872 +                            struct cfi_usb_ctrlrequest *req);
18873 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
18874 +
18875 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
18876 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
18877 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
18878 +
18879 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
18880 +
18881 +/** This is the header of the all features descriptor */
18882 +static cfi_all_features_header_t all_props_desc_header = {
18883 +       .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
18884 +       .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
18885 +       .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
18886 +};
18887 +
18888 +/** This is an array of statically allocated feature descriptors */
18889 +static cfi_feature_desc_header_t prop_descs[] = {
18890 +
18891 +       /* FT_ID_DMA_MODE */
18892 +       {
18893 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
18894 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18895 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
18896 +        },
18897 +
18898 +       /* FT_ID_DMA_BUFFER_SETUP */
18899 +       {
18900 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
18901 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18902 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18903 +        },
18904 +
18905 +       /* FT_ID_DMA_BUFF_ALIGN */
18906 +       {
18907 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
18908 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18909 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18910 +        },
18911 +
18912 +       /* FT_ID_DMA_CONCAT_SETUP */
18913 +       {
18914 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
18915 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18916 +        //.wDataLength  = DWC_CONSTANT_CPU_TO_LE16(6),
18917 +        },
18918 +
18919 +       /* FT_ID_DMA_CIRCULAR */
18920 +       {
18921 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
18922 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18923 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18924 +        },
18925 +
18926 +       /* FT_ID_THRESHOLD_SETUP */
18927 +       {
18928 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
18929 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18930 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
18931 +        },
18932 +
18933 +       /* FT_ID_DFIFO_DEPTH */
18934 +       {
18935 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
18936 +        .bmAttributes = CFI_FEATURE_ATTR_RO,
18937 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18938 +        },
18939 +
18940 +       /* FT_ID_TX_FIFO_DEPTH */
18941 +       {
18942 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
18943 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18944 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18945 +        },
18946 +
18947 +       /* FT_ID_RX_FIFO_DEPTH */
18948 +       {
18949 +        .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
18950 +        .bmAttributes = CFI_FEATURE_ATTR_RW,
18951 +        .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
18952 +        }
18953 +};
18954 +
18955 +/** The table of feature names */
18956 +cfi_string_t prop_name_table[] = {
18957 +       {FT_ID_DMA_MODE, "dma_mode"},
18958 +       {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
18959 +       {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
18960 +       {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
18961 +       {FT_ID_DMA_CIRCULAR, "buffer_circular"},
18962 +       {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
18963 +       {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
18964 +       {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
18965 +       {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
18966 +       {}
18967 +};
18968 +
18969 +/************************************************************************/
18970 +
18971 +/**
18972 + * Returns the name of the feature by its ID
18973 + * or NULL if no featute ID matches.
18974 + *
18975 + */
18976 +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
18977 +{
18978 +       cfi_string_t *pstr;
18979 +       *len = 0;
18980 +
18981 +       for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
18982 +               if (pstr->id == prop_id) {
18983 +                       *len = DWC_STRLEN(pstr->s);
18984 +                       return pstr->s;
18985 +               }
18986 +       }
18987 +       return NULL;
18988 +}
18989 +
18990 +/**
18991 + * This function handles all CFI specific control requests.
18992 + *
18993 + * Return a negative value to stall the DCE.
18994 + */
18995 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
18996 +{
18997 +       int retval = 0;
18998 +       dwc_otg_pcd_ep_t *ep = NULL;
18999 +       cfiobject_t *cfi = pcd->cfi;
19000 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19001 +       uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
19002 +       uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
19003 +       uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
19004 +       uint32_t regaddr = 0;
19005 +       uint32_t regval = 0;
19006 +
19007 +       /* Save this Control Request in the CFI object.
19008 +        * The data field will be assigned in the data stage completion CB function.
19009 +        */
19010 +       cfi->ctrl_req = *ctrl;
19011 +       cfi->ctrl_req.data = NULL;
19012 +
19013 +       cfi->need_gadget_att = 0;
19014 +       cfi->need_status_in_complete = 0;
19015 +
19016 +       switch (ctrl->bRequest) {
19017 +       case VEN_CORE_GET_FEATURES:
19018 +               retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
19019 +               if (retval >= 0) {
19020 +                       //dump_msg(cfi->buf_in.buf, retval);
19021 +                       ep = &pcd->ep0;
19022 +
19023 +                       retval = min((uint16_t) retval, wLen);
19024 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19025 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19026 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19027 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19028 +                       ep->dwc_ep.xfer_len = retval;
19029 +                       ep->dwc_ep.xfer_count = 0;
19030 +                       ep->dwc_ep.sent_zlp = 0;
19031 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19032 +
19033 +                       pcd->ep0_pending = 1;
19034 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19035 +               }
19036 +               retval = 0;
19037 +               break;
19038 +
19039 +       case VEN_CORE_GET_FEATURE:
19040 +               CFI_INFO("VEN_CORE_GET_FEATURE\n");
19041 +               retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
19042 +                                              pcd, ctrl);
19043 +               if (retval >= 0) {
19044 +                       ep = &pcd->ep0;
19045 +
19046 +                       retval = min((uint16_t) retval, wLen);
19047 +                       /* Transfer this buffer to the host through the EP0-IN EP */
19048 +                       ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19049 +                       ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19050 +                       ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19051 +                       ep->dwc_ep.xfer_len = retval;
19052 +                       ep->dwc_ep.xfer_count = 0;
19053 +                       ep->dwc_ep.sent_zlp = 0;
19054 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19055 +
19056 +                       pcd->ep0_pending = 1;
19057 +                       dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19058 +               }
19059 +               CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
19060 +               dump_msg(cfi->buf_in.buf, retval);
19061 +               break;
19062 +
19063 +       case VEN_CORE_SET_FEATURE:
19064 +               CFI_INFO("VEN_CORE_SET_FEATURE\n");
19065 +               /* Set up an XFER to get the data stage of the control request,
19066 +                * which is the new value of the feature to be modified.
19067 +                */
19068 +               ep = &pcd->ep0;
19069 +               ep->dwc_ep.is_in = 0;
19070 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19071 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19072 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19073 +               ep->dwc_ep.xfer_len = wLen;
19074 +               ep->dwc_ep.xfer_count = 0;
19075 +               ep->dwc_ep.sent_zlp = 0;
19076 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19077 +
19078 +               pcd->ep0_pending = 1;
19079 +               /* Read the control write's data stage */
19080 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19081 +               retval = 0;
19082 +               break;
19083 +
19084 +       case VEN_CORE_RESET_FEATURES:
19085 +               CFI_INFO("VEN_CORE_RESET_FEATURES\n");
19086 +               cfi->need_gadget_att = 1;
19087 +               cfi->need_status_in_complete = 1;
19088 +               retval = cfi_preproc_reset(pcd, ctrl);
19089 +               CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
19090 +               break;
19091 +
19092 +       case VEN_CORE_ACTIVATE_FEATURES:
19093 +               CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
19094 +               break;
19095 +
19096 +       case VEN_CORE_READ_REGISTER:
19097 +               CFI_INFO("VEN_CORE_READ_REGISTER\n");
19098 +               /* wValue optionally contains the HI WORD of the register offset and
19099 +                * wIndex contains the LOW WORD of the register offset
19100 +                */
19101 +               if (wValue == 0) {
19102 +                       /* @TODO - MAS - fix the access to the base field */
19103 +                       regaddr = 0;
19104 +                       //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
19105 +                       //GET_CORE_IF(pcd)->co
19106 +                       regaddr |= wIndex;
19107 +               } else {
19108 +                       regaddr = (wValue << 16) | wIndex;
19109 +               }
19110 +
19111 +               /* Read a 32-bit value of the memory at the regaddr */
19112 +               regval = DWC_READ_REG32((uint32_t *) regaddr);
19113 +
19114 +               ep = &pcd->ep0;
19115 +               dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
19116 +               ep->dwc_ep.is_in = 1;
19117 +               ep->dwc_ep.dma_addr = cfi->buf_in.addr;
19118 +               ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
19119 +               ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
19120 +               ep->dwc_ep.xfer_len = wLen;
19121 +               ep->dwc_ep.xfer_count = 0;
19122 +               ep->dwc_ep.sent_zlp = 0;
19123 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19124 +
19125 +               pcd->ep0_pending = 1;
19126 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19127 +               cfi->need_gadget_att = 0;
19128 +               retval = 0;
19129 +               break;
19130 +
19131 +       case VEN_CORE_WRITE_REGISTER:
19132 +               CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
19133 +               /* Set up an XFER to get the data stage of the control request,
19134 +                * which is the new value of the register to be modified.
19135 +                */
19136 +               ep = &pcd->ep0;
19137 +               ep->dwc_ep.is_in = 0;
19138 +               ep->dwc_ep.dma_addr = cfi->buf_out.addr;
19139 +               ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
19140 +               ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
19141 +               ep->dwc_ep.xfer_len = wLen;
19142 +               ep->dwc_ep.xfer_count = 0;
19143 +               ep->dwc_ep.sent_zlp = 0;
19144 +               ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
19145 +
19146 +               pcd->ep0_pending = 1;
19147 +               /* Read the control write's data stage */
19148 +               dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
19149 +               retval = 0;
19150 +               break;
19151 +
19152 +       default:
19153 +               retval = -DWC_E_NOT_SUPPORTED;
19154 +               break;
19155 +       }
19156 +
19157 +       return retval;
19158 +}
19159 +
19160 +/**
19161 + * This function prepares the core features descriptors and copies its
19162 + * raw representation into the buffer <buf>.
19163 + *
19164 + * The buffer structure is as follows:
19165 + *     all_features_header (8 bytes)
19166 + *     features_#1 (8 bytes + feature name string length)
19167 + *     features_#2 (8 bytes + feature name string length)
19168 + *     .....
19169 + *     features_#n - where n=the total count of feature descriptors
19170 + */
19171 +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
19172 +{
19173 +       cfi_feature_desc_header_t *prop_hdr = prop_descs;
19174 +       cfi_feature_desc_header_t *prop;
19175 +       cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
19176 +       cfi_all_features_header_t *tmp;
19177 +       uint8_t *tmpbuf = buf;
19178 +       const uint8_t *pname = NULL;
19179 +       int i, j, namelen = 0, totlen;
19180 +
19181 +       /* Prepare and copy the core features into the buffer */
19182 +       CFI_INFO("%s:\n", __func__);
19183 +
19184 +       tmp = (cfi_all_features_header_t *) tmpbuf;
19185 +       *tmp = *all_props_hdr;
19186 +       tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
19187 +
19188 +       j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
19189 +       for (i = 0; i < j; i++, prop_hdr++) {
19190 +               pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
19191 +               prop = (cfi_feature_desc_header_t *) tmpbuf;
19192 +               *prop = *prop_hdr;
19193 +
19194 +               prop->bNameLen = namelen;
19195 +               prop->wLength =
19196 +                   DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
19197 +                                            namelen);
19198 +
19199 +               tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
19200 +               dwc_memcpy(tmpbuf, pname, namelen);
19201 +               tmpbuf += namelen;
19202 +       }
19203 +
19204 +       totlen = tmpbuf - buf;
19205 +
19206 +       if (totlen > 0) {
19207 +               tmp = (cfi_all_features_header_t *) buf;
19208 +               tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
19209 +       }
19210 +
19211 +       return totlen;
19212 +}
19213 +
19214 +/**
19215 + * This function releases all the dynamic memory in the CFI object.
19216 + */
19217 +static void cfi_release(cfiobject_t * cfiobj)
19218 +{
19219 +       cfi_ep_t *cfiep;
19220 +       dwc_list_link_t *tmp;
19221 +
19222 +       CFI_INFO("%s\n", __func__);
19223 +
19224 +       if (cfiobj->buf_in.buf) {
19225 +               DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
19226 +                            cfiobj->buf_in.addr);
19227 +               cfiobj->buf_in.buf = NULL;
19228 +       }
19229 +
19230 +       if (cfiobj->buf_out.buf) {
19231 +               DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
19232 +                            cfiobj->buf_out.addr);
19233 +               cfiobj->buf_out.buf = NULL;
19234 +       }
19235 +
19236 +       /* Free the Buffer Setup values for each EP */
19237 +       //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
19238 +       DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
19239 +               cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19240 +               cfi_free_ep_bs_dyn_data(cfiep);
19241 +       }
19242 +}
19243 +
19244 +/**
19245 + * This function frees the dynamically allocated EP buffer setup data.
19246 + */
19247 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
19248 +{
19249 +       if (cfiep->bm_sg) {
19250 +               DWC_FREE(cfiep->bm_sg);
19251 +               cfiep->bm_sg = NULL;
19252 +       }
19253 +
19254 +       if (cfiep->bm_align) {
19255 +               DWC_FREE(cfiep->bm_align);
19256 +               cfiep->bm_align = NULL;
19257 +       }
19258 +
19259 +       if (cfiep->bm_concat) {
19260 +               if (NULL != cfiep->bm_concat->wTxBytes) {
19261 +                       DWC_FREE(cfiep->bm_concat->wTxBytes);
19262 +                       cfiep->bm_concat->wTxBytes = NULL;
19263 +               }
19264 +               DWC_FREE(cfiep->bm_concat);
19265 +               cfiep->bm_concat = NULL;
19266 +       }
19267 +}
19268 +
19269 +/**
19270 + * This function initializes the default values of the features
19271 + * for a specific endpoint and should be called only once when
19272 + * the EP is enabled first time.
19273 + */
19274 +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
19275 +{
19276 +       int retval = 0;
19277 +
19278 +       cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
19279 +       if (NULL == cfiep->bm_sg) {
19280 +               CFI_INFO("Failed to allocate memory for SG feature value\n");
19281 +               return -DWC_E_NO_MEMORY;
19282 +       }
19283 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19284 +
19285 +       /* For the Concatenation feature's default value we do not allocate
19286 +        * memory for the wTxBytes field - it will be done in the set_feature_value
19287 +        * request handler.
19288 +        */
19289 +       cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
19290 +       if (NULL == cfiep->bm_concat) {
19291 +               CFI_INFO
19292 +                   ("Failed to allocate memory for CONCATENATION feature value\n");
19293 +               DWC_FREE(cfiep->bm_sg);
19294 +               return -DWC_E_NO_MEMORY;
19295 +       }
19296 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19297 +
19298 +       cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
19299 +       if (NULL == cfiep->bm_align) {
19300 +               CFI_INFO
19301 +                   ("Failed to allocate memory for Alignment feature value\n");
19302 +               DWC_FREE(cfiep->bm_sg);
19303 +               DWC_FREE(cfiep->bm_concat);
19304 +               return -DWC_E_NO_MEMORY;
19305 +       }
19306 +       dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
19307 +
19308 +       return retval;
19309 +}
19310 +
19311 +/**
19312 + * The callback function that notifies the CFI on the activation of
19313 + * an endpoint in the PCD. The following steps are done in this function:
19314 + *
19315 + *     Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's
19316 + *             active endpoint)
19317 + *     Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
19318 + *     Set the Buffer Mode to standard
19319 + *     Initialize the default values for all EP modes (SG, Circular, Concat, Align)
19320 + *     Add the cfi_ep_t object to the list of active endpoints in the CFI object
19321 + */
19322 +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19323 +                        struct dwc_otg_pcd_ep *ep)
19324 +{
19325 +       cfi_ep_t *cfiep;
19326 +       int retval = -DWC_E_NOT_SUPPORTED;
19327 +
19328 +       CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
19329 +                "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
19330 +       /* MAS - Check whether this endpoint already is in the list */
19331 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19332 +
19333 +       if (NULL == cfiep) {
19334 +               /* Allocate a cfi_ep_t object */
19335 +               cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
19336 +               if (NULL == cfiep) {
19337 +                       CFI_INFO
19338 +                           ("Unable to allocate memory for <cfiep> in function %s\n",
19339 +                            __func__);
19340 +                       return -DWC_E_NO_MEMORY;
19341 +               }
19342 +               dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
19343 +
19344 +               /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
19345 +               cfiep->ep = ep;
19346 +
19347 +               /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
19348 +               ep->dwc_ep.descs =
19349 +                   DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
19350 +                                 sizeof(dwc_otg_dma_desc_t),
19351 +                                 &ep->dwc_ep.descs_dma_addr);
19352 +
19353 +               if (NULL == ep->dwc_ep.descs) {
19354 +                       DWC_FREE(cfiep);
19355 +                       return -DWC_E_NO_MEMORY;
19356 +               }
19357 +
19358 +               DWC_LIST_INIT(&cfiep->lh);
19359 +
19360 +               /* Set the buffer mode to BM_STANDARD. It will be modified
19361 +                * when building descriptors for a specific buffer mode */
19362 +               ep->dwc_ep.buff_mode = BM_STANDARD;
19363 +
19364 +               /* Create and initialize the default values for this EP's Buffer modes */
19365 +               if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
19366 +                       return retval;
19367 +
19368 +               /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
19369 +               DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
19370 +               retval = 0;
19371 +       } else {                /* The sought EP already is in the list */
19372 +               CFI_INFO("%s: The sought EP already is in the list\n",
19373 +                        __func__);
19374 +       }
19375 +
19376 +       return retval;
19377 +}
19378 +
19379 +/**
19380 + * This function is called when the data stage of a 3-stage Control Write request
19381 + * is complete.
19382 + *
19383 + */
19384 +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
19385 +                                  struct dwc_otg_pcd *pcd)
19386 +{
19387 +       uint32_t addr, reg_value;
19388 +       uint16_t wIndex, wValue;
19389 +       uint8_t bRequest;
19390 +       uint8_t *buf = cfi->buf_out.buf;
19391 +       //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
19392 +       struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
19393 +       int retval = -DWC_E_NOT_SUPPORTED;
19394 +
19395 +       CFI_INFO("%s\n", __func__);
19396 +
19397 +       bRequest = ctrl_req->bRequest;
19398 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
19399 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
19400 +
19401 +       /*
19402 +        * Save the pointer to the data stage in the ctrl_req's <data> field.
19403 +        * The request should be already saved in the command stage by now.
19404 +        */
19405 +       ctrl_req->data = cfi->buf_out.buf;
19406 +       cfi->need_status_in_complete = 0;
19407 +       cfi->need_gadget_att = 0;
19408 +
19409 +       switch (bRequest) {
19410 +       case VEN_CORE_WRITE_REGISTER:
19411 +               /* The buffer contains raw data of the new value for the register */
19412 +               reg_value = *((uint32_t *) buf);
19413 +               if (wValue == 0) {
19414 +                       addr = 0;
19415 +                       //addr = (uint32_t) pcd->otg_dev->os_dep.base;
19416 +                       addr += wIndex;
19417 +               } else {
19418 +                       addr = (wValue << 16) | wIndex;
19419 +               }
19420 +
19421 +               //writel(reg_value, addr);
19422 +
19423 +               retval = 0;
19424 +               cfi->need_status_in_complete = 1;
19425 +               break;
19426 +
19427 +       case VEN_CORE_SET_FEATURE:
19428 +               /* The buffer contains raw data of the new value of the feature */
19429 +               retval = cfi_set_feature_value(pcd);
19430 +               if (retval < 0)
19431 +                       return retval;
19432 +
19433 +               cfi->need_status_in_complete = 1;
19434 +               break;
19435 +
19436 +       default:
19437 +               break;
19438 +       }
19439 +
19440 +       return retval;
19441 +}
19442 +
19443 +/**
19444 + * This function builds the DMA descriptors for the SG buffer mode.
19445 + */
19446 +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19447 +                              dwc_otg_pcd_request_t * req)
19448 +{
19449 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19450 +       ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
19451 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19452 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19453 +       dma_addr_t buff_addr = req->dma;
19454 +       int i;
19455 +       uint32_t txsize, off;
19456 +
19457 +       txsize = sgval->wSize;
19458 +       off = sgval->bOffset;
19459 +
19460 +//      CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n",
19461 +//              __func__, cfiep->ep->ep.name, txsize, off);
19462 +
19463 +       for (i = 0; i < sgval->bCount; i++) {
19464 +               desc->status.b.bs = BS_HOST_BUSY;
19465 +               desc->buf = buff_addr;
19466 +               desc->status.b.l = 0;
19467 +               desc->status.b.ioc = 0;
19468 +               desc->status.b.sp = 0;
19469 +               desc->status.b.bytes = txsize;
19470 +               desc->status.b.bs = BS_HOST_READY;
19471 +
19472 +               /* Set the next address of the buffer */
19473 +               buff_addr += txsize + off;
19474 +               desc_last = desc;
19475 +               desc++;
19476 +       }
19477 +
19478 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19479 +       desc_last->status.b.l = 1;
19480 +       desc_last->status.b.ioc = 1;
19481 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19482 +       /* Save the last DMA descriptor pointer */
19483 +       cfiep->dma_desc_last = desc_last;
19484 +       cfiep->desc_count = sgval->bCount;
19485 +}
19486 +
19487 +/**
19488 + * This function builds the DMA descriptors for the Concatenation buffer mode.
19489 + */
19490 +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19491 +                                  dwc_otg_pcd_request_t * req)
19492 +{
19493 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19494 +       ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
19495 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19496 +       struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
19497 +       dma_addr_t buff_addr = req->dma;
19498 +       int i;
19499 +       uint16_t *txsize;
19500 +
19501 +       txsize = concatval->wTxBytes;
19502 +
19503 +       for (i = 0; i < concatval->hdr.bDescCount; i++) {
19504 +               desc->buf = buff_addr;
19505 +               desc->status.b.bs = BS_HOST_BUSY;
19506 +               desc->status.b.l = 0;
19507 +               desc->status.b.ioc = 0;
19508 +               desc->status.b.sp = 0;
19509 +               desc->status.b.bytes = *txsize;
19510 +               desc->status.b.bs = BS_HOST_READY;
19511 +
19512 +               txsize++;
19513 +               /* Set the next address of the buffer */
19514 +               buff_addr += UGETW(ep->desc->wMaxPacketSize);
19515 +               desc_last = desc;
19516 +               desc++;
19517 +       }
19518 +
19519 +       /* Set the last, ioc and sp bits on the Last DMA Descriptor */
19520 +       desc_last->status.b.l = 1;
19521 +       desc_last->status.b.ioc = 1;
19522 +       desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
19523 +       cfiep->dma_desc_last = desc_last;
19524 +       cfiep->desc_count = concatval->hdr.bDescCount;
19525 +}
19526 +
19527 +/**
19528 + * This function builds the DMA descriptors for the Circular buffer mode
19529 + */
19530 +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19531 +                                dwc_otg_pcd_request_t * req)
19532 +{
19533 +       /* @todo: MAS - add implementation when this feature needs to be tested */
19534 +}
19535 +
19536 +/**
19537 + * This function builds the DMA descriptors for the Alignment buffer mode
19538 + */
19539 +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
19540 +                                 dwc_otg_pcd_request_t * req)
19541 +{
19542 +       struct dwc_otg_pcd_ep *ep = cfiep->ep;
19543 +       ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
19544 +       struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
19545 +       dma_addr_t buff_addr = req->dma;
19546 +
19547 +       desc->status.b.bs = BS_HOST_BUSY;
19548 +       desc->status.b.l = 1;
19549 +       desc->status.b.ioc = 1;
19550 +       desc->status.b.sp = ep->dwc_ep.sent_zlp;
19551 +       desc->status.b.bytes = req->length;
19552 +       /* Adjust the buffer alignment */
19553 +       desc->buf = (buff_addr + alignval->bAlign);
19554 +       desc->status.b.bs = BS_HOST_READY;
19555 +       cfiep->dma_desc_last = desc;
19556 +       cfiep->desc_count = 1;
19557 +}
19558 +
19559 +/**
19560 + * This function builds the DMA descriptors chain for different modes of the
19561 + * buffer setup of an endpoint.
19562 + */
19563 +static void cfi_build_descriptors(struct cfiobject *cfi,
19564 +                                 struct dwc_otg_pcd *pcd,
19565 +                                 struct dwc_otg_pcd_ep *ep,
19566 +                                 dwc_otg_pcd_request_t * req)
19567 +{
19568 +       cfi_ep_t *cfiep;
19569 +
19570 +       /* Get the cfiep by the dwc_otg_pcd_ep */
19571 +       cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
19572 +       if (NULL == cfiep) {
19573 +               CFI_INFO("%s: Unable to find a matching active endpoint\n",
19574 +                        __func__);
19575 +               return;
19576 +       }
19577 +
19578 +       cfiep->xfer_len = req->length;
19579 +
19580 +       /* Iterate through all the DMA descriptors */
19581 +       switch (cfiep->ep->dwc_ep.buff_mode) {
19582 +       case BM_SG:
19583 +               cfi_build_sg_descs(cfi, cfiep, req);
19584 +               break;
19585 +
19586 +       case BM_CONCAT:
19587 +               cfi_build_concat_descs(cfi, cfiep, req);
19588 +               break;
19589 +
19590 +       case BM_CIRCULAR:
19591 +               cfi_build_circ_descs(cfi, cfiep, req);
19592 +               break;
19593 +
19594 +       case BM_ALIGN:
19595 +               cfi_build_align_descs(cfi, cfiep, req);
19596 +               break;
19597 +
19598 +       default:
19599 +               break;
19600 +       }
19601 +}
19602 +
19603 +/**
19604 + * Allocate DMA buffer for different Buffer modes.
19605 + */
19606 +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
19607 +                             struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
19608 +                             unsigned size, gfp_t flags)
19609 +{
19610 +       return DWC_DMA_ALLOC(size, dma);
19611 +}
19612 +
19613 +/**
19614 + * This function initializes the CFI object.
19615 + */
19616 +int init_cfi(cfiobject_t * cfiobj)
19617 +{
19618 +       CFI_INFO("%s\n", __func__);
19619 +
19620 +       /* Allocate a buffer for IN XFERs */
19621 +       cfiobj->buf_in.buf =
19622 +           DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
19623 +       if (NULL == cfiobj->buf_in.buf) {
19624 +               CFI_INFO("Unable to allocate buffer for INs\n");
19625 +               return -DWC_E_NO_MEMORY;
19626 +       }
19627 +
19628 +       /* Allocate a buffer for OUT XFERs */
19629 +       cfiobj->buf_out.buf =
19630 +           DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
19631 +       if (NULL == cfiobj->buf_out.buf) {
19632 +               CFI_INFO("Unable to allocate buffer for OUT\n");
19633 +               return -DWC_E_NO_MEMORY;
19634 +       }
19635 +
19636 +       /* Initialize the callback function pointers */
19637 +       cfiobj->ops.release = cfi_release;
19638 +       cfiobj->ops.ep_enable = cfi_ep_enable;
19639 +       cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
19640 +       cfiobj->ops.build_descriptors = cfi_build_descriptors;
19641 +       cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
19642 +
19643 +       /* Initialize the list of active endpoints in the CFI object */
19644 +       DWC_LIST_INIT(&cfiobj->active_eps);
19645 +
19646 +       return 0;
19647 +}
19648 +
19649 +/**
19650 + * This function reads the required feature's current value into the buffer
19651 + *
19652 + * @retval: Returns negative as error, or the data length of the feature
19653 + */
19654 +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
19655 +                                struct dwc_otg_pcd *pcd,
19656 +                                struct cfi_usb_ctrlrequest *ctrl_req)
19657 +{
19658 +       int retval = -DWC_E_NOT_SUPPORTED;
19659 +       struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
19660 +       uint16_t dfifo, rxfifo, txfifo;
19661 +
19662 +       switch (ctrl_req->wIndex) {
19663 +               /* Whether the DDMA is enabled or not */
19664 +       case FT_ID_DMA_MODE:
19665 +               *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
19666 +               retval = 1;
19667 +               break;
19668 +
19669 +       case FT_ID_DMA_BUFFER_SETUP:
19670 +               retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
19671 +               break;
19672 +
19673 +       case FT_ID_DMA_BUFF_ALIGN:
19674 +               retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
19675 +               break;
19676 +
19677 +       case FT_ID_DMA_CONCAT_SETUP:
19678 +               retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
19679 +               break;
19680 +
19681 +       case FT_ID_DMA_CIRCULAR:
19682 +               CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
19683 +               break;
19684 +
19685 +       case FT_ID_THRESHOLD_SETUP:
19686 +               CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
19687 +               break;
19688 +
19689 +       case FT_ID_DFIFO_DEPTH:
19690 +               dfifo = get_dfifo_size(coreif);
19691 +               *((uint16_t *) buf) = dfifo;
19692 +               retval = sizeof(uint16_t);
19693 +               break;
19694 +
19695 +       case FT_ID_TX_FIFO_DEPTH:
19696 +               retval = get_txfifo_size(pcd, ctrl_req->wValue);
19697 +               if (retval >= 0) {
19698 +                       txfifo = retval;
19699 +                       *((uint16_t *) buf) = txfifo;
19700 +                       retval = sizeof(uint16_t);
19701 +               }
19702 +               break;
19703 +
19704 +       case FT_ID_RX_FIFO_DEPTH:
19705 +               retval = get_rxfifo_size(coreif, ctrl_req->wValue);
19706 +               if (retval >= 0) {
19707 +                       rxfifo = retval;
19708 +                       *((uint16_t *) buf) = rxfifo;
19709 +                       retval = sizeof(uint16_t);
19710 +               }
19711 +               break;
19712 +       }
19713 +
19714 +       return retval;
19715 +}
19716 +
19717 +/**
19718 + * This function resets the SG for the specified EP to its default value
19719 + */
19720 +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
19721 +{
19722 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19723 +       return 0;
19724 +}
19725 +
19726 +/**
19727 + * This function resets the Alignment for the specified EP to its default value
19728 + */
19729 +static int cfi_reset_align_val(cfi_ep_t * cfiep)
19730 +{
19731 +       dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
19732 +       return 0;
19733 +}
19734 +
19735 +/**
19736 + * This function resets the Concatenation for the specified EP to its default value
19737 + * This function will also set the value of the wTxBytes field to NULL after
19738 + * freeing the memory previously allocated for this field.
19739 + */
19740 +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
19741 +{
19742 +       /* First we need to free the wTxBytes field */
19743 +       if (cfiep->bm_concat->wTxBytes) {
19744 +               DWC_FREE(cfiep->bm_concat->wTxBytes);
19745 +               cfiep->bm_concat->wTxBytes = NULL;
19746 +       }
19747 +
19748 +       dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
19749 +       return 0;
19750 +}
19751 +
19752 +/**
19753 + * This function resets all the buffer setups of the specified endpoint
19754 + */
19755 +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
19756 +{
19757 +       cfi_reset_sg_val(cfiep);
19758 +       cfi_reset_align_val(cfiep);
19759 +       cfi_reset_concat_val(cfiep);
19760 +       return 0;
19761 +}
19762 +
19763 +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
19764 +                                    uint8_t rx_rst, uint8_t tx_rst)
19765 +{
19766 +       int retval = -DWC_E_INVALID;
19767 +       uint16_t tx_siz[15];
19768 +       uint16_t rx_siz = 0;
19769 +       dwc_otg_pcd_ep_t *ep = NULL;
19770 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
19771 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
19772 +
19773 +       if (rx_rst) {
19774 +               rx_siz = params->dev_rx_fifo_size;
19775 +               params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
19776 +       }
19777 +
19778 +       if (tx_rst) {
19779 +               if (ep_addr == 0) {
19780 +                       int i;
19781 +
19782 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
19783 +                               tx_siz[i] =
19784 +                                   core_if->core_params->dev_tx_fifo_size[i];
19785 +                               core_if->core_params->dev_tx_fifo_size[i] =
19786 +                                   core_if->init_txfsiz[i];
19787 +                       }
19788 +               } else {
19789 +
19790 +                       ep = get_ep_by_addr(pcd, ep_addr);
19791 +
19792 +                       if (NULL == ep) {
19793 +                               CFI_INFO
19794 +                                   ("%s: Unable to get the endpoint addr=0x%02x\n",
19795 +                                    __func__, ep_addr);
19796 +                               return -DWC_E_INVALID;
19797 +                       }
19798 +
19799 +                       tx_siz[0] =
19800 +                           params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
19801 +                                                    1];
19802 +                       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
19803 +                           GET_CORE_IF(pcd)->init_txfsiz[ep->
19804 +                                                         dwc_ep.tx_fifo_num -
19805 +                                                         1];
19806 +               }
19807 +       }
19808 +
19809 +       if (resize_fifos(GET_CORE_IF(pcd))) {
19810 +               retval = 0;
19811 +       } else {
19812 +               CFI_INFO
19813 +                   ("%s: Error resetting the feature Reset All(FIFO size)\n",
19814 +                    __func__);
19815 +               if (rx_rst) {
19816 +                       params->dev_rx_fifo_size = rx_siz;
19817 +               }
19818 +
19819 +               if (tx_rst) {
19820 +                       if (ep_addr == 0) {
19821 +                               int i;
19822 +                               for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
19823 +                                    i++) {
19824 +                                       core_if->
19825 +                                           core_params->dev_tx_fifo_size[i] =
19826 +                                           tx_siz[i];
19827 +                               }
19828 +                       } else {
19829 +                               params->dev_tx_fifo_size[ep->
19830 +                                                        dwc_ep.tx_fifo_num -
19831 +                                                        1] = tx_siz[0];
19832 +                       }
19833 +               }
19834 +               retval = -DWC_E_INVALID;
19835 +       }
19836 +       return retval;
19837 +}
19838 +
19839 +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
19840 +{
19841 +       int retval = 0;
19842 +       cfi_ep_t *cfiep;
19843 +       cfiobject_t *cfi = pcd->cfi;
19844 +       dwc_list_link_t *tmp;
19845 +
19846 +       retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
19847 +       if (retval < 0) {
19848 +               return retval;
19849 +       }
19850 +
19851 +       /* If the EP address is known then reset the features for only that EP */
19852 +       if (addr) {
19853 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19854 +               if (NULL == cfiep) {
19855 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19856 +                                __func__, addr);
19857 +                       return -DWC_E_INVALID;
19858 +               }
19859 +               retval = cfi_ep_reset_all_setup_vals(cfiep);
19860 +               cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19861 +       }
19862 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19863 +       else {
19864 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19865 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19866 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19867 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19868 +                       retval = cfi_ep_reset_all_setup_vals(cfiep);
19869 +                       cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
19870 +                       if (retval < 0) {
19871 +                               CFI_INFO
19872 +                                   ("%s: Error resetting the feature Reset All\n",
19873 +                                    __func__);
19874 +                               return retval;
19875 +                       }
19876 +               }
19877 +       }
19878 +       return retval;
19879 +}
19880 +
19881 +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
19882 +                                          uint8_t addr)
19883 +{
19884 +       int retval = 0;
19885 +       cfi_ep_t *cfiep;
19886 +       cfiobject_t *cfi = pcd->cfi;
19887 +       dwc_list_link_t *tmp;
19888 +
19889 +       /* If the EP address is known then reset the features for only that EP */
19890 +       if (addr) {
19891 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19892 +               if (NULL == cfiep) {
19893 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19894 +                                __func__, addr);
19895 +                       return -DWC_E_INVALID;
19896 +               }
19897 +               retval = cfi_reset_sg_val(cfiep);
19898 +       }
19899 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19900 +       else {
19901 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19902 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19903 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19904 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19905 +                       retval = cfi_reset_sg_val(cfiep);
19906 +                       if (retval < 0) {
19907 +                               CFI_INFO
19908 +                                   ("%s: Error resetting the feature Buffer Setup\n",
19909 +                                    __func__);
19910 +                               return retval;
19911 +                       }
19912 +               }
19913 +       }
19914 +       return retval;
19915 +}
19916 +
19917 +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19918 +{
19919 +       int retval = 0;
19920 +       cfi_ep_t *cfiep;
19921 +       cfiobject_t *cfi = pcd->cfi;
19922 +       dwc_list_link_t *tmp;
19923 +
19924 +       /* If the EP address is known then reset the features for only that EP */
19925 +       if (addr) {
19926 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19927 +               if (NULL == cfiep) {
19928 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19929 +                                __func__, addr);
19930 +                       return -DWC_E_INVALID;
19931 +               }
19932 +               retval = cfi_reset_concat_val(cfiep);
19933 +       }
19934 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19935 +       else {
19936 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19937 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19938 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19939 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19940 +                       retval = cfi_reset_concat_val(cfiep);
19941 +                       if (retval < 0) {
19942 +                               CFI_INFO
19943 +                                   ("%s: Error resetting the feature Concatenation Value\n",
19944 +                                    __func__);
19945 +                               return retval;
19946 +                       }
19947 +               }
19948 +       }
19949 +       return retval;
19950 +}
19951 +
19952 +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
19953 +{
19954 +       int retval = 0;
19955 +       cfi_ep_t *cfiep;
19956 +       cfiobject_t *cfi = pcd->cfi;
19957 +       dwc_list_link_t *tmp;
19958 +
19959 +       /* If the EP address is known then reset the features for only that EP */
19960 +       if (addr) {
19961 +               cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
19962 +               if (NULL == cfiep) {
19963 +                       CFI_INFO("%s: Error getting the EP address 0x%02x\n",
19964 +                                __func__, addr);
19965 +                       return -DWC_E_INVALID;
19966 +               }
19967 +               retval = cfi_reset_align_val(cfiep);
19968 +       }
19969 +       /* Otherwise (wValue == 0), reset all features of all EP's */
19970 +       else {
19971 +               /* Traverse all the active EP's and reset the feature(s) value(s) */
19972 +               //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
19973 +               DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
19974 +                       cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
19975 +                       retval = cfi_reset_align_val(cfiep);
19976 +                       if (retval < 0) {
19977 +                               CFI_INFO
19978 +                                   ("%s: Error resetting the feature Aliignment Value\n",
19979 +                                    __func__);
19980 +                               return retval;
19981 +                       }
19982 +               }
19983 +       }
19984 +       return retval;
19985 +
19986 +}
19987 +
19988 +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
19989 +                            struct cfi_usb_ctrlrequest *req)
19990 +{
19991 +       int retval = 0;
19992 +
19993 +       switch (req->wIndex) {
19994 +       case 0:
19995 +               /* Reset all features */
19996 +               retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
19997 +               break;
19998 +
19999 +       case FT_ID_DMA_BUFFER_SETUP:
20000 +               /* Reset the SG buffer setup */
20001 +               retval =
20002 +                   cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
20003 +               break;
20004 +
20005 +       case FT_ID_DMA_CONCAT_SETUP:
20006 +               /* Reset the Concatenation buffer setup */
20007 +               retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
20008 +               break;
20009 +
20010 +       case FT_ID_DMA_BUFF_ALIGN:
20011 +               /* Reset the Alignment buffer setup */
20012 +               retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
20013 +               break;
20014 +
20015 +       case FT_ID_TX_FIFO_DEPTH:
20016 +               retval =
20017 +                   cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
20018 +               pcd->cfi->need_gadget_att = 0;
20019 +               break;
20020 +
20021 +       case FT_ID_RX_FIFO_DEPTH:
20022 +               retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
20023 +               pcd->cfi->need_gadget_att = 0;
20024 +               break;
20025 +       default:
20026 +               break;
20027 +       }
20028 +       return retval;
20029 +}
20030 +
20031 +/**
20032 + * This function sets a new value for the SG buffer setup.
20033 + */
20034 +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20035 +{
20036 +       uint8_t inaddr, outaddr;
20037 +       cfi_ep_t *epin, *epout;
20038 +       ddma_sg_buffer_setup_t *psgval;
20039 +       uint32_t desccount, size;
20040 +
20041 +       CFI_INFO("%s\n", __func__);
20042 +
20043 +       psgval = (ddma_sg_buffer_setup_t *) buf;
20044 +       desccount = (uint32_t) psgval->bCount;
20045 +       size = (uint32_t) psgval->wSize;
20046 +
20047 +       /* Check the DMA descriptor count */
20048 +       if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
20049 +               CFI_INFO
20050 +                   ("%s: The count of DMA Descriptors should be between 1 and %d\n",
20051 +                    __func__, MAX_DMA_DESCS_PER_EP);
20052 +               return -DWC_E_INVALID;
20053 +       }
20054 +
20055 +       /* Check the DMA descriptor count */
20056 +
20057 +       if (size == 0) {
20058 +
20059 +               CFI_INFO("%s: The transfer size should be at least 1 byte\n",
20060 +                        __func__);
20061 +
20062 +               return -DWC_E_INVALID;
20063 +
20064 +       }
20065 +
20066 +       inaddr = psgval->bInEndpointAddress;
20067 +       outaddr = psgval->bOutEndpointAddress;
20068 +
20069 +       epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
20070 +       epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
20071 +
20072 +       if (NULL == epin || NULL == epout) {
20073 +               CFI_INFO
20074 +                   ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
20075 +                    __func__, inaddr, outaddr);
20076 +               return -DWC_E_INVALID;
20077 +       }
20078 +
20079 +       epin->ep->dwc_ep.buff_mode = BM_SG;
20080 +       dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20081 +
20082 +       epout->ep->dwc_ep.buff_mode = BM_SG;
20083 +       dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
20084 +
20085 +       return 0;
20086 +}
20087 +
20088 +/**
20089 + * This function sets a new value for the buffer Alignment setup.
20090 + */
20091 +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20092 +{
20093 +       cfi_ep_t *ep;
20094 +       uint8_t addr;
20095 +       ddma_align_buffer_setup_t *palignval;
20096 +
20097 +       palignval = (ddma_align_buffer_setup_t *) buf;
20098 +       addr = palignval->bEndpointAddress;
20099 +
20100 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20101 +
20102 +       if (NULL == ep) {
20103 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20104 +                        __func__, addr);
20105 +               return -DWC_E_INVALID;
20106 +       }
20107 +
20108 +       ep->ep->dwc_ep.buff_mode = BM_ALIGN;
20109 +       dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
20110 +
20111 +       return 0;
20112 +}
20113 +
20114 +/**
20115 + * This function sets a new value for the Concatenation buffer setup.
20116 + */
20117 +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
20118 +{
20119 +       uint8_t addr;
20120 +       cfi_ep_t *ep;
20121 +       struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
20122 +       uint16_t *pVals;
20123 +       uint32_t desccount;
20124 +       int i;
20125 +       uint16_t mps;
20126 +
20127 +       pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
20128 +       desccount = (uint32_t) pConcatValHdr->bDescCount;
20129 +       pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
20130 +
20131 +       /* Check the DMA descriptor count */
20132 +       if (desccount > MAX_DMA_DESCS_PER_EP) {
20133 +               CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
20134 +                        __func__, MAX_DMA_DESCS_PER_EP);
20135 +               return -DWC_E_INVALID;
20136 +       }
20137 +
20138 +       addr = pConcatValHdr->bEndpointAddress;
20139 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20140 +       if (NULL == ep) {
20141 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20142 +                        __func__, addr);
20143 +               return -DWC_E_INVALID;
20144 +       }
20145 +
20146 +       mps = UGETW(ep->ep->desc->wMaxPacketSize);
20147 +
20148 +#if 0
20149 +       for (i = 0; i < desccount; i++) {
20150 +               CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
20151 +       }
20152 +       CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
20153 +#endif
20154 +
20155 +       /* Check the wTxSizes to be less than or equal to the mps */
20156 +       for (i = 0; i < desccount; i++) {
20157 +               if (pVals[i] > mps) {
20158 +                       CFI_INFO
20159 +                           ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
20160 +                            __func__, i, pVals[i]);
20161 +                       return -DWC_E_INVALID;
20162 +               }
20163 +       }
20164 +
20165 +       ep->ep->dwc_ep.buff_mode = BM_CONCAT;
20166 +       dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
20167 +
20168 +       /* Free the previously allocated storage for the wTxBytes */
20169 +       if (ep->bm_concat->wTxBytes) {
20170 +               DWC_FREE(ep->bm_concat->wTxBytes);
20171 +       }
20172 +
20173 +       /* Allocate a new storage for the wTxBytes field */
20174 +       ep->bm_concat->wTxBytes =
20175 +           DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
20176 +       if (NULL == ep->bm_concat->wTxBytes) {
20177 +               CFI_INFO("%s: Unable to allocate memory\n", __func__);
20178 +               return -DWC_E_NO_MEMORY;
20179 +       }
20180 +
20181 +       /* Copy the new values into the wTxBytes filed */
20182 +       dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
20183 +                  sizeof(uint16_t) * pConcatValHdr->bDescCount);
20184 +
20185 +       return 0;
20186 +}
20187 +
20188 +/**
20189 + * This function calculates the total of all FIFO sizes
20190 + *
20191 + * @param core_if Programming view of DWC_otg controller
20192 + *
20193 + * @return The total of data FIFO sizes.
20194 + *
20195 + */
20196 +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
20197 +{
20198 +       dwc_otg_core_params_t *params = core_if->core_params;
20199 +       uint16_t dfifo_total = 0;
20200 +       int i;
20201 +
20202 +       /* The shared RxFIFO size */
20203 +       dfifo_total =
20204 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20205 +
20206 +       /* Add up each TxFIFO size to the total */
20207 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20208 +               dfifo_total += params->dev_tx_fifo_size[i];
20209 +       }
20210 +
20211 +       return dfifo_total;
20212 +}
20213 +
20214 +/**
20215 + * This function returns Rx FIFO size
20216 + *
20217 + * @param core_if Programming view of DWC_otg controller
20218 + *
20219 + * @return The total of data FIFO sizes.
20220 + *
20221 + */
20222 +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
20223 +{
20224 +       switch (wValue >> 8) {
20225 +       case 0:
20226 +               return (core_if->pwron_rxfsiz <
20227 +                       32768) ? core_if->pwron_rxfsiz : 32768;
20228 +               break;
20229 +       case 1:
20230 +               return core_if->core_params->dev_rx_fifo_size;
20231 +               break;
20232 +       default:
20233 +               return -DWC_E_INVALID;
20234 +               break;
20235 +       }
20236 +}
20237 +
20238 +/**
20239 + * This function returns Tx FIFO size for IN EP
20240 + *
20241 + * @param core_if Programming view of DWC_otg controller
20242 + *
20243 + * @return The total of data FIFO sizes.
20244 + *
20245 + */
20246 +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
20247 +{
20248 +       dwc_otg_pcd_ep_t *ep;
20249 +
20250 +       ep = get_ep_by_addr(pcd, wValue & 0xff);
20251 +
20252 +       if (NULL == ep) {
20253 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20254 +                        __func__, wValue & 0xff);
20255 +               return -DWC_E_INVALID;
20256 +       }
20257 +
20258 +       if (!ep->dwc_ep.is_in) {
20259 +               CFI_INFO
20260 +                   ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
20261 +                    __func__, wValue & 0xff);
20262 +               return -DWC_E_INVALID;
20263 +       }
20264 +
20265 +       switch (wValue >> 8) {
20266 +       case 0:
20267 +               return (GET_CORE_IF(pcd)->pwron_txfsiz
20268 +                       [ep->dwc_ep.tx_fifo_num - 1] <
20269 +                       768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
20270 +                                                             dwc_ep.tx_fifo_num
20271 +                                                             - 1] : 32768;
20272 +               break;
20273 +       case 1:
20274 +               return GET_CORE_IF(pcd)->core_params->
20275 +                   dev_tx_fifo_size[ep->dwc_ep.num - 1];
20276 +               break;
20277 +       default:
20278 +               return -DWC_E_INVALID;
20279 +               break;
20280 +       }
20281 +}
20282 +
20283 +/**
20284 + * This function checks if the submitted combination of
20285 + * device mode FIFO sizes is possible or not.
20286 + *
20287 + * @param core_if Programming view of DWC_otg controller
20288 + *
20289 + * @return 1 if possible, 0 otherwise.
20290 + *
20291 + */
20292 +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
20293 +{
20294 +       uint16_t dfifo_actual = 0;
20295 +       dwc_otg_core_params_t *params = core_if->core_params;
20296 +       uint16_t start_addr = 0;
20297 +       int i;
20298 +
20299 +       dfifo_actual =
20300 +           params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
20301 +
20302 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20303 +               dfifo_actual += params->dev_tx_fifo_size[i];
20304 +       }
20305 +
20306 +       if (dfifo_actual > core_if->total_fifo_size) {
20307 +               return 0;
20308 +       }
20309 +
20310 +       if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
20311 +               return 0;
20312 +
20313 +       if (params->dev_nperio_tx_fifo_size > 32768
20314 +           || params->dev_nperio_tx_fifo_size < 16)
20315 +               return 0;
20316 +
20317 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20318 +
20319 +               if (params->dev_tx_fifo_size[i] > 768
20320 +                   || params->dev_tx_fifo_size[i] < 4)
20321 +                       return 0;
20322 +       }
20323 +
20324 +       if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
20325 +               return 0;
20326 +       start_addr = params->dev_rx_fifo_size;
20327 +
20328 +       if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
20329 +               return 0;
20330 +       start_addr += params->dev_nperio_tx_fifo_size;
20331 +
20332 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20333 +
20334 +               if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
20335 +                       return 0;
20336 +               start_addr += params->dev_tx_fifo_size[i];
20337 +       }
20338 +
20339 +       return 1;
20340 +}
20341 +
20342 +/**
20343 + * This function resizes Device mode FIFOs
20344 + *
20345 + * @param core_if Programming view of DWC_otg controller
20346 + *
20347 + * @return 1 if successful, 0 otherwise
20348 + *
20349 + */
20350 +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
20351 +{
20352 +       int i = 0;
20353 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
20354 +       dwc_otg_core_params_t *params = core_if->core_params;
20355 +       uint32_t rx_fifo_size;
20356 +       fifosize_data_t nptxfifosize;
20357 +       fifosize_data_t txfifosize[15];
20358 +
20359 +       uint32_t rx_fsz_bak;
20360 +       uint32_t nptxfsz_bak;
20361 +       uint32_t txfsz_bak[15];
20362 +
20363 +       uint16_t start_address;
20364 +       uint8_t retval = 1;
20365 +
20366 +       if (!check_fifo_sizes(core_if)) {
20367 +               return 0;
20368 +       }
20369 +
20370 +       /* Configure data FIFO sizes */
20371 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
20372 +               rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
20373 +               rx_fifo_size = params->dev_rx_fifo_size;
20374 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
20375 +
20376 +               /*
20377 +                * Tx FIFOs These FIFOs are numbered from 1 to 15.
20378 +                * Indexes of the FIFO size module parameters in the
20379 +                * dev_tx_fifo_size array and the FIFO size registers in
20380 +                * the dtxfsiz array run from 0 to 14.
20381 +                */
20382 +
20383 +               /* Non-periodic Tx FIFO */
20384 +               nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
20385 +               nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
20386 +               start_address = params->dev_rx_fifo_size;
20387 +               nptxfifosize.b.startaddr = start_address;
20388 +
20389 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
20390 +
20391 +               start_address += nptxfifosize.b.depth;
20392 +
20393 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20394 +                       txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
20395 +
20396 +                       txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
20397 +                       txfifosize[i].b.startaddr = start_address;
20398 +                       DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20399 +                                       txfifosize[i].d32);
20400 +
20401 +                       start_address += txfifosize[i].b.depth;
20402 +               }
20403 +
20404 +               /** Check if register values are set correctly */
20405 +               if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
20406 +                       retval = 0;
20407 +               }
20408 +
20409 +               if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
20410 +                       retval = 0;
20411 +               }
20412 +
20413 +               for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20414 +                       if (txfifosize[i].d32 !=
20415 +                           DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
20416 +                               retval = 0;
20417 +                       }
20418 +               }
20419 +
20420 +               /** If register values are not set correctly, reset old values */
20421 +               if (retval == 0) {
20422 +                       DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
20423 +
20424 +                       /* Non-periodic Tx FIFO */
20425 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
20426 +
20427 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
20428 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
20429 +                                               txfsz_bak[i]);
20430 +                       }
20431 +               }
20432 +       } else {
20433 +               return 0;
20434 +       }
20435 +
20436 +       /* Flush the FIFOs */
20437 +       dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
20438 +       dwc_otg_flush_rx_fifo(core_if);
20439 +
20440 +       return retval;
20441 +}
20442 +
20443 +/**
20444 + * This function sets a new value for the buffer Alignment setup.
20445 + */
20446 +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20447 +{
20448 +       int retval;
20449 +       uint32_t fsiz;
20450 +       uint16_t size;
20451 +       uint16_t ep_addr;
20452 +       dwc_otg_pcd_ep_t *ep;
20453 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20454 +       tx_fifo_size_setup_t *ptxfifoval;
20455 +
20456 +       ptxfifoval = (tx_fifo_size_setup_t *) buf;
20457 +       ep_addr = ptxfifoval->bEndpointAddress;
20458 +       size = ptxfifoval->wDepth;
20459 +
20460 +       ep = get_ep_by_addr(pcd, ep_addr);
20461 +
20462 +       CFI_INFO
20463 +           ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
20464 +            __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
20465 +
20466 +       if (NULL == ep) {
20467 +               CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
20468 +                        __func__, ep_addr);
20469 +               return -DWC_E_INVALID;
20470 +       }
20471 +
20472 +       fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
20473 +       params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
20474 +
20475 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20476 +               retval = 0;
20477 +       } else {
20478 +               CFI_INFO
20479 +                   ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
20480 +                    __func__, ep_addr);
20481 +               params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
20482 +               retval = -DWC_E_INVALID;
20483 +       }
20484 +
20485 +       return retval;
20486 +}
20487 +
20488 +/**
20489 + * This function sets a new value for the buffer Alignment setup.
20490 + */
20491 +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
20492 +{
20493 +       int retval;
20494 +       uint32_t fsiz;
20495 +       uint16_t size;
20496 +       dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
20497 +       rx_fifo_size_setup_t *prxfifoval;
20498 +
20499 +       prxfifoval = (rx_fifo_size_setup_t *) buf;
20500 +       size = prxfifoval->wDepth;
20501 +
20502 +       fsiz = params->dev_rx_fifo_size;
20503 +       params->dev_rx_fifo_size = size;
20504 +
20505 +       if (resize_fifos(GET_CORE_IF(pcd))) {
20506 +               retval = 0;
20507 +       } else {
20508 +               CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
20509 +                        __func__);
20510 +               params->dev_rx_fifo_size = fsiz;
20511 +               retval = -DWC_E_INVALID;
20512 +       }
20513 +
20514 +       return retval;
20515 +}
20516 +
20517 +/**
20518 + * This function reads the SG of an EP's buffer setup into the buffer buf
20519 + */
20520 +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20521 +                            struct cfi_usb_ctrlrequest *req)
20522 +{
20523 +       int retval = -DWC_E_INVALID;
20524 +       uint8_t addr;
20525 +       cfi_ep_t *ep;
20526 +
20527 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20528 +       addr = req->wValue & 0xFF;
20529 +       if (addr == 0)          /* The address should be non-zero */
20530 +               return retval;
20531 +
20532 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20533 +       if (NULL == ep) {
20534 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20535 +                        __func__, addr);
20536 +               return retval;
20537 +       }
20538 +
20539 +       dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
20540 +       retval = BS_SG_VAL_DESC_LEN;
20541 +       return retval;
20542 +}
20543 +
20544 +/**
20545 + * This function reads the Concatenation value of an EP's buffer mode into
20546 + * the buffer buf
20547 + */
20548 +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20549 +                                struct cfi_usb_ctrlrequest *req)
20550 +{
20551 +       int retval = -DWC_E_INVALID;
20552 +       uint8_t addr;
20553 +       cfi_ep_t *ep;
20554 +       uint8_t desc_count;
20555 +
20556 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20557 +       addr = req->wValue & 0xFF;
20558 +       if (addr == 0)          /* The address should be non-zero */
20559 +               return retval;
20560 +
20561 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20562 +       if (NULL == ep) {
20563 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20564 +                        __func__, addr);
20565 +               return retval;
20566 +       }
20567 +
20568 +       /* Copy the header to the buffer */
20569 +       dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
20570 +       /* Advance the buffer pointer by the header size */
20571 +       buf += BS_CONCAT_VAL_HDR_LEN;
20572 +
20573 +       desc_count = ep->bm_concat->hdr.bDescCount;
20574 +       /* Copy alll the wTxBytes to the buffer */
20575 +       dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
20576 +
20577 +       retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
20578 +       return retval;
20579 +}
20580 +
20581 +/**
20582 + * This function reads the buffer Alignment value of an EP's buffer mode into
20583 + * the buffer buf
20584 + *
20585 + * @return The total number of bytes copied to the buffer or negative error code.
20586 + */
20587 +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
20588 +                               struct cfi_usb_ctrlrequest *req)
20589 +{
20590 +       int retval = -DWC_E_INVALID;
20591 +       uint8_t addr;
20592 +       cfi_ep_t *ep;
20593 +
20594 +       /* The Low Byte of the wValue contains a non-zero address of the endpoint */
20595 +       addr = req->wValue & 0xFF;
20596 +       if (addr == 0)          /* The address should be non-zero */
20597 +               return retval;
20598 +
20599 +       ep = get_cfi_ep_by_addr(pcd->cfi, addr);
20600 +       if (NULL == ep) {
20601 +               CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
20602 +                        __func__, addr);
20603 +               return retval;
20604 +       }
20605 +
20606 +       dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
20607 +       retval = BS_ALIGN_VAL_HDR_LEN;
20608 +
20609 +       return retval;
20610 +}
20611 +
20612 +/**
20613 + * This function sets a new value for the specified feature
20614 + *
20615 + * @param      pcd     A pointer to the PCD object
20616 + *
20617 + * @return 0 if successful, negative error code otherwise to stall the DCE.
20618 + */
20619 +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
20620 +{
20621 +       int retval = -DWC_E_NOT_SUPPORTED;
20622 +       uint16_t wIndex, wValue;
20623 +       uint8_t bRequest;
20624 +       struct dwc_otg_core_if *coreif;
20625 +       cfiobject_t *cfi = pcd->cfi;
20626 +       struct cfi_usb_ctrlrequest *ctrl_req;
20627 +       uint8_t *buf;
20628 +       ctrl_req = &cfi->ctrl_req;
20629 +
20630 +       buf = pcd->cfi->ctrl_req.data;
20631 +
20632 +       coreif = GET_CORE_IF(pcd);
20633 +       bRequest = ctrl_req->bRequest;
20634 +       wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
20635 +       wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
20636 +
20637 +       /* See which feature is to be modified */
20638 +       switch (wIndex) {
20639 +       case FT_ID_DMA_BUFFER_SETUP:
20640 +               /* Modify the feature */
20641 +               if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
20642 +                       return retval;
20643 +
20644 +               /* And send this request to the gadget */
20645 +               cfi->need_gadget_att = 1;
20646 +               break;
20647 +
20648 +       case FT_ID_DMA_BUFF_ALIGN:
20649 +               if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
20650 +                       return retval;
20651 +               cfi->need_gadget_att = 1;
20652 +               break;
20653 +
20654 +       case FT_ID_DMA_CONCAT_SETUP:
20655 +               /* Modify the feature */
20656 +               if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
20657 +                       return retval;
20658 +               cfi->need_gadget_att = 1;
20659 +               break;
20660 +
20661 +       case FT_ID_DMA_CIRCULAR:
20662 +               CFI_INFO("FT_ID_DMA_CIRCULAR\n");
20663 +               break;
20664 +
20665 +       case FT_ID_THRESHOLD_SETUP:
20666 +               CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
20667 +               break;
20668 +
20669 +       case FT_ID_DFIFO_DEPTH:
20670 +               CFI_INFO("FT_ID_DFIFO_DEPTH\n");
20671 +               break;
20672 +
20673 +       case FT_ID_TX_FIFO_DEPTH:
20674 +               CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
20675 +               if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
20676 +                       return retval;
20677 +               cfi->need_gadget_att = 0;
20678 +               break;
20679 +
20680 +       case FT_ID_RX_FIFO_DEPTH:
20681 +               CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
20682 +               if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
20683 +                       return retval;
20684 +               cfi->need_gadget_att = 0;
20685 +               break;
20686 +       }
20687 +
20688 +       return retval;
20689 +}
20690 +
20691 +#endif //DWC_UTE_CFI
20692 --- /dev/null
20693 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
20694 @@ -0,0 +1,320 @@
20695 +/* ==========================================================================
20696 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
20697 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
20698 + * otherwise expressly agreed to in writing between Synopsys and you.
20699 + *
20700 + * The Software IS NOT an item of Licensed Software or Licensed Product under
20701 + * any End User Software License Agreement or Agreement for Licensed Product
20702 + * with Synopsys or any supplement thereto. You are permitted to use and
20703 + * redistribute this Software in source and binary forms, with or without
20704 + * modification, provided that redistributions of source code must retain this
20705 + * notice. You may not view, use, disclose, copy or distribute this file or
20706 + * any information contained herein except pursuant to this license grant from
20707 + * Synopsys. If you do not agree with this notice, including the disclaimer
20708 + * below, then you are not authorized to use the Software.
20709 + *
20710 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
20711 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20712 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20713 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
20714 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20715 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20716 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20717 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20718 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20719 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20720 + * DAMAGE.
20721 + * ========================================================================== */
20722 +
20723 +#if !defined(__DWC_OTG_CFI_H__)
20724 +#define __DWC_OTG_CFI_H__
20725 +
20726 +#include "dwc_otg_pcd.h"
20727 +#include "dwc_cfi_common.h"
20728 +
20729 +/**
20730 + * @file
20731 + * This file contains the CFI related OTG PCD specific common constants,
20732 + * interfaces(functions and macros) and data structures.The CFI Protocol is an
20733 + * optional interface for internal testing purposes that a DUT may implement to
20734 + * support testing of configurable features.
20735 + *
20736 + */
20737 +
20738 +struct dwc_otg_pcd;
20739 +struct dwc_otg_pcd_ep;
20740 +
20741 +/** OTG CFI Features (properties) ID constants */
20742 +/** This is a request for all Core Features */
20743 +#define FT_ID_DMA_MODE                                 0x0001
20744 +#define FT_ID_DMA_BUFFER_SETUP                 0x0002
20745 +#define FT_ID_DMA_BUFF_ALIGN                   0x0003
20746 +#define FT_ID_DMA_CONCAT_SETUP                 0x0004
20747 +#define FT_ID_DMA_CIRCULAR                             0x0005
20748 +#define FT_ID_THRESHOLD_SETUP                  0x0006
20749 +#define FT_ID_DFIFO_DEPTH                              0x0007
20750 +#define FT_ID_TX_FIFO_DEPTH                            0x0008
20751 +#define FT_ID_RX_FIFO_DEPTH                            0x0009
20752 +
20753 +/**********************************************************/
20754 +#define CFI_INFO_DEF
20755 +
20756 +#ifdef CFI_INFO_DEF
20757 +#define CFI_INFO(fmt...)       DWC_PRINTF("CFI: " fmt);
20758 +#else
20759 +#define CFI_INFO(fmt...)
20760 +#endif
20761 +
20762 +#define min(x,y) ({ \
20763 +       x < y ? x : y; })
20764 +
20765 +#define max(x,y) ({ \
20766 +       x > y ? x : y; })
20767 +
20768 +/**
20769 + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
20770 + * also used for setting up a buffer for Circular DDMA.
20771 + */
20772 +struct _ddma_sg_buffer_setup {
20773 +#define BS_SG_VAL_DESC_LEN     6
20774 +       /* The OUT EP address */
20775 +       uint8_t bOutEndpointAddress;
20776 +       /* The IN EP address */
20777 +       uint8_t bInEndpointAddress;
20778 +       /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
20779 +       uint8_t bOffset;
20780 +       /* The number of transfer segments (a DMA descriptors per each segment) */
20781 +       uint8_t bCount;
20782 +       /* Size (in byte) of each transfer segment */
20783 +       uint16_t wSize;
20784 +} __attribute__ ((packed));
20785 +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
20786 +
20787 +/** Descriptor DMA Concatenation Buffer setup structure */
20788 +struct _ddma_concat_buffer_setup_hdr {
20789 +#define BS_CONCAT_VAL_HDR_LEN  4
20790 +       /* The endpoint for which the buffer is to be set up */
20791 +       uint8_t bEndpointAddress;
20792 +       /* The count of descriptors to be used */
20793 +       uint8_t bDescCount;
20794 +       /* The total size of the transfer */
20795 +       uint16_t wSize;
20796 +} __attribute__ ((packed));
20797 +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
20798 +
20799 +/** Descriptor DMA Concatenation Buffer setup structure */
20800 +struct _ddma_concat_buffer_setup {
20801 +       /* The SG header */
20802 +       ddma_concat_buffer_setup_hdr_t hdr;
20803 +
20804 +       /* The XFER sizes pointer (allocated dynamically) */
20805 +       uint16_t *wTxBytes;
20806 +} __attribute__ ((packed));
20807 +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
20808 +
20809 +/** Descriptor DMA Alignment Buffer setup structure */
20810 +struct _ddma_align_buffer_setup {
20811 +#define BS_ALIGN_VAL_HDR_LEN   2
20812 +       uint8_t bEndpointAddress;
20813 +       uint8_t bAlign;
20814 +} __attribute__ ((packed));
20815 +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
20816 +
20817 +/** Transmit FIFO Size setup structure */
20818 +struct _tx_fifo_size_setup {
20819 +       uint8_t bEndpointAddress;
20820 +       uint16_t wDepth;
20821 +} __attribute__ ((packed));
20822 +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
20823 +
20824 +/** Transmit FIFO Size setup structure */
20825 +struct _rx_fifo_size_setup {
20826 +       uint16_t wDepth;
20827 +} __attribute__ ((packed));
20828 +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
20829 +
20830 +/**
20831 + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
20832 + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer
20833 + * to the data returned in the data stage of a 3-stage Control Write requests.
20834 + */
20835 +struct cfi_usb_ctrlrequest {
20836 +       uint8_t bRequestType;
20837 +       uint8_t bRequest;
20838 +       uint16_t wValue;
20839 +       uint16_t wIndex;
20840 +       uint16_t wLength;
20841 +       uint8_t *data;
20842 +} UPACKED;
20843 +
20844 +/*---------------------------------------------------------------------------*/
20845 +
20846 +/**
20847 + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
20848 + * This structure is used to store the buffer setup data for any
20849 + * enabled endpoint in the PCD.
20850 + */
20851 +struct cfi_ep {
20852 +       /* Entry for the list container */
20853 +       dwc_list_link_t lh;
20854 +       /* Pointer to the active PCD endpoint structure */
20855 +       struct dwc_otg_pcd_ep *ep;
20856 +       /* The last descriptor in the chain of DMA descriptors of the endpoint */
20857 +       struct dwc_otg_dma_desc *dma_desc_last;
20858 +       /* The SG feature value */
20859 +       ddma_sg_buffer_setup_t *bm_sg;
20860 +       /* The Circular feature value */
20861 +       ddma_sg_buffer_setup_t *bm_circ;
20862 +       /* The Concatenation feature value */
20863 +       ddma_concat_buffer_setup_t *bm_concat;
20864 +       /* The Alignment feature value */
20865 +       ddma_align_buffer_setup_t *bm_align;
20866 +       /* XFER length */
20867 +       uint32_t xfer_len;
20868 +       /*
20869 +        * Count of DMA descriptors currently used.
20870 +        * The total should not exceed the MAX_DMA_DESCS_PER_EP value
20871 +        * defined in the dwc_otg_cil.h
20872 +        */
20873 +       uint32_t desc_count;
20874 +};
20875 +typedef struct cfi_ep cfi_ep_t;
20876 +
20877 +typedef struct cfi_dma_buff {
20878 +#define CFI_IN_BUF_LEN 1024
20879 +#define CFI_OUT_BUF_LEN        1024
20880 +       dma_addr_t addr;
20881 +       uint8_t *buf;
20882 +} cfi_dma_buff_t;
20883 +
20884 +struct cfiobject;
20885 +
20886 +/**
20887 + * This is the interface for the CFI operations.
20888 + *
20889 + * @param      ep_enable                       Called when any endpoint is enabled and activated.
20890 + * @param      release                         Called when the CFI object is released and it needs to correctly
20891 + *                                                             deallocate the dynamic memory
20892 + * @param      ctrl_write_complete     Called when the data stage of the request is complete
20893 + */
20894 +typedef struct cfi_ops {
20895 +       int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20896 +                         struct dwc_otg_pcd_ep * ep);
20897 +       void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
20898 +                              struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
20899 +                              unsigned size, gfp_t flags);
20900 +       void (*release) (struct cfiobject * cfi);
20901 +       int (*ctrl_write_complete) (struct cfiobject * cfi,
20902 +                                   struct dwc_otg_pcd * pcd);
20903 +       void (*build_descriptors) (struct cfiobject * cfi,
20904 +                                  struct dwc_otg_pcd * pcd,
20905 +                                  struct dwc_otg_pcd_ep * ep,
20906 +                                  dwc_otg_pcd_request_t * req);
20907 +} cfi_ops_t;
20908 +
20909 +struct cfiobject {
20910 +       cfi_ops_t ops;
20911 +       struct dwc_otg_pcd *pcd;
20912 +       struct usb_gadget *gadget;
20913 +
20914 +       /* Buffers used to send/receive CFI-related request data */
20915 +       cfi_dma_buff_t buf_in;
20916 +       cfi_dma_buff_t buf_out;
20917 +
20918 +       /* CFI specific Control request wrapper */
20919 +       struct cfi_usb_ctrlrequest ctrl_req;
20920 +
20921 +       /* The list of active EP's in the PCD of type cfi_ep_t */
20922 +       dwc_list_link_t active_eps;
20923 +
20924 +       /* This flag shall control the propagation of a specific request
20925 +        * to the gadget's processing routines.
20926 +        * 0 - no gadget handling
20927 +        * 1 - the gadget needs to know about this request (w/o completing a status
20928 +        * phase - just return a 0 to the _setup callback)
20929 +        */
20930 +       uint8_t need_gadget_att;
20931 +
20932 +       /* Flag indicating whether the status IN phase needs to be
20933 +        * completed by the PCD
20934 +        */
20935 +       uint8_t need_status_in_complete;
20936 +};
20937 +typedef struct cfiobject cfiobject_t;
20938 +
20939 +#define DUMP_MSG
20940 +
20941 +#if defined(DUMP_MSG)
20942 +static inline void dump_msg(const u8 * buf, unsigned int length)
20943 +{
20944 +       unsigned int start, num, i;
20945 +       char line[52], *p;
20946 +
20947 +       if (length >= 512)
20948 +               return;
20949 +
20950 +       start = 0;
20951 +       while (length > 0) {
20952 +               num = min(length, 16u);
20953 +               p = line;
20954 +               for (i = 0; i < num; ++i) {
20955 +                       if (i == 8)
20956 +                               *p++ = ' ';
20957 +                       DWC_SPRINTF(p, " %02x", buf[i]);
20958 +                       p += 3;
20959 +               }
20960 +               *p = 0;
20961 +               DWC_DEBUG("%6x: %s\n", start, line);
20962 +               buf += num;
20963 +               start += num;
20964 +               length -= num;
20965 +       }
20966 +}
20967 +#else
20968 +static inline void dump_msg(const u8 * buf, unsigned int length)
20969 +{
20970 +}
20971 +#endif
20972 +
20973 +/**
20974 + * This function returns a pointer to cfi_ep_t object with the addr address.
20975 + */
20976 +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
20977 +                                               uint8_t addr)
20978 +{
20979 +       struct cfi_ep *pcfiep;
20980 +       dwc_list_link_t *tmp;
20981 +
20982 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
20983 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
20984 +
20985 +               if (pcfiep->ep->desc->bEndpointAddress == addr) {
20986 +                       return pcfiep;
20987 +               }
20988 +       }
20989 +
20990 +       return NULL;
20991 +}
20992 +
20993 +/**
20994 + * This function returns a pointer to cfi_ep_t object that matches
20995 + * the dwc_otg_pcd_ep object.
20996 + */
20997 +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
20998 +                                                 struct dwc_otg_pcd_ep *ep)
20999 +{
21000 +       struct cfi_ep *pcfiep = NULL;
21001 +       dwc_list_link_t *tmp;
21002 +
21003 +       DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
21004 +               pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
21005 +               if (pcfiep->ep == ep) {
21006 +                       return pcfiep;
21007 +               }
21008 +       }
21009 +       return NULL;
21010 +}
21011 +
21012 +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
21013 +
21014 +#endif /* (__DWC_OTG_CFI_H__) */
21015 --- /dev/null
21016 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
21017 @@ -0,0 +1,7151 @@
21018 +/* ==========================================================================
21019 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
21020 + * $Revision: #191 $
21021 + * $Date: 2012/08/10 $
21022 + * $Change: 2047372 $
21023 + *
21024 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
21025 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
21026 + * otherwise expressly agreed to in writing between Synopsys and you.
21027 + *
21028 + * The Software IS NOT an item of Licensed Software or Licensed Product under
21029 + * any End User Software License Agreement or Agreement for Licensed Product
21030 + * with Synopsys or any supplement thereto. You are permitted to use and
21031 + * redistribute this Software in source and binary forms, with or without
21032 + * modification, provided that redistributions of source code must retain this
21033 + * notice. You may not view, use, disclose, copy or distribute this file or
21034 + * any information contained herein except pursuant to this license grant from
21035 + * Synopsys. If you do not agree with this notice, including the disclaimer
21036 + * below, then you are not authorized to use the Software.
21037 + *
21038 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
21039 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21040 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21041 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
21042 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21043 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21044 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21045 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21046 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21047 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
21048 + * DAMAGE.
21049 + * ========================================================================== */
21050 +
21051 +/** @file
21052 + *
21053 + * The Core Interface Layer provides basic services for accessing and
21054 + * managing the DWC_otg hardware. These services are used by both the
21055 + * Host Controller Driver and the Peripheral Controller Driver.
21056 + *
21057 + * The CIL manages the memory map for the core so that the HCD and PCD
21058 + * don't have to do this separately. It also handles basic tasks like
21059 + * reading/writing the registers and data FIFOs in the controller.
21060 + * Some of the data access functions provide encapsulation of several
21061 + * operations required to perform a task, such as writing multiple
21062 + * registers to start a transfer. Finally, the CIL performs basic
21063 + * services that are not specific to either the host or device modes
21064 + * of operation. These services include management of the OTG Host
21065 + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
21066 + * Diagnostic API is also provided to allow testing of the controller
21067 + * hardware.
21068 + *
21069 + * The Core Interface Layer has the following requirements:
21070 + * - Provides basic controller operations.
21071 + * - Minimal use of OS services.
21072 + * - The OS services used will be abstracted by using inline functions
21073 + *      or macros.
21074 + *
21075 + */
21076 +
21077 +#include "dwc_os.h"
21078 +#include "dwc_otg_regs.h"
21079 +#include "dwc_otg_cil.h"
21080 +
21081 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
21082 +
21083 +/**
21084 + * This function is called to initialize the DWC_otg CSR data
21085 + * structures. The register addresses in the device and host
21086 + * structures are initialized from the base address supplied by the
21087 + * caller. The calling function must make the OS calls to get the
21088 + * base address of the DWC_otg controller registers. The core_params
21089 + * argument holds the parameters that specify how the core should be
21090 + * configured.
21091 + *
21092 + * @param reg_base_addr Base address of DWC_otg core registers
21093 + *
21094 + */
21095 +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
21096 +{
21097 +       dwc_otg_core_if_t *core_if = 0;
21098 +       dwc_otg_dev_if_t *dev_if = 0;
21099 +       dwc_otg_host_if_t *host_if = 0;
21100 +       uint8_t *reg_base = (uint8_t *) reg_base_addr;
21101 +       int i = 0;
21102 +
21103 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
21104 +
21105 +       core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));
21106 +
21107 +       if (core_if == NULL) {
21108 +               DWC_DEBUGPL(DBG_CIL,
21109 +                           "Allocation of dwc_otg_core_if_t failed\n");
21110 +               return 0;
21111 +       }
21112 +       core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
21113 +
21114 +       /*
21115 +        * Allocate the Device Mode structures.
21116 +        */
21117 +       dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));
21118 +
21119 +       if (dev_if == NULL) {
21120 +               DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
21121 +               DWC_FREE(core_if);
21122 +               return 0;
21123 +       }
21124 +
21125 +       dev_if->dev_global_regs =
21126 +           (dwc_otg_device_global_regs_t *) (reg_base +
21127 +                                             DWC_DEV_GLOBAL_REG_OFFSET);
21128 +
21129 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21130 +               dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
21131 +                   (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
21132 +                    (i * DWC_EP_REG_OFFSET));
21133 +
21134 +               dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
21135 +                   (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
21136 +                    (i * DWC_EP_REG_OFFSET));
21137 +               DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
21138 +                           i, &dev_if->in_ep_regs[i]->diepctl);
21139 +               DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
21140 +                           i, &dev_if->out_ep_regs[i]->doepctl);
21141 +       }
21142 +
21143 +       dev_if->speed = 0;      // unknown
21144 +
21145 +       core_if->dev_if = dev_if;
21146 +
21147 +       /*
21148 +        * Allocate the Host Mode structures.
21149 +        */
21150 +       host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));
21151 +
21152 +       if (host_if == NULL) {
21153 +               DWC_DEBUGPL(DBG_CIL,
21154 +                           "Allocation of dwc_otg_host_if_t failed\n");
21155 +               DWC_FREE(dev_if);
21156 +               DWC_FREE(core_if);
21157 +               return 0;
21158 +       }
21159 +
21160 +       host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
21161 +           (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
21162 +
21163 +       host_if->hprt0 =
21164 +           (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
21165 +
21166 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21167 +               host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
21168 +                   (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
21169 +                    (i * DWC_OTG_CHAN_REGS_OFFSET));
21170 +               DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
21171 +                           i, &host_if->hc_regs[i]->hcchar);
21172 +       }
21173 +
21174 +       host_if->num_host_channels = MAX_EPS_CHANNELS;
21175 +       core_if->host_if = host_if;
21176 +
21177 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21178 +               core_if->data_fifo[i] =
21179 +                   (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
21180 +                                 (i * DWC_OTG_DATA_FIFO_SIZE));
21181 +               DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",
21182 +                           i, (unsigned long)core_if->data_fifo[i]);
21183 +       }
21184 +
21185 +       core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
21186 +
21187 +       /* Initiate lx_state to L3 disconnected state */
21188 +       core_if->lx_state = DWC_OTG_L3;
21189 +       /*
21190 +        * Store the contents of the hardware configuration registers here for
21191 +        * easy access later.
21192 +        */
21193 +       core_if->hwcfg1.d32 =
21194 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
21195 +       core_if->hwcfg2.d32 =
21196 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
21197 +       core_if->hwcfg3.d32 =
21198 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
21199 +       core_if->hwcfg4.d32 =
21200 +           DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
21201 +
21202 +       /* Force host mode to get HPTXFSIZ exact power on value */
21203 +       {
21204 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
21205 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21206 +               gusbcfg.b.force_host_mode = 1;
21207 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21208 +               dwc_mdelay(100);
21209 +               core_if->hptxfsiz.d32 =
21210 +               DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21211 +               gusbcfg.d32 =  DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21212 +               gusbcfg.b.force_host_mode = 0;
21213 +               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
21214 +               dwc_mdelay(100);
21215 +       }
21216 +
21217 +       DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
21218 +       DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
21219 +       DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
21220 +       DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
21221 +
21222 +       core_if->hcfg.d32 =
21223 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21224 +       core_if->dcfg.d32 =
21225 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21226 +
21227 +       DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
21228 +       DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
21229 +
21230 +       DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
21231 +       DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
21232 +       DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
21233 +       DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
21234 +                   core_if->hwcfg2.b.num_host_chan);
21235 +       DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
21236 +                   core_if->hwcfg2.b.nonperio_tx_q_depth);
21237 +       DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
21238 +                   core_if->hwcfg2.b.host_perio_tx_q_depth);
21239 +       DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
21240 +                   core_if->hwcfg2.b.dev_token_q_depth);
21241 +
21242 +       DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
21243 +                   core_if->hwcfg3.b.dfifo_depth);
21244 +       DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
21245 +                   core_if->hwcfg3.b.xfer_size_cntr_width);
21246 +
21247 +       /*
21248 +        * Set the SRP sucess bit for FS-I2c
21249 +        */
21250 +       core_if->srp_success = 0;
21251 +       core_if->srp_timer_started = 0;
21252 +
21253 +       /*
21254 +        * Create new workqueue and init works
21255 +        */
21256 +       core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
21257 +       if (core_if->wq_otg == 0) {
21258 +               DWC_WARN("DWC_WORKQ_ALLOC failed\n");
21259 +               DWC_FREE(host_if);
21260 +               DWC_FREE(dev_if);
21261 +               DWC_FREE(core_if);
21262 +               return 0;
21263 +       }
21264 +
21265 +       core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
21266 +
21267 +       DWC_PRINTF("Core Release: %x.%x%x%x\n",
21268 +                  (core_if->snpsid >> 12 & 0xF),
21269 +                  (core_if->snpsid >> 8 & 0xF),
21270 +                  (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
21271 +
21272 +       core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
21273 +                                            w_wakeup_detected, core_if);
21274 +       if (core_if->wkp_timer == 0) {
21275 +               DWC_WARN("DWC_TIMER_ALLOC failed\n");
21276 +               DWC_FREE(host_if);
21277 +               DWC_FREE(dev_if);
21278 +               DWC_WORKQ_FREE(core_if->wq_otg);
21279 +               DWC_FREE(core_if);
21280 +               return 0;
21281 +       }
21282 +
21283 +       if (dwc_otg_setup_params(core_if)) {
21284 +               DWC_WARN("Error while setting core params\n");
21285 +       }
21286 +
21287 +       core_if->hibernation_suspend = 0;
21288 +
21289 +       /** ADP initialization */
21290 +       dwc_otg_adp_init(core_if);
21291 +
21292 +       return core_if;
21293 +}
21294 +
21295 +/**
21296 + * This function frees the structures allocated by dwc_otg_cil_init().
21297 + *
21298 + * @param core_if The core interface pointer returned from
21299 + *               dwc_otg_cil_init().
21300 + *
21301 + */
21302 +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
21303 +{
21304 +       dctl_data_t dctl = {.d32 = 0 };
21305 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
21306 +
21307 +       /* Disable all interrupts */
21308 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);
21309 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
21310 +
21311 +       dctl.b.sftdiscon = 1;
21312 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
21313 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,
21314 +                                dctl.d32);
21315 +       }
21316 +
21317 +       if (core_if->wq_otg) {
21318 +               DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
21319 +               DWC_WORKQ_FREE(core_if->wq_otg);
21320 +       }
21321 +       if (core_if->dev_if) {
21322 +               DWC_FREE(core_if->dev_if);
21323 +       }
21324 +       if (core_if->host_if) {
21325 +               DWC_FREE(core_if->host_if);
21326 +       }
21327 +
21328 +       /** Remove ADP Stuff  */
21329 +       dwc_otg_adp_remove(core_if);
21330 +       if (core_if->core_params) {
21331 +               DWC_FREE(core_if->core_params);
21332 +       }
21333 +       if (core_if->wkp_timer) {
21334 +               DWC_TIMER_FREE(core_if->wkp_timer);
21335 +       }
21336 +       if (core_if->srp_timer) {
21337 +               DWC_TIMER_FREE(core_if->srp_timer);
21338 +       }
21339 +       DWC_FREE(core_if);
21340 +}
21341 +
21342 +/**
21343 + * This function enables the controller's Global Interrupt in the AHB Config
21344 + * register.
21345 + *
21346 + * @param core_if Programming view of DWC_otg controller.
21347 + */
21348 +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
21349 +{
21350 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21351 +       ahbcfg.b.glblintrmsk = 1;       /* Enable interrupts */
21352 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
21353 +}
21354 +
21355 +/**
21356 + * This function disables the controller's Global Interrupt in the AHB Config
21357 + * register.
21358 + *
21359 + * @param core_if Programming view of DWC_otg controller.
21360 + */
21361 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
21362 +{
21363 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
21364 +       ahbcfg.b.glblintrmsk = 1;       /* Disable interrupts */
21365 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
21366 +}
21367 +
21368 +/**
21369 + * This function initializes the commmon interrupts, used in both
21370 + * device and host modes.
21371 + *
21372 + * @param core_if Programming view of the DWC_otg controller
21373 + *
21374 + */
21375 +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
21376 +{
21377 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
21378 +       gintmsk_data_t intr_mask = {.d32 = 0 };
21379 +
21380 +       /* Clear any pending OTG Interrupts */
21381 +       DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);
21382 +
21383 +       /* Clear any pending interrupts */
21384 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
21385 +
21386 +       /*
21387 +        * Enable the interrupts in the GINTMSK.
21388 +        */
21389 +       intr_mask.b.modemismatch = 1;
21390 +       intr_mask.b.otgintr = 1;
21391 +
21392 +       if (!core_if->dma_enable) {
21393 +               intr_mask.b.rxstsqlvl = 1;
21394 +       }
21395 +
21396 +       intr_mask.b.conidstschng = 1;
21397 +       intr_mask.b.wkupintr = 1;
21398 +       intr_mask.b.disconnect = 0;
21399 +       intr_mask.b.usbsuspend = 1;
21400 +       intr_mask.b.sessreqintr = 1;
21401 +#ifdef CONFIG_USB_DWC_OTG_LPM
21402 +       if (core_if->core_params->lpm_enable) {
21403 +               intr_mask.b.lpmtranrcvd = 1;
21404 +       }
21405 +#endif
21406 +       DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
21407 +}
21408 +
21409 +/*
21410 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21411 + * Hibernation. This function is for exiting from Device mode hibernation by
21412 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21413 + * @param core_if Programming view of DWC_otg controller.
21414 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21415 + * @param reset - indicates whether resume is initiated by Reset.
21416 + */
21417 +int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
21418 +                                      int rem_wakeup, int reset)
21419 +{
21420 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21421 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
21422 +       dctl_data_t dctl = {.d32 = 0 };
21423 +
21424 +       int timeout = 2000;
21425 +
21426 +       if (!core_if->hibernation_suspend) {
21427 +               DWC_PRINTF("Already exited from Hibernation\n");
21428 +               return 1;
21429 +       }
21430 +
21431 +       DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);
21432 +       /* Switch-on voltage to the core */
21433 +       gpwrdn.b.pwrdnswtch = 1;
21434 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21435 +       dwc_udelay(10);
21436 +
21437 +       /* Reset core */
21438 +       gpwrdn.d32 = 0;
21439 +       gpwrdn.b.pwrdnrstn = 1;
21440 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21441 +       dwc_udelay(10);
21442 +
21443 +       /* Assert Restore signal */
21444 +       gpwrdn.d32 = 0;
21445 +       gpwrdn.b.restore = 1;
21446 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21447 +       dwc_udelay(10);
21448 +
21449 +       /* Disable power clamps */
21450 +       gpwrdn.d32 = 0;
21451 +       gpwrdn.b.pwrdnclmp = 1;
21452 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21453 +
21454 +       if (rem_wakeup) {
21455 +               dwc_udelay(70);
21456 +       }
21457 +
21458 +       /* Deassert Reset core */
21459 +       gpwrdn.d32 = 0;
21460 +       gpwrdn.b.pwrdnrstn = 1;
21461 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21462 +       dwc_udelay(10);
21463 +
21464 +       /* Disable PMU interrupt */
21465 +       gpwrdn.d32 = 0;
21466 +       gpwrdn.b.pmuintsel = 1;
21467 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21468 +
21469 +       /* Mask interrupts from gpwrdn */
21470 +       gpwrdn.d32 = 0;
21471 +       gpwrdn.b.connect_det_msk = 1;
21472 +       gpwrdn.b.srp_det_msk = 1;
21473 +       gpwrdn.b.disconn_det_msk = 1;
21474 +       gpwrdn.b.rst_det_msk = 1;
21475 +       gpwrdn.b.lnstchng_msk = 1;
21476 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21477 +
21478 +       /* Indicates that we are going out from hibernation */
21479 +       core_if->hibernation_suspend = 0;
21480 +
21481 +       /*
21482 +        * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1
21483 +        * indicates restore from remote_wakeup
21484 +        */
21485 +       restore_essential_regs(core_if, rem_wakeup, 0);
21486 +
21487 +       /*
21488 +        * Wait a little for seeing new value of variable hibernation_suspend if
21489 +        * Restore done interrupt received before polling
21490 +        */
21491 +       dwc_udelay(10);
21492 +
21493 +       if (core_if->hibernation_suspend == 0) {
21494 +               /*
21495 +                * Wait For Restore_done Interrupt. This mechanism of polling the
21496 +                * interrupt is introduced to avoid any possible race conditions
21497 +                */
21498 +               do {
21499 +                       gintsts_data_t gintsts;
21500 +                       gintsts.d32 =
21501 +                           DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21502 +                       if (gintsts.b.restoredone) {
21503 +                               gintsts.d32 = 0;
21504 +                               gintsts.b.restoredone = 1;
21505 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
21506 +                                               gintsts, gintsts.d32);
21507 +                               DWC_PRINTF("Restore Done Interrupt seen\n");
21508 +                               break;
21509 +                       }
21510 +                       dwc_udelay(10);
21511 +               } while (--timeout);
21512 +               if (!timeout) {
21513 +                       DWC_PRINTF("Restore Done interrupt wasn't generated here\n");
21514 +               }
21515 +       }
21516 +       /* Clear all pending interupts */
21517 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21518 +
21519 +       /* De-assert Restore */
21520 +       gpwrdn.d32 = 0;
21521 +       gpwrdn.b.restore = 1;
21522 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21523 +       dwc_udelay(10);
21524 +
21525 +       if (!rem_wakeup) {
21526 +               pcgcctl.d32 = 0;
21527 +               pcgcctl.b.rstpdwnmodule = 1;
21528 +               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
21529 +       }
21530 +
21531 +       /* Restore GUSBCFG and DCFG */
21532 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21533 +                       core_if->gr_backup->gusbcfg_local);
21534 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
21535 +                       core_if->dr_backup->dcfg);
21536 +
21537 +       /* De-assert Wakeup Logic */
21538 +       gpwrdn.d32 = 0;
21539 +       gpwrdn.b.pmuactv = 1;
21540 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21541 +       dwc_udelay(10);
21542 +
21543 +       if (!rem_wakeup) {
21544 +               /* Set Device programming done bit */
21545 +               dctl.b.pwronprgdone = 1;
21546 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
21547 +       } else {
21548 +               /* Start Remote Wakeup Signaling */
21549 +               dctl.d32 = core_if->dr_backup->dctl;
21550 +               dctl.b.rmtwkupsig = 1;
21551 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
21552 +       }
21553 +
21554 +       dwc_mdelay(2);
21555 +       /* Clear all pending interupts */
21556 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21557 +
21558 +       /* Restore global registers */
21559 +       dwc_otg_restore_global_regs(core_if);
21560 +       /* Restore device global registers */
21561 +       dwc_otg_restore_dev_regs(core_if, rem_wakeup);
21562 +
21563 +       if (rem_wakeup) {
21564 +               dwc_mdelay(7);
21565 +               dctl.d32 = 0;
21566 +               dctl.b.rmtwkupsig = 1;
21567 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
21568 +       }
21569 +
21570 +       core_if->hibernation_suspend = 0;
21571 +       /* The core will be in ON STATE */
21572 +       core_if->lx_state = DWC_OTG_L0;
21573 +       DWC_PRINTF("Hibernation recovery completes here\n");
21574 +
21575 +       return 1;
21576 +}
21577 +
21578 +/*
21579 + * The restore operation is modified to support Synopsys Emulated Powerdown and
21580 + * Hibernation. This function is for exiting from Host mode hibernation by
21581 + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
21582 + * @param core_if Programming view of DWC_otg controller.
21583 + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
21584 + * @param reset - indicates whether resume is initiated by Reset.
21585 + */
21586 +int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
21587 +                                    int rem_wakeup, int reset)
21588 +{
21589 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
21590 +       hprt0_data_t hprt0 = {.d32 = 0 };
21591 +
21592 +       int timeout = 2000;
21593 +
21594 +       DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);
21595 +       /* Switch-on voltage to the core */
21596 +       gpwrdn.b.pwrdnswtch = 1;
21597 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21598 +       dwc_udelay(10);
21599 +
21600 +       /* Reset core */
21601 +       gpwrdn.d32 = 0;
21602 +       gpwrdn.b.pwrdnrstn = 1;
21603 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21604 +       dwc_udelay(10);
21605 +
21606 +       /* Assert Restore signal */
21607 +       gpwrdn.d32 = 0;
21608 +       gpwrdn.b.restore = 1;
21609 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21610 +       dwc_udelay(10);
21611 +
21612 +       /* Disable power clamps */
21613 +       gpwrdn.d32 = 0;
21614 +       gpwrdn.b.pwrdnclmp = 1;
21615 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21616 +
21617 +       if (!rem_wakeup) {
21618 +               dwc_udelay(50);
21619 +       }
21620 +
21621 +       /* Deassert Reset core */
21622 +       gpwrdn.d32 = 0;
21623 +       gpwrdn.b.pwrdnrstn = 1;
21624 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
21625 +       dwc_udelay(10);
21626 +
21627 +       /* Disable PMU interrupt */
21628 +       gpwrdn.d32 = 0;
21629 +       gpwrdn.b.pmuintsel = 1;
21630 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21631 +
21632 +       gpwrdn.d32 = 0;
21633 +       gpwrdn.b.connect_det_msk = 1;
21634 +       gpwrdn.b.srp_det_msk = 1;
21635 +       gpwrdn.b.disconn_det_msk = 1;
21636 +       gpwrdn.b.rst_det_msk = 1;
21637 +       gpwrdn.b.lnstchng_msk = 1;
21638 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21639 +
21640 +       /* Indicates that we are going out from hibernation */
21641 +       core_if->hibernation_suspend = 0;
21642 +
21643 +       /* Set Restore Essential Regs bit in PCGCCTL register */
21644 +       restore_essential_regs(core_if, rem_wakeup, 1);
21645 +
21646 +       /* Wait a little for seeing new value of variable hibernation_suspend if
21647 +        * Restore done interrupt received before polling */
21648 +       dwc_udelay(10);
21649 +
21650 +       if (core_if->hibernation_suspend == 0) {
21651 +               /* Wait For Restore_done Interrupt. This mechanism of polling the
21652 +                * interrupt is introduced to avoid any possible race conditions
21653 +                */
21654 +               do {
21655 +                       gintsts_data_t gintsts;
21656 +                       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
21657 +                       if (gintsts.b.restoredone) {
21658 +                               gintsts.d32 = 0;
21659 +                               gintsts.b.restoredone = 1;
21660 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
21661 +                               DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");
21662 +                               break;
21663 +                       }
21664 +                       dwc_udelay(10);
21665 +               } while (--timeout);
21666 +               if (!timeout) {
21667 +                       DWC_WARN("Restore Done interrupt wasn't generated\n");
21668 +               }
21669 +       }
21670 +
21671 +       /* Set the flag's value to 0 again after receiving restore done interrupt */
21672 +       core_if->hibernation_suspend = 0;
21673 +
21674 +       /* This step is not described in functional spec but if not wait for this
21675 +        * delay, mismatch interrupts occurred because just after restore core is
21676 +        * in Device mode(gintsts.curmode == 0) */
21677 +       dwc_mdelay(100);
21678 +
21679 +       /* Clear all pending interrupts */
21680 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21681 +
21682 +       /* De-assert Restore */
21683 +       gpwrdn.d32 = 0;
21684 +       gpwrdn.b.restore = 1;
21685 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21686 +       dwc_udelay(10);
21687 +
21688 +       /* Restore GUSBCFG and HCFG */
21689 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
21690 +                       core_if->gr_backup->gusbcfg_local);
21691 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
21692 +                       core_if->hr_backup->hcfg_local);
21693 +
21694 +       /* De-assert Wakeup Logic */
21695 +       gpwrdn.d32 = 0;
21696 +       gpwrdn.b.pmuactv = 1;
21697 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
21698 +       dwc_udelay(10);
21699 +
21700 +       /* Start the Resume operation by programming HPRT0 */
21701 +       hprt0.d32 = core_if->hr_backup->hprt0_local;
21702 +       hprt0.b.prtpwr = 1;
21703 +       hprt0.b.prtena = 0;
21704 +       hprt0.b.prtsusp = 0;
21705 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21706 +
21707 +       DWC_PRINTF("Resume Starts Now\n");
21708 +       if (!reset) {           // Indicates it is Resume Operation
21709 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21710 +               hprt0.b.prtres = 1;
21711 +               hprt0.b.prtpwr = 1;
21712 +               hprt0.b.prtena = 0;
21713 +               hprt0.b.prtsusp = 0;
21714 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21715 +
21716 +               if (!rem_wakeup)
21717 +                       hprt0.b.prtres = 0;
21718 +               /* Wait for Resume time and then program HPRT again */
21719 +               dwc_mdelay(100);
21720 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21721 +
21722 +       } else {                // Indicates it is Reset Operation
21723 +               hprt0.d32 = core_if->hr_backup->hprt0_local;
21724 +               hprt0.b.prtrst = 1;
21725 +               hprt0.b.prtpwr = 1;
21726 +               hprt0.b.prtena = 0;
21727 +               hprt0.b.prtsusp = 0;
21728 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21729 +               /* Wait for Reset time and then program HPRT again */
21730 +               dwc_mdelay(60);
21731 +               hprt0.b.prtrst = 0;
21732 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21733 +       }
21734 +       /* Clear all interrupt status */
21735 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
21736 +       hprt0.b.prtconndet = 1;
21737 +       hprt0.b.prtenchng = 1;
21738 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
21739 +
21740 +       /* Clear all pending interupts */
21741 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21742 +
21743 +       /* Restore global registers */
21744 +       dwc_otg_restore_global_regs(core_if);
21745 +       /* Restore host global registers */
21746 +       dwc_otg_restore_host_regs(core_if, reset);
21747 +
21748 +       /* The core will be in ON STATE */
21749 +       core_if->lx_state = DWC_OTG_L0;
21750 +       DWC_PRINTF("Hibernation recovery is complete here\n");
21751 +       return 0;
21752 +}
21753 +
21754 +/** Saves some register values into system memory. */
21755 +int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)
21756 +{
21757 +       struct dwc_otg_global_regs_backup *gr;
21758 +       int i;
21759 +
21760 +       gr = core_if->gr_backup;
21761 +       if (!gr) {
21762 +               gr = DWC_ALLOC(sizeof(*gr));
21763 +               if (!gr) {
21764 +                       return -DWC_E_NO_MEMORY;
21765 +               }
21766 +               core_if->gr_backup = gr;
21767 +       }
21768 +
21769 +       gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
21770 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21771 +       gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
21772 +       gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
21773 +       gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
21774 +       gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
21775 +       gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
21776 +#ifdef CONFIG_USB_DWC_OTG_LPM
21777 +       gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
21778 +#endif
21779 +       gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);
21780 +       gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);
21781 +       gr->gdfifocfg_local =
21782 +           DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);
21783 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21784 +               gr->dtxfsiz_local[i] =
21785 +                   DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));
21786 +       }
21787 +
21788 +       DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");
21789 +       DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl   = %08x\n", gr->gotgctl_local);
21790 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21791 +       DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg   = %08x\n", gr->gahbcfg_local);
21792 +       DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg   = %08x\n", gr->gusbcfg_local);
21793 +       DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz   = %08x\n", gr->grxfsiz_local);
21794 +       DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",
21795 +                   gr->gnptxfsiz_local);
21796 +       DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz  = %08x\n",
21797 +                   gr->hptxfsiz_local);
21798 +#ifdef CONFIG_USB_DWC_OTG_LPM
21799 +       DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg   = %08x\n", gr->glpmcfg_local);
21800 +#endif
21801 +       DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl   = %08x\n", gr->gi2cctl_local);
21802 +       DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl   = %08x\n", gr->pcgcctl_local);
21803 +       DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg   = %08x\n",gr->gdfifocfg_local);
21804 +
21805 +       return 0;
21806 +}
21807 +
21808 +/** Saves GINTMSK register before setting the msk bits. */
21809 +int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)
21810 +{
21811 +       struct dwc_otg_global_regs_backup *gr;
21812 +
21813 +       gr = core_if->gr_backup;
21814 +       if (!gr) {
21815 +               gr = DWC_ALLOC(sizeof(*gr));
21816 +               if (!gr) {
21817 +                       return -DWC_E_NO_MEMORY;
21818 +               }
21819 +               core_if->gr_backup = gr;
21820 +       }
21821 +
21822 +       gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
21823 +
21824 +       DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");
21825 +       DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk   = %08x\n", gr->gintmsk_local);
21826 +
21827 +       return 0;
21828 +}
21829 +
21830 +int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)
21831 +{
21832 +       struct dwc_otg_dev_regs_backup *dr;
21833 +       int i;
21834 +
21835 +       dr = core_if->dr_backup;
21836 +       if (!dr) {
21837 +               dr = DWC_ALLOC(sizeof(*dr));
21838 +               if (!dr) {
21839 +                       return -DWC_E_NO_MEMORY;
21840 +               }
21841 +               core_if->dr_backup = dr;
21842 +       }
21843 +
21844 +       dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
21845 +       dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
21846 +       dr->daintmsk =
21847 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
21848 +       dr->diepmsk =
21849 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);
21850 +       dr->doepmsk =
21851 +           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);
21852 +
21853 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21854 +               dr->diepctl[i] =
21855 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
21856 +               dr->dieptsiz[i] =
21857 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);
21858 +               dr->diepdma[i] =
21859 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
21860 +       }
21861 +
21862 +       DWC_DEBUGPL(DBG_ANY,
21863 +                   "=============Backing Host registers==============\n");
21864 +       DWC_DEBUGPL(DBG_ANY, "Backed up dcfg            = %08x\n", dr->dcfg);
21865 +       DWC_DEBUGPL(DBG_ANY, "Backed up dctl        = %08x\n", dr->dctl);
21866 +       DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk            = %08x\n",
21867 +                   dr->daintmsk);
21868 +       DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk        = %08x\n", dr->diepmsk);
21869 +       DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk        = %08x\n", dr->doepmsk);
21870 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21871 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d]        = %08x\n", i,
21872 +                           dr->diepctl[i]);
21873 +               DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d]        = %08x\n",
21874 +                           i, dr->dieptsiz[i]);
21875 +               DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d]        = %08x\n", i,
21876 +                           dr->diepdma[i]);
21877 +       }
21878 +
21879 +       return 0;
21880 +}
21881 +
21882 +int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)
21883 +{
21884 +       struct dwc_otg_host_regs_backup *hr;
21885 +       int i;
21886 +
21887 +       hr = core_if->hr_backup;
21888 +       if (!hr) {
21889 +               hr = DWC_ALLOC(sizeof(*hr));
21890 +               if (!hr) {
21891 +                       return -DWC_E_NO_MEMORY;
21892 +               }
21893 +               core_if->hr_backup = hr;
21894 +       }
21895 +
21896 +       hr->hcfg_local =
21897 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
21898 +       hr->haintmsk_local =
21899 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
21900 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21901 +               hr->hcintmsk_local[i] =
21902 +                   DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);
21903 +       }
21904 +       hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);
21905 +       hr->hfir_local =
21906 +           DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
21907 +
21908 +       DWC_DEBUGPL(DBG_ANY,
21909 +                   "=============Backing Host registers===============\n");
21910 +       DWC_DEBUGPL(DBG_ANY, "Backed up hcfg            = %08x\n",
21911 +                   hr->hcfg_local);
21912 +       DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);
21913 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
21914 +               DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,
21915 +                           hr->hcintmsk_local[i]);
21916 +       }
21917 +       DWC_DEBUGPL(DBG_ANY, "Backed up hprt0           = %08x\n",
21918 +                   hr->hprt0_local);
21919 +       DWC_DEBUGPL(DBG_ANY, "Backed up hfir           = %08x\n",
21920 +                   hr->hfir_local);
21921 +
21922 +       return 0;
21923 +}
21924 +
21925 +int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)
21926 +{
21927 +       struct dwc_otg_global_regs_backup *gr;
21928 +       int i;
21929 +
21930 +       gr = core_if->gr_backup;
21931 +       if (!gr) {
21932 +               return -DWC_E_INVALID;
21933 +       }
21934 +
21935 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
21936 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
21937 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
21938 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);
21939 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);
21940 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,
21941 +                       gr->gnptxfsiz_local);
21942 +       DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,
21943 +                       gr->hptxfsiz_local);
21944 +       DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,
21945 +                       gr->gdfifocfg_local);
21946 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
21947 +               DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],
21948 +                               gr->dtxfsiz_local[i]);
21949 +       }
21950 +
21951 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
21952 +       DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);
21953 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,
21954 +                       (gr->gahbcfg_local));
21955 +       return 0;
21956 +}
21957 +
21958 +int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)
21959 +{
21960 +       struct dwc_otg_dev_regs_backup *dr;
21961 +       int i;
21962 +
21963 +       dr = core_if->dr_backup;
21964 +
21965 +       if (!dr) {
21966 +               return -DWC_E_INVALID;
21967 +       }
21968 +
21969 +       if (!rem_wakeup) {
21970 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
21971 +                               dr->dctl);
21972 +       }
21973 +
21974 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
21975 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
21976 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
21977 +
21978 +       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
21979 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
21980 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
21981 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);
21982 +       }
21983 +
21984 +       return 0;
21985 +}
21986 +
21987 +int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)
21988 +{
21989 +       struct dwc_otg_host_regs_backup *hr;
21990 +       int i;
21991 +       hr = core_if->hr_backup;
21992 +
21993 +       if (!hr) {
21994 +               return -DWC_E_INVALID;
21995 +       }
21996 +
21997 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);
21998 +       //if (!reset)
21999 +       //{
22000 +       //      DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);
22001 +       //}
22002 +
22003 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,
22004 +                       hr->haintmsk_local);
22005 +       for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
22006 +               DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,
22007 +                               hr->hcintmsk_local[i]);
22008 +       }
22009 +
22010 +       return 0;
22011 +}
22012 +
22013 +int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)
22014 +{
22015 +       struct dwc_otg_global_regs_backup *gr;
22016 +
22017 +       gr = core_if->gr_backup;
22018 +
22019 +       /* Restore values for LPM and I2C */
22020 +#ifdef CONFIG_USB_DWC_OTG_LPM
22021 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);
22022 +#endif
22023 +       DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);
22024 +
22025 +       return 0;
22026 +}
22027 +
22028 +int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)
22029 +{
22030 +       struct dwc_otg_global_regs_backup *gr;
22031 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
22032 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
22033 +       gusbcfg_data_t gusbcfg = {.d32 = 0 };
22034 +       gintmsk_data_t gintmsk = {.d32 = 0 };
22035 +
22036 +       /* Restore LPM and I2C registers */
22037 +       restore_lpm_i2c_regs(core_if);
22038 +
22039 +       /* Set PCGCCTL to 0 */
22040 +       DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);
22041 +
22042 +       gr = core_if->gr_backup;
22043 +       /* Load restore values for [31:14] bits */
22044 +       DWC_WRITE_REG32(core_if->pcgcctl,
22045 +                       ((gr->pcgcctl_local & 0xffffc000) | 0x00020000));
22046 +
22047 +       /* Umnask global Interrupt in GAHBCFG and restore it */
22048 +       gahbcfg.d32 = gr->gahbcfg_local;
22049 +       gahbcfg.b.glblintrmsk = 1;
22050 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
22051 +
22052 +       /* Clear all pending interupts */
22053 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
22054 +
22055 +       /* Unmask restore done interrupt */
22056 +       gintmsk.b.restoredone = 1;
22057 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
22058 +
22059 +       /* Restore GUSBCFG and HCFG/DCFG */
22060 +       gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;
22061 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
22062 +
22063 +       if (is_host) {
22064 +               hcfg_data_t hcfg = {.d32 = 0 };
22065 +               hcfg.d32 = core_if->hr_backup->hcfg_local;
22066 +               DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
22067 +                               hcfg.d32);
22068 +
22069 +               /* Load restore values for [31:14] bits */
22070 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22071 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22072 +
22073 +               if (rmode)
22074 +                       pcgcctl.b.restoremode = 1;
22075 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22076 +               dwc_udelay(10);
22077 +
22078 +               /* Load restore values for [31:14] bits and set EssRegRestored bit */
22079 +               pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;
22080 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22081 +               pcgcctl.b.ess_reg_restored = 1;
22082 +               if (rmode)
22083 +                       pcgcctl.b.restoremode = 1;
22084 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22085 +       } else {
22086 +               dcfg_data_t dcfg = {.d32 = 0 };
22087 +               dcfg.d32 = core_if->dr_backup->dcfg;
22088 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22089 +
22090 +               /* Load restore values for [31:14] bits */
22091 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22092 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22093 +               if (!rmode) {
22094 +                       pcgcctl.d32 |= 0x208;
22095 +               }
22096 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22097 +               dwc_udelay(10);
22098 +
22099 +               /* Load restore values for [31:14] bits */
22100 +               pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
22101 +               pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
22102 +               pcgcctl.b.ess_reg_restored = 1;
22103 +               if (!rmode)
22104 +                       pcgcctl.d32 |= 0x208;
22105 +               DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
22106 +       }
22107 +
22108 +       return 0;
22109 +}
22110 +
22111 +/**
22112 + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
22113 + * type.
22114 + */
22115 +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
22116 +{
22117 +       uint32_t val;
22118 +       hcfg_data_t hcfg;
22119 +
22120 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22121 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22122 +            (core_if->core_params->ulpi_fs_ls)) ||
22123 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22124 +               /* Full speed PHY */
22125 +               val = DWC_HCFG_48_MHZ;
22126 +       } else {
22127 +               /* High speed PHY running at full speed or high speed */
22128 +               val = DWC_HCFG_30_60_MHZ;
22129 +       }
22130 +
22131 +       DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
22132 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
22133 +       hcfg.b.fslspclksel = val;
22134 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
22135 +}
22136 +
22137 +/**
22138 + * Initializes the DevSpd field of the DCFG register depending on the PHY type
22139 + * and the enumeration speed of the device.
22140 + */
22141 +static void init_devspd(dwc_otg_core_if_t * core_if)
22142 +{
22143 +       uint32_t val;
22144 +       dcfg_data_t dcfg;
22145 +
22146 +       if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
22147 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
22148 +            (core_if->core_params->ulpi_fs_ls)) ||
22149 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22150 +               /* Full speed PHY */
22151 +               val = 0x3;
22152 +       } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
22153 +               /* High speed PHY running at full speed */
22154 +               val = 0x1;
22155 +       } else {
22156 +               /* High speed PHY running at high speed */
22157 +               val = 0x0;
22158 +       }
22159 +
22160 +       DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
22161 +
22162 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
22163 +       dcfg.b.devspd = val;
22164 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
22165 +}
22166 +
22167 +/**
22168 + * This function calculates the number of IN EPS
22169 + * using GHWCFG1 and GHWCFG2 registers values
22170 + *
22171 + * @param core_if Programming view of the DWC_otg controller
22172 + */
22173 +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
22174 +{
22175 +       uint32_t num_in_eps = 0;
22176 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22177 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
22178 +       uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
22179 +       int i;
22180 +
22181 +       for (i = 0; i < num_eps; ++i) {
22182 +               if (!(hwcfg1 & 0x1))
22183 +                       num_in_eps++;
22184 +
22185 +               hwcfg1 >>= 2;
22186 +       }
22187 +
22188 +       if (core_if->hwcfg4.b.ded_fifo_en) {
22189 +               num_in_eps =
22190 +                   (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
22191 +       }
22192 +
22193 +       return num_in_eps;
22194 +}
22195 +
22196 +/**
22197 + * This function calculates the number of OUT EPS
22198 + * using GHWCFG1 and GHWCFG2 registers values
22199 + *
22200 + * @param core_if Programming view of the DWC_otg controller
22201 + */
22202 +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
22203 +{
22204 +       uint32_t num_out_eps = 0;
22205 +       uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
22206 +       uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
22207 +       int i;
22208 +
22209 +       for (i = 0; i < num_eps; ++i) {
22210 +               if (!(hwcfg1 & 0x1))
22211 +                       num_out_eps++;
22212 +
22213 +               hwcfg1 >>= 2;
22214 +       }
22215 +       return num_out_eps;
22216 +}
22217 +
22218 +/**
22219 + * This function initializes the DWC_otg controller registers and
22220 + * prepares the core for device mode or host mode operation.
22221 + *
22222 + * @param core_if Programming view of the DWC_otg controller
22223 + *
22224 + */
22225 +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
22226 +{
22227 +       int i = 0;
22228 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22229 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22230 +       gahbcfg_data_t ahbcfg = {.d32 = 0 };
22231 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
22232 +       gi2cctl_data_t i2cctl = {.d32 = 0 };
22233 +
22234 +       DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
22235 +                    core_if, global_regs);
22236 +
22237 +       /* Common Initialization */
22238 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22239 +
22240 +       /* Program the ULPI External VBUS bit if needed */
22241 +       usbcfg.b.ulpi_ext_vbus_drv =
22242 +           (core_if->core_params->phy_ulpi_ext_vbus ==
22243 +            DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
22244 +
22245 +       /* Set external TS Dline pulsing */
22246 +       usbcfg.b.term_sel_dl_pulse =
22247 +           (core_if->core_params->ts_dline == 1) ? 1 : 0;
22248 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22249 +
22250 +       /* Reset the Controller */
22251 +       dwc_otg_core_reset(core_if);
22252 +
22253 +       core_if->adp_enable = core_if->core_params->adp_supp_enable;
22254 +       core_if->power_down = core_if->core_params->power_down;
22255 +       core_if->otg_sts = 0;
22256 +
22257 +       /* Initialize parameters from Hardware configuration registers. */
22258 +       dev_if->num_in_eps = calc_num_in_eps(core_if);
22259 +       dev_if->num_out_eps = calc_num_out_eps(core_if);
22260 +
22261 +       DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
22262 +                   core_if->hwcfg4.b.num_dev_perio_in_ep);
22263 +
22264 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22265 +               dev_if->perio_tx_fifo_size[i] =
22266 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22267 +               DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
22268 +                           i, dev_if->perio_tx_fifo_size[i]);
22269 +       }
22270 +
22271 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22272 +               dev_if->tx_fifo_size[i] =
22273 +                   DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
22274 +               DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
22275 +                           i, dev_if->tx_fifo_size[i]);
22276 +       }
22277 +
22278 +       core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
22279 +       core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
22280 +       core_if->nperio_tx_fifo_size =
22281 +           DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
22282 +
22283 +       DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
22284 +       DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
22285 +       DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
22286 +                   core_if->nperio_tx_fifo_size);
22287 +
22288 +       /* This programming sequence needs to happen in FS mode before any other
22289 +        * programming occurs */
22290 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
22291 +           (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
22292 +               /* If FS mode with FS PHY */
22293 +
22294 +               /* core_init() is now called on every switch so only call the
22295 +                * following for the first time through. */
22296 +               if (!core_if->phy_init_done) {
22297 +                       core_if->phy_init_done = 1;
22298 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
22299 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22300 +                       usbcfg.b.physel = 1;
22301 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22302 +
22303 +                       /* Reset after a PHY select */
22304 +                       dwc_otg_core_reset(core_if);
22305 +               }
22306 +
22307 +               /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also
22308 +                * do this on HNP Dev/Host mode switches (done in dev_init and
22309 +                * host_init). */
22310 +               if (dwc_otg_is_host_mode(core_if)) {
22311 +                       init_fslspclksel(core_if);
22312 +               } else {
22313 +                       init_devspd(core_if);
22314 +               }
22315 +
22316 +               if (core_if->core_params->i2c_enable) {
22317 +                       DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
22318 +                       /* Program GUSBCFG.OtgUtmifsSel to I2C */
22319 +                       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22320 +                       usbcfg.b.otgutmifssel = 1;
22321 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22322 +
22323 +                       /* Program GI2CCTL.I2CEn */
22324 +                       i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);
22325 +                       i2cctl.b.i2cdevaddr = 1;
22326 +                       i2cctl.b.i2cen = 0;
22327 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22328 +                       i2cctl.b.i2cen = 1;
22329 +                       DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
22330 +               }
22331 +
22332 +       } /* endif speed == DWC_SPEED_PARAM_FULL */
22333 +       else {
22334 +               /* High speed PHY. */
22335 +               if (!core_if->phy_init_done) {
22336 +                       core_if->phy_init_done = 1;
22337 +                       /* HS PHY parameters.  These parameters are preserved
22338 +                        * during soft reset so only program the first time.  Do
22339 +                        * a soft reset immediately after setting phyif.  */
22340 +
22341 +                       if (core_if->core_params->phy_type == 2) {
22342 +                               /* ULPI interface */
22343 +                               usbcfg.b.ulpi_utmi_sel = 1;
22344 +                               usbcfg.b.phyif = 0;
22345 +                               usbcfg.b.ddrsel =
22346 +                                   core_if->core_params->phy_ulpi_ddr;
22347 +                       } else if (core_if->core_params->phy_type == 1) {
22348 +                               /* UTMI+ interface */
22349 +                               usbcfg.b.ulpi_utmi_sel = 0;
22350 +                               if (core_if->core_params->phy_utmi_width == 16) {
22351 +                                       usbcfg.b.phyif = 1;
22352 +
22353 +                               } else {
22354 +                                       usbcfg.b.phyif = 0;
22355 +                               }
22356 +                       } else {
22357 +                               DWC_ERROR("FS PHY TYPE\n");
22358 +                       }
22359 +                       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22360 +                       /* Reset after setting the PHY parameters */
22361 +                       dwc_otg_core_reset(core_if);
22362 +               }
22363 +       }
22364 +
22365 +       if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
22366 +           (core_if->hwcfg2.b.fs_phy_type == 1) &&
22367 +           (core_if->core_params->ulpi_fs_ls)) {
22368 +               DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
22369 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22370 +               usbcfg.b.ulpi_fsls = 1;
22371 +               usbcfg.b.ulpi_clk_sus_m = 1;
22372 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22373 +       } else {
22374 +               usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22375 +               usbcfg.b.ulpi_fsls = 0;
22376 +               usbcfg.b.ulpi_clk_sus_m = 0;
22377 +               DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22378 +       }
22379 +
22380 +       /* Program the GAHBCFG Register. */
22381 +       switch (core_if->hwcfg2.b.architecture) {
22382 +
22383 +       case DWC_SLAVE_ONLY_ARCH:
22384 +               DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
22385 +               ahbcfg.b.nptxfemplvl_txfemplvl =
22386 +                   DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22387 +               ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
22388 +               core_if->dma_enable = 0;
22389 +               core_if->dma_desc_enable = 0;
22390 +               break;
22391 +
22392 +       case DWC_EXT_DMA_ARCH:
22393 +               DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
22394 +               {
22395 +                       uint8_t brst_sz = core_if->core_params->dma_burst_size;
22396 +                       ahbcfg.b.hburstlen = 0;
22397 +                       while (brst_sz > 1) {
22398 +                               ahbcfg.b.hburstlen++;
22399 +                               brst_sz >>= 1;
22400 +                       }
22401 +               }
22402 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22403 +               core_if->dma_desc_enable =
22404 +                   (core_if->core_params->dma_desc_enable != 0);
22405 +               break;
22406 +
22407 +       case DWC_INT_DMA_ARCH:
22408 +               DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
22409 +               /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
22410 +                 Host mode ISOC in issue fix - vahrama */
22411 +               /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */
22412 +               ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;
22413 +               core_if->dma_enable = (core_if->core_params->dma_enable != 0);
22414 +               core_if->dma_desc_enable =
22415 +                   (core_if->core_params->dma_desc_enable != 0);
22416 +               break;
22417 +
22418 +       }
22419 +       if (core_if->dma_enable) {
22420 +               if (core_if->dma_desc_enable) {
22421 +                       DWC_PRINTF("Using Descriptor DMA mode\n");
22422 +               } else {
22423 +                       DWC_PRINTF("Using Buffer DMA mode\n");
22424 +
22425 +               }
22426 +       } else {
22427 +               DWC_PRINTF("Using Slave mode\n");
22428 +               core_if->dma_desc_enable = 0;
22429 +       }
22430 +
22431 +       if (core_if->core_params->ahb_single) {
22432 +               ahbcfg.b.ahbsingle = 1;
22433 +       }
22434 +
22435 +       ahbcfg.b.dmaenable = core_if->dma_enable;
22436 +       DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
22437 +
22438 +       core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
22439 +
22440 +       core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
22441 +       core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
22442 +       DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
22443 +                  ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
22444 +       DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
22445 +                  ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
22446 +
22447 +       /*
22448 +        * Program the GUSBCFG register.
22449 +        */
22450 +       usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
22451 +
22452 +       switch (core_if->hwcfg2.b.op_mode) {
22453 +       case DWC_MODE_HNP_SRP_CAPABLE:
22454 +               usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
22455 +                                  DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
22456 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22457 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22458 +               break;
22459 +
22460 +       case DWC_MODE_SRP_ONLY_CAPABLE:
22461 +               usbcfg.b.hnpcap = 0;
22462 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22463 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22464 +               break;
22465 +
22466 +       case DWC_MODE_NO_HNP_SRP_CAPABLE:
22467 +               usbcfg.b.hnpcap = 0;
22468 +               usbcfg.b.srpcap = 0;
22469 +               break;
22470 +
22471 +       case DWC_MODE_SRP_CAPABLE_DEVICE:
22472 +               usbcfg.b.hnpcap = 0;
22473 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22474 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22475 +               break;
22476 +
22477 +       case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
22478 +               usbcfg.b.hnpcap = 0;
22479 +               usbcfg.b.srpcap = 0;
22480 +               break;
22481 +
22482 +       case DWC_MODE_SRP_CAPABLE_HOST:
22483 +               usbcfg.b.hnpcap = 0;
22484 +               usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
22485 +                                  DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
22486 +               break;
22487 +
22488 +       case DWC_MODE_NO_SRP_CAPABLE_HOST:
22489 +               usbcfg.b.hnpcap = 0;
22490 +               usbcfg.b.srpcap = 0;
22491 +               break;
22492 +       }
22493 +
22494 +       DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
22495 +
22496 +#ifdef CONFIG_USB_DWC_OTG_LPM
22497 +       if (core_if->core_params->lpm_enable) {
22498 +               glpmcfg_data_t lpmcfg = {.d32 = 0 };
22499 +
22500 +               /* To enable LPM support set lpm_cap_en bit */
22501 +               lpmcfg.b.lpm_cap_en = 1;
22502 +
22503 +               /* Make AppL1Res ACK */
22504 +               lpmcfg.b.appl_resp = 1;
22505 +
22506 +               /* Retry 3 times */
22507 +               lpmcfg.b.retry_count = 3;
22508 +
22509 +               DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,
22510 +                                0, lpmcfg.d32);
22511 +
22512 +       }
22513 +#endif
22514 +       if (core_if->core_params->ic_usb_cap) {
22515 +               gusbcfg_data_t gusbcfg = {.d32 = 0 };
22516 +               gusbcfg.b.ic_usb_cap = 1;
22517 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,
22518 +                                0, gusbcfg.d32);
22519 +       }
22520 +       {
22521 +               gotgctl_data_t gotgctl = {.d32 = 0 };
22522 +               gotgctl.b.otgver = core_if->core_params->otg_ver;
22523 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,
22524 +                                gotgctl.d32);
22525 +               /* Set OTG version supported */
22526 +               core_if->otg_ver = core_if->core_params->otg_ver;
22527 +               DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
22528 +                          core_if->core_params->otg_ver, core_if->otg_ver);
22529 +       }
22530 +
22531 +
22532 +       /* Enable common interrupts */
22533 +       dwc_otg_enable_common_interrupts(core_if);
22534 +
22535 +       /* Do device or host intialization based on mode during PCD
22536 +        * and HCD initialization  */
22537 +       if (dwc_otg_is_host_mode(core_if)) {
22538 +               DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
22539 +               core_if->op_state = A_HOST;
22540 +       } else {
22541 +               DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
22542 +               core_if->op_state = B_PERIPHERAL;
22543 +#ifdef DWC_DEVICE_ONLY
22544 +               dwc_otg_core_dev_init(core_if);
22545 +#endif
22546 +       }
22547 +}
22548 +
22549 +/**
22550 + * This function enables the Device mode interrupts.
22551 + *
22552 + * @param core_if Programming view of DWC_otg controller
22553 + */
22554 +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
22555 +{
22556 +       gintmsk_data_t intr_mask = {.d32 = 0 };
22557 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22558 +
22559 +       DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
22560 +
22561 +       /* Disable all interrupts. */
22562 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
22563 +
22564 +       /* Clear any pending interrupts */
22565 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
22566 +
22567 +       /* Enable the common interrupts */
22568 +       dwc_otg_enable_common_interrupts(core_if);
22569 +
22570 +       /* Enable interrupts */
22571 +       intr_mask.b.usbreset = 1;
22572 +       intr_mask.b.enumdone = 1;
22573 +       /* Disable Disconnect interrupt in Device mode */
22574 +       intr_mask.b.disconnect = 0;
22575 +
22576 +       if (!core_if->multiproc_int_enable) {
22577 +               intr_mask.b.inepintr = 1;
22578 +               intr_mask.b.outepintr = 1;
22579 +       }
22580 +
22581 +       intr_mask.b.erlysuspend = 1;
22582 +
22583 +       if (core_if->en_multiple_tx_fifo == 0) {
22584 +               intr_mask.b.epmismatch = 1;
22585 +       }
22586 +
22587 +       //intr_mask.b.incomplisoout = 1;
22588 +       intr_mask.b.incomplisoin = 1;
22589 +
22590 +/* Enable the ignore frame number for ISOC xfers - MAS */
22591 +/* Disable to support high bandwith ISOC transfers - manukz */
22592 +#if 0
22593 +#ifdef DWC_UTE_PER_IO
22594 +       if (core_if->dma_enable) {
22595 +               if (core_if->dma_desc_enable) {
22596 +                       dctl_data_t dctl1 = {.d32 = 0 };
22597 +                       dctl1.b.ifrmnum = 1;
22598 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
22599 +                                        dctl, 0, dctl1.d32);
22600 +                       DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",
22601 +                                 DWC_READ_REG32(&core_if->dev_if->
22602 +                                                dev_global_regs->dctl));
22603 +               }
22604 +       }
22605 +#endif
22606 +#endif
22607 +#ifdef DWC_EN_ISOC
22608 +       if (core_if->dma_enable) {
22609 +               if (core_if->dma_desc_enable == 0) {
22610 +                       if (core_if->pti_enh_enable) {
22611 +                               dctl_data_t dctl = {.d32 = 0 };
22612 +                               dctl.b.ifrmnum = 1;
22613 +                               DWC_MODIFY_REG32(&core_if->
22614 +                                                dev_if->dev_global_regs->dctl,
22615 +                                                0, dctl.d32);
22616 +                       } else {
22617 +                               intr_mask.b.incomplisoin = 1;
22618 +                               intr_mask.b.incomplisoout = 1;
22619 +                       }
22620 +               }
22621 +       } else {
22622 +               intr_mask.b.incomplisoin = 1;
22623 +               intr_mask.b.incomplisoout = 1;
22624 +       }
22625 +#endif /* DWC_EN_ISOC */
22626 +
22627 +       /** @todo NGS: Should this be a module parameter? */
22628 +#ifdef USE_PERIODIC_EP
22629 +       intr_mask.b.isooutdrop = 1;
22630 +       intr_mask.b.eopframe = 1;
22631 +       intr_mask.b.incomplisoin = 1;
22632 +       intr_mask.b.incomplisoout = 1;
22633 +#endif
22634 +
22635 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
22636 +
22637 +       DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
22638 +                   DWC_READ_REG32(&global_regs->gintmsk));
22639 +}
22640 +
22641 +/**
22642 + * This function initializes the DWC_otg controller registers for
22643 + * device mode.
22644 + *
22645 + * @param core_if Programming view of DWC_otg controller
22646 + *
22647 + */
22648 +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
22649 +{
22650 +       int i;
22651 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
22652 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
22653 +       dwc_otg_core_params_t *params = core_if->core_params;
22654 +       dcfg_data_t dcfg = {.d32 = 0 };
22655 +       depctl_data_t diepctl = {.d32 = 0 };
22656 +       grstctl_t resetctl = {.d32 = 0 };
22657 +       uint32_t rx_fifo_size;
22658 +       fifosize_data_t nptxfifosize;
22659 +       fifosize_data_t txfifosize;
22660 +       dthrctl_data_t dthrctl;
22661 +       fifosize_data_t ptxfifosize;
22662 +       uint16_t rxfsiz, nptxfsiz;
22663 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
22664 +       hwcfg3_data_t hwcfg3 = {.d32 = 0 };
22665 +
22666 +       /* Restart the Phy Clock */
22667 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
22668 +
22669 +       /* Device configuration register */
22670 +       init_devspd(core_if);
22671 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22672 +       dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
22673 +       dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
22674 +       /* Enable Device OUT NAK in case of DDMA mode*/
22675 +       if (core_if->core_params->dev_out_nak) {
22676 +               dcfg.b.endevoutnak = 1;
22677 +       }
22678 +
22679 +       if (core_if->core_params->cont_on_bna) {
22680 +               dctl_data_t dctl = {.d32 = 0 };
22681 +               dctl.b.encontonbna = 1;
22682 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22683 +       }
22684 +
22685 +
22686 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22687 +
22688 +       /* Configure data FIFO sizes */
22689 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
22690 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
22691 +                           core_if->total_fifo_size);
22692 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
22693 +                           params->dev_rx_fifo_size);
22694 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
22695 +                           params->dev_nperio_tx_fifo_size);
22696 +
22697 +               /* Rx FIFO */
22698 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
22699 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22700 +
22701 +#ifdef DWC_UTE_CFI
22702 +               core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);
22703 +               core_if->init_rxfsiz = params->dev_rx_fifo_size;
22704 +#endif
22705 +               rx_fifo_size = params->dev_rx_fifo_size;
22706 +               DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
22707 +
22708 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
22709 +                           DWC_READ_REG32(&global_regs->grxfsiz));
22710 +
22711 +               /** Set Periodic Tx FIFO Mask all bits 0 */
22712 +               core_if->p_tx_msk = 0;
22713 +
22714 +               /** Set Tx FIFO Mask all bits 0 */
22715 +               core_if->tx_msk = 0;
22716 +
22717 +               if (core_if->en_multiple_tx_fifo == 0) {
22718 +                       /* Non-periodic Tx FIFO */
22719 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22720 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22721 +
22722 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22723 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22724 +
22725 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22726 +                                       nptxfifosize.d32);
22727 +
22728 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22729 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22730 +
22731 +                       /**@todo NGS: Fix Periodic FIFO Sizing! */
22732 +                       /*
22733 +                        * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
22734 +                        * Indexes of the FIFO size module parameters in the
22735 +                        * dev_perio_tx_fifo_size array and the FIFO size registers in
22736 +                        * the dptxfsiz array run from 0 to 14.
22737 +                        */
22738 +                       /** @todo Finish debug of this */
22739 +                       ptxfifosize.b.startaddr =
22740 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22741 +                       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
22742 +                               ptxfifosize.b.depth =
22743 +                                   params->dev_perio_tx_fifo_size[i];
22744 +                               DWC_DEBUGPL(DBG_CIL,
22745 +                                           "initial dtxfsiz[%d]=%08x\n", i,
22746 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22747 +                                                          [i]));
22748 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22749 +                                               ptxfifosize.d32);
22750 +                               DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",
22751 +                                           i,
22752 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22753 +                                                          [i]));
22754 +                               ptxfifosize.b.startaddr += ptxfifosize.b.depth;
22755 +                       }
22756 +               } else {
22757 +                       /*
22758 +                        * Tx FIFOs These FIFOs are numbered from 1 to 15.
22759 +                        * Indexes of the FIFO size module parameters in the
22760 +                        * dev_tx_fifo_size array and the FIFO size registers in
22761 +                        * the dtxfsiz array run from 0 to 14.
22762 +                        */
22763 +
22764 +                       /* Non-periodic Tx FIFO */
22765 +                       DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
22766 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22767 +
22768 +#ifdef DWC_UTE_CFI
22769 +                       core_if->pwron_gnptxfsiz =
22770 +                           (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22771 +                       core_if->init_gnptxfsiz =
22772 +                           params->dev_nperio_tx_fifo_size;
22773 +#endif
22774 +                       nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
22775 +                       nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
22776 +
22777 +                       DWC_WRITE_REG32(&global_regs->gnptxfsiz,
22778 +                                       nptxfifosize.d32);
22779 +
22780 +                       DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
22781 +                                   DWC_READ_REG32(&global_regs->gnptxfsiz));
22782 +
22783 +                       txfifosize.b.startaddr =
22784 +                           nptxfifosize.b.startaddr + nptxfifosize.b.depth;
22785 +
22786 +                       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
22787 +
22788 +                               txfifosize.b.depth =
22789 +                                   params->dev_tx_fifo_size[i];
22790 +
22791 +                               DWC_DEBUGPL(DBG_CIL,
22792 +                                           "initial dtxfsiz[%d]=%08x\n",
22793 +                                           i,
22794 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22795 +                                                          [i]));
22796 +
22797 +#ifdef DWC_UTE_CFI
22798 +                               core_if->pwron_txfsiz[i] =
22799 +                                   (DWC_READ_REG32
22800 +                                    (&global_regs->dtxfsiz[i]) >> 16);
22801 +                               core_if->init_txfsiz[i] =
22802 +                                   params->dev_tx_fifo_size[i];
22803 +#endif
22804 +                               DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
22805 +                                               txfifosize.d32);
22806 +
22807 +                               DWC_DEBUGPL(DBG_CIL,
22808 +                                           "new dtxfsiz[%d]=%08x\n",
22809 +                                           i,
22810 +                                           DWC_READ_REG32(&global_regs->dtxfsiz
22811 +                                                          [i]));
22812 +
22813 +                               txfifosize.b.startaddr += txfifosize.b.depth;
22814 +                       }
22815 +                       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
22816 +                               /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */
22817 +                               gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
22818 +                               hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);
22819 +                               gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);
22820 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22821 +                               rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
22822 +                               nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
22823 +                               gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;
22824 +                               DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
22825 +                       }
22826 +               }
22827 +
22828 +               /* Flush the FIFOs */
22829 +               dwc_otg_flush_tx_fifo(core_if, 0x10);   /* all Tx FIFOs */
22830 +               dwc_otg_flush_rx_fifo(core_if);
22831 +
22832 +               /* Flush the Learning Queue. */
22833 +               resetctl.b.intknqflsh = 1;
22834 +               DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
22835 +
22836 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
22837 +                       core_if->start_predict = 0;
22838 +                       for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
22839 +                               core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
22840 +                       }
22841 +                       core_if->nextep_seq[0] = 0;
22842 +                       core_if->first_in_nextep_seq = 0;
22843 +                       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
22844 +                       diepctl.b.nextep = 0;
22845 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
22846 +
22847 +                       /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
22848 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
22849 +                       dcfg.b.epmscnt = 2;
22850 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
22851 +
22852 +                       DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
22853 +                               __func__, core_if->first_in_nextep_seq);
22854 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
22855 +                               DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
22856 +                       }
22857 +                       DWC_DEBUGPL(DBG_CILV,"\n");
22858 +               }
22859 +
22860 +               /* Clear all pending Device Interrupts */
22861 +               /** @todo - if the condition needed to be checked
22862 +                *  or in any case all pending interrutps should be cleared?
22863 +            */
22864 +               if (core_if->multiproc_int_enable) {
22865 +                       for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
22866 +                               DWC_WRITE_REG32(&dev_if->
22867 +                                               dev_global_regs->diepeachintmsk[i], 0);
22868 +                       }
22869 +               }
22870 +
22871 +               for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
22872 +                       DWC_WRITE_REG32(&dev_if->
22873 +                                       dev_global_regs->doepeachintmsk[i], 0);
22874 +               }
22875 +
22876 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
22877 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);
22878 +       } else {
22879 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
22880 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
22881 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
22882 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
22883 +       }
22884 +
22885 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
22886 +               depctl_data_t depctl;
22887 +               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
22888 +               if (depctl.b.epena) {
22889 +                       depctl.d32 = 0;
22890 +                       depctl.b.epdis = 1;
22891 +                       depctl.b.snak = 1;
22892 +               } else {
22893 +                       depctl.d32 = 0;
22894 +               }
22895 +
22896 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
22897 +
22898 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
22899 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
22900 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
22901 +       }
22902 +
22903 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
22904 +               depctl_data_t depctl;
22905 +               depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
22906 +               if (depctl.b.epena) {
22907 +                       dctl_data_t dctl = {.d32 = 0 };
22908 +                       gintmsk_data_t gintsts = {.d32 = 0 };
22909 +                       doepint_data_t doepint = {.d32 = 0 };
22910 +                       dctl.b.sgoutnak = 1;
22911 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22912 +                       do {
22913 +                               dwc_udelay(10);
22914 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
22915 +                       } while (!gintsts.b.goutnakeff);
22916 +                       gintsts.d32 = 0;
22917 +                       gintsts.b.goutnakeff = 1;
22918 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
22919 +
22920 +                       depctl.d32 = 0;
22921 +                       depctl.b.epdis = 1;
22922 +                       depctl.b.snak = 1;
22923 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);
22924 +                       do {
22925 +                               dwc_udelay(10);
22926 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
22927 +                                       out_ep_regs[i]->doepint);
22928 +                       } while (!doepint.b.epdisabled);
22929 +
22930 +                       doepint.b.epdisabled = 1;
22931 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);
22932 +
22933 +                       dctl.d32 = 0;
22934 +                       dctl.b.cgoutnak = 1;
22935 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
22936 +               } else {
22937 +                       depctl.d32 = 0;
22938 +               }
22939 +
22940 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
22941 +
22942 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
22943 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
22944 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
22945 +       }
22946 +
22947 +       if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
22948 +               dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
22949 +               dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
22950 +               dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
22951 +
22952 +               dev_if->rx_thr_length = params->rx_thr_length;
22953 +               dev_if->tx_thr_length = params->tx_thr_length;
22954 +
22955 +               dev_if->setup_desc_index = 0;
22956 +
22957 +               dthrctl.d32 = 0;
22958 +               dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
22959 +               dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
22960 +               dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
22961 +               dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
22962 +               dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
22963 +               dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
22964 +
22965 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
22966 +                               dthrctl.d32);
22967 +
22968 +               DWC_DEBUGPL(DBG_CIL,
22969 +                           "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
22970 +                           dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
22971 +                           dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
22972 +                           dthrctl.b.rx_thr_len);
22973 +
22974 +       }
22975 +
22976 +       dwc_otg_enable_device_interrupts(core_if);
22977 +
22978 +       {
22979 +               diepmsk_data_t msk = {.d32 = 0 };
22980 +               msk.b.txfifoundrn = 1;
22981 +               if (core_if->multiproc_int_enable) {
22982 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->
22983 +                                        diepeachintmsk[0], msk.d32, msk.d32);
22984 +               } else {
22985 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,
22986 +                                        msk.d32, msk.d32);
22987 +               }
22988 +       }
22989 +
22990 +       if (core_if->multiproc_int_enable) {
22991 +               /* Set NAK on Babble */
22992 +               dctl_data_t dctl = {.d32 = 0 };
22993 +               dctl.b.nakonbble = 1;
22994 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
22995 +       }
22996 +
22997 +       if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
22998 +               dctl_data_t dctl = {.d32 = 0 };
22999 +               dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
23000 +               dctl.b.sftdiscon = 0;
23001 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
23002 +       }
23003 +}
23004 +
23005 +/**
23006 + * This function enables the Host mode interrupts.
23007 + *
23008 + * @param core_if Programming view of DWC_otg controller
23009 + */
23010 +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
23011 +{
23012 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23013 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23014 +
23015 +       DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
23016 +
23017 +       /* Disable all interrupts. */
23018 +       DWC_WRITE_REG32(&global_regs->gintmsk, 0);
23019 +
23020 +       /* Clear any pending interrupts. */
23021 +       DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
23022 +
23023 +       /* Enable the common interrupts */
23024 +       dwc_otg_enable_common_interrupts(core_if);
23025 +
23026 +       /*
23027 +        * Enable host mode interrupts without disturbing common
23028 +        * interrupts.
23029 +        */
23030 +
23031 +       intr_mask.b.disconnect = 1;
23032 +       intr_mask.b.portintr = 1;
23033 +       intr_mask.b.hcintr = 1;
23034 +
23035 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
23036 +}
23037 +
23038 +/**
23039 + * This function disables the Host Mode interrupts.
23040 + *
23041 + * @param core_if Programming view of DWC_otg controller
23042 + */
23043 +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
23044 +{
23045 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23046 +       gintmsk_data_t intr_mask = {.d32 = 0 };
23047 +
23048 +       DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
23049 +
23050 +       /*
23051 +        * Disable host mode interrupts without disturbing common
23052 +        * interrupts.
23053 +        */
23054 +       intr_mask.b.sofintr = 1;
23055 +       intr_mask.b.portintr = 1;
23056 +       intr_mask.b.hcintr = 1;
23057 +       intr_mask.b.ptxfempty = 1;
23058 +       intr_mask.b.nptxfempty = 1;
23059 +
23060 +       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);
23061 +}
23062 +
23063 +/**
23064 + * This function initializes the DWC_otg controller registers for
23065 + * host mode.
23066 + *
23067 + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
23068 + * request queues. Host channels are reset to ensure that they are ready for
23069 + * performing transfers.
23070 + *
23071 + * @param core_if Programming view of DWC_otg controller
23072 + *
23073 + */
23074 +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
23075 +{
23076 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
23077 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23078 +       dwc_otg_core_params_t *params = core_if->core_params;
23079 +       hprt0_data_t hprt0 = {.d32 = 0 };
23080 +       fifosize_data_t nptxfifosize;
23081 +       fifosize_data_t ptxfifosize;
23082 +       uint16_t rxfsiz, nptxfsiz, hptxfsiz;
23083 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
23084 +       int i;
23085 +       hcchar_data_t hcchar;
23086 +       hcfg_data_t hcfg;
23087 +       hfir_data_t hfir;
23088 +       dwc_otg_hc_regs_t *hc_regs;
23089 +       int num_channels;
23090 +       gotgctl_data_t gotgctl = {.d32 = 0 };
23091 +
23092 +       DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
23093 +
23094 +       /* Restart the Phy Clock */
23095 +       DWC_WRITE_REG32(core_if->pcgcctl, 0);
23096 +
23097 +       /* Initialize Host Configuration Register */
23098 +       init_fslspclksel(core_if);
23099 +       if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
23100 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23101 +               hcfg.b.fslssupp = 1;
23102 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23103 +
23104 +       }
23105 +
23106 +       /* This bit allows dynamic reloading of the HFIR register
23107 +        * during runtime. This bit needs to be programmed during
23108 +        * initial configuration and its value must not be changed
23109 +        * during runtime.*/
23110 +       if (core_if->core_params->reload_ctl == 1) {
23111 +               hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
23112 +               hfir.b.hfirrldctrl = 1;
23113 +               DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
23114 +       }
23115 +
23116 +       if (core_if->core_params->dma_desc_enable) {
23117 +               uint8_t op_mode = core_if->hwcfg2.b.op_mode;
23118 +               if (!
23119 +                   (core_if->hwcfg4.b.desc_dma
23120 +                    && (core_if->snpsid >= OTG_CORE_REV_2_90a)
23121 +                    && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
23122 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
23123 +                        || (op_mode ==
23124 +                            DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)
23125 +                        || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
23126 +                        || (op_mode ==
23127 +                            DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
23128 +
23129 +                       DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
23130 +                                 "Either core version is below 2.90a or "
23131 +                                 "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
23132 +                                 "To run the driver in Buffer DMA host mode set dma_desc_enable "
23133 +                                 "module parameter to 0.\n");
23134 +                       return;
23135 +               }
23136 +               hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
23137 +               hcfg.b.descdma = 1;
23138 +               DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
23139 +       }
23140 +
23141 +       /* Configure data FIFO sizes */
23142 +       if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
23143 +               DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
23144 +                           core_if->total_fifo_size);
23145 +               DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
23146 +                           params->host_rx_fifo_size);
23147 +               DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
23148 +                           params->host_nperio_tx_fifo_size);
23149 +               DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
23150 +                           params->host_perio_tx_fifo_size);
23151 +
23152 +               /* Rx FIFO */
23153 +               DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
23154 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23155 +               DWC_WRITE_REG32(&global_regs->grxfsiz,
23156 +                               params->host_rx_fifo_size);
23157 +               DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
23158 +                           DWC_READ_REG32(&global_regs->grxfsiz));
23159 +
23160 +               /* Non-periodic Tx FIFO */
23161 +               DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
23162 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23163 +               nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
23164 +               nptxfifosize.b.startaddr = params->host_rx_fifo_size;
23165 +               DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
23166 +               DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
23167 +                           DWC_READ_REG32(&global_regs->gnptxfsiz));
23168 +
23169 +               /* Periodic Tx FIFO */
23170 +               DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
23171 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23172 +               ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
23173 +               ptxfifosize.b.startaddr =
23174 +                   nptxfifosize.b.startaddr + nptxfifosize.b.depth;
23175 +               DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
23176 +               DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
23177 +                           DWC_READ_REG32(&global_regs->hptxfsiz));
23178 +
23179 +               if (core_if->en_multiple_tx_fifo
23180 +                   && core_if->snpsid <= OTG_CORE_REV_2_94a) {
23181 +                       /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
23182 +                       gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
23183 +                       rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
23184 +                       nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
23185 +                       hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);
23186 +                       gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;
23187 +                       DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
23188 +               }
23189 +       }
23190 +
23191 +       /* TODO - check this */
23192 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23193 +       gotgctl.b.hstsethnpen = 1;
23194 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23195 +       /* Make sure the FIFOs are flushed. */
23196 +       dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );
23197 +       dwc_otg_flush_rx_fifo(core_if);
23198 +
23199 +       /* Clear Host Set HNP Enable in the OTG Control Register */
23200 +       gotgctl.b.hstsethnpen = 1;
23201 +       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
23202 +
23203 +       if (!core_if->core_params->dma_desc_enable) {
23204 +               /* Flush out any leftover queued requests. */
23205 +               num_channels = core_if->core_params->host_channels;
23206 +
23207 +               for (i = 0; i < num_channels; i++) {
23208 +                       hc_regs = core_if->host_if->hc_regs[i];
23209 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23210 +                       hcchar.b.chen = 0;
23211 +                       hcchar.b.chdis = 1;
23212 +                       hcchar.b.epdir = 0;
23213 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23214 +               }
23215 +
23216 +               /* Halt all channels to put them into a known state. */
23217 +               for (i = 0; i < num_channels; i++) {
23218 +                       int count = 0;
23219 +                       hc_regs = core_if->host_if->hc_regs[i];
23220 +                       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23221 +                       hcchar.b.chen = 1;
23222 +                       hcchar.b.chdis = 1;
23223 +                       hcchar.b.epdir = 0;
23224 +                       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23225 +                       DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
23226 +                       do {
23227 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23228 +                               if (++count > 1000) {
23229 +                                       DWC_ERROR
23230 +                                           ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
23231 +                                            __func__, i, hcchar.d32, &hc_regs->hcchar);
23232 +                                       break;
23233 +                               }
23234 +                               dwc_udelay(1);
23235 +                       } while (hcchar.b.chen);
23236 +               }
23237 +       }
23238 +
23239 +       /* Turn on the vbus power. */
23240 +       DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
23241 +       if (core_if->op_state == A_HOST) {
23242 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
23243 +               DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
23244 +               if (hprt0.b.prtpwr == 0) {
23245 +                       hprt0.b.prtpwr = 1;
23246 +                       DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);
23247 +               }
23248 +       }
23249 +
23250 +       dwc_otg_enable_host_interrupts(core_if);
23251 +}
23252 +
23253 +/**
23254 + * Prepares a host channel for transferring packets to/from a specific
23255 + * endpoint. The HCCHARn register is set up with the characteristics specified
23256 + * in _hc. Host channel interrupts that may need to be serviced while this
23257 + * transfer is in progress are enabled.
23258 + *
23259 + * @param core_if Programming view of DWC_otg controller
23260 + * @param hc Information needed to initialize the host channel
23261 + */
23262 +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23263 +{
23264 +       uint32_t intr_enable;
23265 +       hcintmsk_data_t hc_intr_mask;
23266 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23267 +       hcchar_data_t hcchar;
23268 +       hcsplt_data_t hcsplt;
23269 +
23270 +       uint8_t hc_num = hc->hc_num;
23271 +       dwc_otg_host_if_t *host_if = core_if->host_if;
23272 +       dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
23273 +
23274 +       /* Clear old interrupt conditions for this host channel. */
23275 +       hc_intr_mask.d32 = 0xFFFFFFFF;
23276 +       hc_intr_mask.b.reserved14_31 = 0;
23277 +       DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);
23278 +
23279 +       /* Enable channel interrupts required for this transfer. */
23280 +       hc_intr_mask.d32 = 0;
23281 +       hc_intr_mask.b.chhltd = 1;
23282 +       if (core_if->dma_enable) {
23283 +               /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
23284 +               if (!core_if->dma_desc_enable)
23285 +                       hc_intr_mask.b.ahberr = 1;
23286 +               else {
23287 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23288 +                               hc_intr_mask.b.xfercompl = 1;
23289 +               }
23290 +
23291 +               if (hc->error_state && !hc->do_split &&
23292 +                   hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
23293 +                       hc_intr_mask.b.ack = 1;
23294 +                       if (hc->ep_is_in) {
23295 +                               hc_intr_mask.b.datatglerr = 1;
23296 +                               if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23297 +                                       hc_intr_mask.b.nak = 1;
23298 +                               }
23299 +                       }
23300 +               }
23301 +       } else {
23302 +               switch (hc->ep_type) {
23303 +               case DWC_OTG_EP_TYPE_CONTROL:
23304 +               case DWC_OTG_EP_TYPE_BULK:
23305 +                       hc_intr_mask.b.xfercompl = 1;
23306 +                       hc_intr_mask.b.stall = 1;
23307 +                       hc_intr_mask.b.xacterr = 1;
23308 +                       hc_intr_mask.b.datatglerr = 1;
23309 +                       if (hc->ep_is_in) {
23310 +                               hc_intr_mask.b.bblerr = 1;
23311 +                       } else {
23312 +                               hc_intr_mask.b.nak = 1;
23313 +                               hc_intr_mask.b.nyet = 1;
23314 +                               if (hc->do_ping) {
23315 +                                       hc_intr_mask.b.ack = 1;
23316 +                               }
23317 +                       }
23318 +
23319 +                       if (hc->do_split) {
23320 +                               hc_intr_mask.b.nak = 1;
23321 +                               if (hc->complete_split) {
23322 +                                       hc_intr_mask.b.nyet = 1;
23323 +                               } else {
23324 +                                       hc_intr_mask.b.ack = 1;
23325 +                               }
23326 +                       }
23327 +
23328 +                       if (hc->error_state) {
23329 +                               hc_intr_mask.b.ack = 1;
23330 +                       }
23331 +                       break;
23332 +               case DWC_OTG_EP_TYPE_INTR:
23333 +                       hc_intr_mask.b.xfercompl = 1;
23334 +                       hc_intr_mask.b.nak = 1;
23335 +                       hc_intr_mask.b.stall = 1;
23336 +                       hc_intr_mask.b.xacterr = 1;
23337 +                       hc_intr_mask.b.datatglerr = 1;
23338 +                       hc_intr_mask.b.frmovrun = 1;
23339 +
23340 +                       if (hc->ep_is_in) {
23341 +                               hc_intr_mask.b.bblerr = 1;
23342 +                       }
23343 +                       if (hc->error_state) {
23344 +                               hc_intr_mask.b.ack = 1;
23345 +                       }
23346 +                       if (hc->do_split) {
23347 +                               if (hc->complete_split) {
23348 +                                       hc_intr_mask.b.nyet = 1;
23349 +                               } else {
23350 +                                       hc_intr_mask.b.ack = 1;
23351 +                               }
23352 +                       }
23353 +                       break;
23354 +               case DWC_OTG_EP_TYPE_ISOC:
23355 +                       hc_intr_mask.b.xfercompl = 1;
23356 +                       hc_intr_mask.b.frmovrun = 1;
23357 +                       hc_intr_mask.b.ack = 1;
23358 +
23359 +                       if (hc->ep_is_in) {
23360 +                               hc_intr_mask.b.xacterr = 1;
23361 +                               hc_intr_mask.b.bblerr = 1;
23362 +                       }
23363 +                       break;
23364 +               }
23365 +       }
23366 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
23367 +
23368 +       /* Enable the top level host channel interrupt. */
23369 +       intr_enable = (1 << hc_num);
23370 +       DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
23371 +
23372 +       /* Make sure host channel interrupts are enabled. */
23373 +       gintmsk.b.hcintr = 1;
23374 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
23375 +
23376 +       /*
23377 +        * Program the HCCHARn register with the endpoint characteristics for
23378 +        * the current transfer.
23379 +        */
23380 +       hcchar.d32 = 0;
23381 +       hcchar.b.devaddr = hc->dev_addr;
23382 +       hcchar.b.epnum = hc->ep_num;
23383 +       hcchar.b.epdir = hc->ep_is_in;
23384 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
23385 +       hcchar.b.eptype = hc->ep_type;
23386 +       hcchar.b.mps = hc->max_packet;
23387 +
23388 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
23389 +
23390 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",
23391 +                    __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);
23392 +       DWC_DEBUGPL(DBG_HCDV, "  Is In %d, Is Low Speed %d, EP Type %d, "
23393 +                                "Max Pkt %d, Multi Cnt %d\n",
23394 +                    hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,
23395 +                    hcchar.b.mps, hcchar.b.multicnt);
23396 +
23397 +       /*
23398 +        * Program the HCSPLIT register for SPLITs
23399 +        */
23400 +       hcsplt.d32 = 0;
23401 +       if (hc->do_split) {
23402 +               DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
23403 +                           hc->hc_num,
23404 +                           hc->complete_split ? "CSPLIT" : "SSPLIT");
23405 +               hcsplt.b.compsplt = hc->complete_split;
23406 +               hcsplt.b.xactpos = hc->xact_pos;
23407 +               hcsplt.b.hubaddr = hc->hub_addr;
23408 +               hcsplt.b.prtaddr = hc->port_addr;
23409 +               DWC_DEBUGPL(DBG_HCDV, "\t  comp split %d\n", hc->complete_split);
23410 +               DWC_DEBUGPL(DBG_HCDV, "\t  xact pos %d\n", hc->xact_pos);
23411 +               DWC_DEBUGPL(DBG_HCDV, "\t  hub addr %d\n", hc->hub_addr);
23412 +               DWC_DEBUGPL(DBG_HCDV, "\t  port addr %d\n", hc->port_addr);
23413 +               DWC_DEBUGPL(DBG_HCDV, "\t  is_in %d\n", hc->ep_is_in);
23414 +               DWC_DEBUGPL(DBG_HCDV, "\t  Max Pkt: %d\n", hcchar.b.mps);
23415 +               DWC_DEBUGPL(DBG_HCDV, "\t  xferlen: %d\n", hc->xfer_len);
23416 +       }
23417 +       DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
23418 +
23419 +}
23420 +
23421 +/**
23422 + * Attempts to halt a host channel. This function should only be called in
23423 + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
23424 + * normal circumstances in DMA mode, the controller halts the channel when the
23425 + * transfer is complete or a condition occurs that requires application
23426 + * intervention.
23427 + *
23428 + * In slave mode, checks for a free request queue entry, then sets the Channel
23429 + * Enable and Channel Disable bits of the Host Channel Characteristics
23430 + * register of the specified channel to intiate the halt. If there is no free
23431 + * request queue entry, sets only the Channel Disable bit of the HCCHARn
23432 + * register to flush requests for this channel. In the latter case, sets a
23433 + * flag to indicate that the host channel needs to be halted when a request
23434 + * queue slot is open.
23435 + *
23436 + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
23437 + * HCCHARn register. The controller ensures there is space in the request
23438 + * queue before submitting the halt request.
23439 + *
23440 + * Some time may elapse before the core flushes any posted requests for this
23441 + * host channel and halts. The Channel Halted interrupt handler completes the
23442 + * deactivation of the host channel.
23443 + *
23444 + * @param core_if Controller register interface.
23445 + * @param hc Host channel to halt.
23446 + * @param halt_status Reason for halting the channel.
23447 + */
23448 +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
23449 +                    dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
23450 +{
23451 +       gnptxsts_data_t nptxsts;
23452 +       hptxsts_data_t hptxsts;
23453 +       hcchar_data_t hcchar;
23454 +       dwc_otg_hc_regs_t *hc_regs;
23455 +       dwc_otg_core_global_regs_t *global_regs;
23456 +       dwc_otg_host_global_regs_t *host_global_regs;
23457 +
23458 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23459 +       global_regs = core_if->core_global_regs;
23460 +       host_global_regs = core_if->host_if->host_global_regs;
23461 +
23462 +       DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
23463 +                  "halt_status = %d\n", halt_status);
23464 +
23465 +       if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
23466 +           halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
23467 +               /*
23468 +                * Disable all channel interrupts except Ch Halted. The QTD
23469 +                * and QH state associated with this transfer has been cleared
23470 +                * (in the case of URB_DEQUEUE), so the channel needs to be
23471 +                * shut down carefully to prevent crashes.
23472 +                */
23473 +               hcintmsk_data_t hcintmsk;
23474 +               hcintmsk.d32 = 0;
23475 +               hcintmsk.b.chhltd = 1;
23476 +               DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);
23477 +
23478 +               /*
23479 +                * Make sure no other interrupts besides halt are currently
23480 +                * pending. Handling another interrupt could cause a crash due
23481 +                * to the QTD and QH state.
23482 +                */
23483 +               DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);
23484 +
23485 +               /*
23486 +                * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
23487 +                * even if the channel was already halted for some other
23488 +                * reason.
23489 +                */
23490 +               hc->halt_status = halt_status;
23491 +
23492 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23493 +               if (hcchar.b.chen == 0) {
23494 +                       /*
23495 +                        * The channel is either already halted or it hasn't
23496 +                        * started yet. In DMA mode, the transfer may halt if
23497 +                        * it finishes normally or a condition occurs that
23498 +                        * requires driver intervention. Don't want to halt
23499 +                        * the channel again. In either Slave or DMA mode,
23500 +                        * it's possible that the transfer has been assigned
23501 +                        * to a channel, but not started yet when an URB is
23502 +                        * dequeued. Don't want to halt a channel that hasn't
23503 +                        * started yet.
23504 +                        */
23505 +                       return;
23506 +               }
23507 +       }
23508 +       if (hc->halt_pending) {
23509 +               /*
23510 +                * A halt has already been issued for this channel. This might
23511 +                * happen when a transfer is aborted by a higher level in
23512 +                * the stack.
23513 +                */
23514 +#ifdef DEBUG
23515 +               DWC_PRINTF
23516 +                   ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
23517 +                    __func__, hc->hc_num);
23518 +
23519 +#endif
23520 +               return;
23521 +       }
23522 +
23523 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23524 +
23525 +       /* No need to set the bit in DDMA for disabling the channel */
23526 +       //TODO check it everywhere channel is disabled
23527 +       if (!core_if->core_params->dma_desc_enable)
23528 +               hcchar.b.chen = 1;
23529 +       hcchar.b.chdis = 1;
23530 +
23531 +       if (!core_if->dma_enable) {
23532 +               /* Check for space in the request queue to issue the halt. */
23533 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
23534 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
23535 +                       nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
23536 +                       if (nptxsts.b.nptxqspcavail == 0) {
23537 +                               hcchar.b.chen = 0;
23538 +                       }
23539 +               } else {
23540 +                       hptxsts.d32 =
23541 +                           DWC_READ_REG32(&host_global_regs->hptxsts);
23542 +                       if ((hptxsts.b.ptxqspcavail == 0)
23543 +                           || (core_if->queuing_high_bandwidth)) {
23544 +                               hcchar.b.chen = 0;
23545 +                       }
23546 +               }
23547 +       }
23548 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23549 +
23550 +       hc->halt_status = halt_status;
23551 +
23552 +       if (hcchar.b.chen) {
23553 +               hc->halt_pending = 1;
23554 +               hc->halt_on_queue = 0;
23555 +       } else {
23556 +               hc->halt_on_queue = 1;
23557 +       }
23558 +
23559 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23560 +       DWC_DEBUGPL(DBG_HCDV, "  hcchar: 0x%08x\n", hcchar.d32);
23561 +       DWC_DEBUGPL(DBG_HCDV, "  halt_pending: %d\n", hc->halt_pending);
23562 +       DWC_DEBUGPL(DBG_HCDV, "  halt_on_queue: %d\n", hc->halt_on_queue);
23563 +       DWC_DEBUGPL(DBG_HCDV, "  halt_status: %d\n", hc->halt_status);
23564 +
23565 +       return;
23566 +}
23567 +
23568 +/**
23569 + * Clears the transfer state for a host channel. This function is normally
23570 + * called after a transfer is done and the host channel is being released.
23571 + *
23572 + * @param core_if Programming view of DWC_otg controller.
23573 + * @param hc Identifies the host channel to clean up.
23574 + */
23575 +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23576 +{
23577 +       dwc_otg_hc_regs_t *hc_regs;
23578 +
23579 +       hc->xfer_started = 0;
23580 +
23581 +       /*
23582 +        * Clear channel interrupt enables and any unhandled channel interrupt
23583 +        * conditions.
23584 +        */
23585 +       hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23586 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);
23587 +       DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);
23588 +#ifdef DEBUG
23589 +       DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
23590 +#endif
23591 +}
23592 +
23593 +/**
23594 + * Sets the channel property that indicates in which frame a periodic transfer
23595 + * should occur. This is always set to the _next_ frame. This function has no
23596 + * effect on non-periodic transfers.
23597 + *
23598 + * @param core_if Programming view of DWC_otg controller.
23599 + * @param hc Identifies the host channel to set up and its properties.
23600 + * @param hcchar Current value of the HCCHAR register for the specified host
23601 + * channel.
23602 + */
23603 +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
23604 +                                        dwc_hc_t * hc, hcchar_data_t * hcchar)
23605 +{
23606 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23607 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23608 +               hfnum_data_t hfnum;
23609 +               hfnum.d32 =
23610 +                   DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);
23611 +
23612 +               /* 1 if _next_ frame is odd, 0 if it's even */
23613 +               hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
23614 +#ifdef DEBUG
23615 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
23616 +                   && !hc->complete_split) {
23617 +                       switch (hfnum.b.frnum & 0x7) {
23618 +                       case 7:
23619 +                               core_if->hfnum_7_samples++;
23620 +                               core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
23621 +                               break;
23622 +                       case 0:
23623 +                               core_if->hfnum_0_samples++;
23624 +                               core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
23625 +                               break;
23626 +                       default:
23627 +                               core_if->hfnum_other_samples++;
23628 +                               core_if->hfnum_other_frrem_accum +=
23629 +                                   hfnum.b.frrem;
23630 +                               break;
23631 +                       }
23632 +               }
23633 +#endif
23634 +       }
23635 +}
23636 +
23637 +#ifdef DEBUG
23638 +void hc_xfer_timeout(void *ptr)
23639 +{
23640 +       hc_xfer_info_t *xfer_info = NULL;
23641 +       int hc_num = 0;
23642 +
23643 +       if (ptr)
23644 +               xfer_info = (hc_xfer_info_t *) ptr;
23645 +
23646 +       if (!xfer_info->hc) {
23647 +               DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);
23648 +               return;
23649 +       }
23650 +
23651 +       hc_num = xfer_info->hc->hc_num;
23652 +       DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
23653 +       DWC_WARN("      start_hcchar_val 0x%08x\n",
23654 +                xfer_info->core_if->start_hcchar_val[hc_num]);
23655 +}
23656 +#endif
23657 +
23658 +void ep_xfer_timeout(void *ptr)
23659 +{
23660 +       ep_xfer_info_t *xfer_info = NULL;
23661 +       int ep_num = 0;
23662 +       dctl_data_t dctl = {.d32 = 0 };
23663 +       gintsts_data_t gintsts = {.d32 = 0 };
23664 +       gintmsk_data_t gintmsk = {.d32 = 0 };
23665 +
23666 +       if (ptr)
23667 +               xfer_info = (ep_xfer_info_t *) ptr;
23668 +
23669 +       if (!xfer_info->ep) {
23670 +               DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);
23671 +               return;
23672 +       }
23673 +
23674 +       ep_num = xfer_info->ep->num;
23675 +       DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);
23676 +       /* Put the sate to 2 as it was time outed */
23677 +       xfer_info->state = 2;
23678 +
23679 +       dctl.d32 =
23680 +           DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);
23681 +       gintsts.d32 =
23682 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);
23683 +       gintmsk.d32 =
23684 +           DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);
23685 +
23686 +       if (!gintmsk.b.goutnakeff) {
23687 +               /* Unmask it */
23688 +               gintmsk.b.goutnakeff = 1;
23689 +               DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,
23690 +                               gintmsk.d32);
23691 +
23692 +       }
23693 +
23694 +       if (!gintsts.b.goutnakeff) {
23695 +               dctl.b.sgoutnak = 1;
23696 +       }
23697 +       DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,
23698 +                       dctl.d32);
23699 +
23700 +}
23701 +
23702 +void set_pid_isoc(dwc_hc_t * hc)
23703 +{
23704 +       /* Set up the initial PID for the transfer. */
23705 +       if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
23706 +               if (hc->ep_is_in) {
23707 +                       if (hc->multi_count == 1) {
23708 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23709 +                       } else if (hc->multi_count == 2) {
23710 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
23711 +                       } else {
23712 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
23713 +                       }
23714 +               } else {
23715 +                       if (hc->multi_count == 1) {
23716 +                               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23717 +                       } else {
23718 +                               hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
23719 +                       }
23720 +               }
23721 +       } else {
23722 +               hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
23723 +       }
23724 +}
23725 +
23726 +/**
23727 + * This function does the setup for a data transfer for a host channel and
23728 + * starts the transfer. May be called in either Slave mode or DMA mode. In
23729 + * Slave mode, the caller must ensure that there is sufficient space in the
23730 + * request queue and Tx Data FIFO.
23731 + *
23732 + * For an OUT transfer in Slave mode, it loads a data packet into the
23733 + * appropriate FIFO. If necessary, additional data packets will be loaded in
23734 + * the Host ISR.
23735 + *
23736 + * For an IN transfer in Slave mode, a data packet is requested. The data
23737 + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
23738 + * additional data packets are requested in the Host ISR.
23739 + *
23740 + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
23741 + * register along with a packet count of 1 and the channel is enabled. This
23742 + * causes a single PING transaction to occur. Other fields in HCTSIZ are
23743 + * simply set to 0 since no data transfer occurs in this case.
23744 + *
23745 + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
23746 + * all the information required to perform the subsequent data transfer. In
23747 + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
23748 + * controller performs the entire PING protocol, then starts the data
23749 + * transfer.
23750 + *
23751 + * @param core_if Programming view of DWC_otg controller.
23752 + * @param hc Information needed to initialize the host channel. The xfer_len
23753 + * value may be reduced to accommodate the max widths of the XferSize and
23754 + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
23755 + * to reflect the final xfer_len value.
23756 + */
23757 +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23758 +{
23759 +       hcchar_data_t hcchar;
23760 +       hctsiz_data_t hctsiz;
23761 +       uint16_t num_packets;
23762 +       uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
23763 +       uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
23764 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23765 +
23766 +       hctsiz.d32 = 0;
23767 +
23768 +       if (hc->do_ping) {
23769 +               if (!core_if->dma_enable) {
23770 +                       dwc_otg_hc_do_ping(core_if, hc);
23771 +                       hc->xfer_started = 1;
23772 +                       return;
23773 +               } else {
23774 +                       hctsiz.b.dopng = 1;
23775 +               }
23776 +       }
23777 +
23778 +       if (hc->do_split) {
23779 +               num_packets = 1;
23780 +
23781 +               if (hc->complete_split && !hc->ep_is_in) {
23782 +                       /* For CSPLIT OUT Transfer, set the size to 0 so the
23783 +                        * core doesn't expect any data written to the FIFO */
23784 +                       hc->xfer_len = 0;
23785 +               } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
23786 +                       hc->xfer_len = hc->max_packet;
23787 +               } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
23788 +                       hc->xfer_len = 188;
23789 +               }
23790 +
23791 +               hctsiz.b.xfersize = hc->xfer_len;
23792 +       } else {
23793 +               /*
23794 +                * Ensure that the transfer length and packet count will fit
23795 +                * in the widths allocated for them in the HCTSIZn register.
23796 +                */
23797 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23798 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23799 +                       /*
23800 +                        * Make sure the transfer size is no larger than one
23801 +                        * (micro)frame's worth of data. (A check was done
23802 +                        * when the periodic transfer was accepted to ensure
23803 +                        * that a (micro)frame's worth of data can be
23804 +                        * programmed into a channel.)
23805 +                        */
23806 +                       uint32_t max_periodic_len =
23807 +                           hc->multi_count * hc->max_packet;
23808 +                       if (hc->xfer_len > max_periodic_len) {
23809 +                               hc->xfer_len = max_periodic_len;
23810 +                       } else {
23811 +                       }
23812 +               } else if (hc->xfer_len > max_hc_xfer_size) {
23813 +                       /* Make sure that xfer_len is a multiple of max packet size. */
23814 +                       hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
23815 +               }
23816 +
23817 +               if (hc->xfer_len > 0) {
23818 +                       num_packets =
23819 +                           (hc->xfer_len + hc->max_packet -
23820 +                            1) / hc->max_packet;
23821 +                       if (num_packets > max_hc_pkt_count) {
23822 +                               num_packets = max_hc_pkt_count;
23823 +                               hc->xfer_len = num_packets * hc->max_packet;
23824 +                       }
23825 +               } else {
23826 +                       /* Need 1 packet for transfer length of 0. */
23827 +                       num_packets = 1;
23828 +               }
23829 +
23830 +               if (hc->ep_is_in) {
23831 +                       /* Always program an integral # of max packets for IN transfers. */
23832 +                       hc->xfer_len = num_packets * hc->max_packet;
23833 +               }
23834 +
23835 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
23836 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
23837 +                       /*
23838 +                        * Make sure that the multi_count field matches the
23839 +                        * actual transfer length.
23840 +                        */
23841 +                       hc->multi_count = num_packets;
23842 +               }
23843 +
23844 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23845 +                       set_pid_isoc(hc);
23846 +
23847 +               hctsiz.b.xfersize = hc->xfer_len;
23848 +       }
23849 +
23850 +       hc->start_pkt_count = num_packets;
23851 +       hctsiz.b.pktcnt = num_packets;
23852 +       hctsiz.b.pid = hc->data_pid_start;
23853 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23854 +
23855 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23856 +       DWC_DEBUGPL(DBG_HCDV, "  Xfer Size: %d\n", hctsiz.b.xfersize);
23857 +       DWC_DEBUGPL(DBG_HCDV, "  Num Pkts: %d\n", hctsiz.b.pktcnt);
23858 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
23859 +
23860 +       if (core_if->dma_enable) {
23861 +               dwc_dma_t dma_addr;
23862 +               if (hc->align_buff) {
23863 +                       dma_addr = hc->align_buff;
23864 +               } else {
23865 +                       dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);
23866 +               }
23867 +               DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);
23868 +       }
23869 +
23870 +       /* Start the split */
23871 +       if (hc->do_split) {
23872 +               hcsplt_data_t hcsplt;
23873 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
23874 +               hcsplt.b.spltena = 1;
23875 +               DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);
23876 +       }
23877 +
23878 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23879 +       hcchar.b.multicnt = hc->multi_count;
23880 +       hc_set_even_odd_frame(core_if, hc, &hcchar);
23881 +#ifdef DEBUG
23882 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23883 +       if (hcchar.b.chdis) {
23884 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23885 +                        __func__, hc->hc_num, hcchar.d32);
23886 +       }
23887 +#endif
23888 +
23889 +       /* Set host channel enable after all other setup is complete. */
23890 +       hcchar.b.chen = 1;
23891 +       hcchar.b.chdis = 0;
23892 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23893 +
23894 +       hc->xfer_started = 1;
23895 +       hc->requests++;
23896 +
23897 +       if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
23898 +               /* Load OUT packet into the appropriate Tx FIFO. */
23899 +               dwc_otg_hc_write_packet(core_if, hc);
23900 +       }
23901 +#ifdef DEBUG
23902 +       if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
23903 +                DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
23904 +                            hc->hc_num, core_if);//GRAYG
23905 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23906 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
23907 +
23908 +               /* Start a timer for this transfer. */
23909 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23910 +       }
23911 +#endif
23912 +}
23913 +
23914 +/**
23915 + * This function does the setup for a data transfer for a host channel
23916 + * and starts the transfer in Descriptor DMA mode.
23917 + *
23918 + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
23919 + * Sets PID and NTD values. For periodic transfers
23920 + * initializes SCHED_INFO field with micro-frame bitmap.
23921 + *
23922 + * Initializes HCDMA register with descriptor list address and CTD value
23923 + * then starts the transfer via enabling the channel.
23924 + *
23925 + * @param core_if Programming view of DWC_otg controller.
23926 + * @param hc Information needed to initialize the host channel.
23927 + */
23928 +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
23929 +{
23930 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
23931 +       hcchar_data_t hcchar;
23932 +       hctsiz_data_t hctsiz;
23933 +       hcdma_data_t hcdma;
23934 +
23935 +       hctsiz.d32 = 0;
23936 +
23937 +       if (hc->do_ping)
23938 +               hctsiz.b_ddma.dopng = 1;
23939 +
23940 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
23941 +               set_pid_isoc(hc);
23942 +
23943 +       /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
23944 +       hctsiz.b_ddma.pid = hc->data_pid_start;
23945 +       hctsiz.b_ddma.ntd = hc->ntd - 1;        /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
23946 +       hctsiz.b_ddma.schinfo = hc->schinfo;    /* Non-zero only for high-speed interrupt endpoints */
23947 +
23948 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
23949 +       DWC_DEBUGPL(DBG_HCDV, "  Start PID: %d\n", hctsiz.b.pid);
23950 +       DWC_DEBUGPL(DBG_HCDV, "  NTD: %d\n", hctsiz.b_ddma.ntd);
23951 +
23952 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
23953 +
23954 +       hcdma.d32 = 0;
23955 +       hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;
23956 +
23957 +       /* Always start from first descriptor. */
23958 +       hcdma.b.ctd = 0;
23959 +       DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);
23960 +
23961 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
23962 +       hcchar.b.multicnt = hc->multi_count;
23963 +
23964 +#ifdef DEBUG
23965 +       core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
23966 +       if (hcchar.b.chdis) {
23967 +               DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
23968 +                        __func__, hc->hc_num, hcchar.d32);
23969 +       }
23970 +#endif
23971 +
23972 +       /* Set host channel enable after all other setup is complete. */
23973 +       hcchar.b.chen = 1;
23974 +       hcchar.b.chdis = 0;
23975 +
23976 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
23977 +
23978 +       hc->xfer_started = 1;
23979 +       hc->requests++;
23980 +
23981 +#ifdef DEBUG
23982 +       if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)
23983 +           && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
23984 +                DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
23985 +                            hc->hc_num, core_if);//GRAYG
23986 +               core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
23987 +               core_if->hc_xfer_info[hc->hc_num].hc = hc;
23988 +               /* Start a timer for this transfer. */
23989 +               DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
23990 +       }
23991 +#endif
23992 +
23993 +}
23994 +
23995 +/**
23996 + * This function continues a data transfer that was started by previous call
23997 + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
23998 + * sufficient space in the request queue and Tx Data FIFO. This function
23999 + * should only be called in Slave mode. In DMA mode, the controller acts
24000 + * autonomously to complete transfers programmed to a host channel.
24001 + *
24002 + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
24003 + * if there is any data remaining to be queued. For an IN transfer, another
24004 + * data packet is always requested. For the SETUP phase of a control transfer,
24005 + * this function does nothing.
24006 + *
24007 + * @return 1 if a new request is queued, 0 if no more requests are required
24008 + * for this transfer.
24009 + */
24010 +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24011 +{
24012 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24013 +
24014 +       if (hc->do_split) {
24015 +               /* SPLITs always queue just once per channel */
24016 +               return 0;
24017 +       } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
24018 +               /* SETUPs are queued only once since they can't be NAKed. */
24019 +               return 0;
24020 +       } else if (hc->ep_is_in) {
24021 +               /*
24022 +                * Always queue another request for other IN transfers. If
24023 +                * back-to-back INs are issued and NAKs are received for both,
24024 +                * the driver may still be processing the first NAK when the
24025 +                * second NAK is received. When the interrupt handler clears
24026 +                * the NAK interrupt for the first NAK, the second NAK will
24027 +                * not be seen. So we can't depend on the NAK interrupt
24028 +                * handler to requeue a NAKed request. Instead, IN requests
24029 +                * are issued each time this function is called. When the
24030 +                * transfer completes, the extra requests for the channel will
24031 +                * be flushed.
24032 +                */
24033 +               hcchar_data_t hcchar;
24034 +               dwc_otg_hc_regs_t *hc_regs =
24035 +                   core_if->host_if->hc_regs[hc->hc_num];
24036 +
24037 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24038 +               hc_set_even_odd_frame(core_if, hc, &hcchar);
24039 +               hcchar.b.chen = 1;
24040 +               hcchar.b.chdis = 0;
24041 +               DWC_DEBUGPL(DBG_HCDV, "  IN xfer: hcchar = 0x%08x\n",
24042 +                           hcchar.d32);
24043 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24044 +               hc->requests++;
24045 +               return 1;
24046 +       } else {
24047 +               /* OUT transfers. */
24048 +               if (hc->xfer_count < hc->xfer_len) {
24049 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
24050 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
24051 +                               hcchar_data_t hcchar;
24052 +                               dwc_otg_hc_regs_t *hc_regs;
24053 +                               hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24054 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24055 +                               hc_set_even_odd_frame(core_if, hc, &hcchar);
24056 +                       }
24057 +
24058 +                       /* Load OUT packet into the appropriate Tx FIFO. */
24059 +                       dwc_otg_hc_write_packet(core_if, hc);
24060 +                       hc->requests++;
24061 +                       return 1;
24062 +               } else {
24063 +                       return 0;
24064 +               }
24065 +       }
24066 +}
24067 +
24068 +/**
24069 + * Starts a PING transfer. This function should only be called in Slave mode.
24070 + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
24071 + */
24072 +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24073 +{
24074 +       hcchar_data_t hcchar;
24075 +       hctsiz_data_t hctsiz;
24076 +       dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
24077 +
24078 +       DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
24079 +
24080 +       hctsiz.d32 = 0;
24081 +       hctsiz.b.dopng = 1;
24082 +       hctsiz.b.pktcnt = 1;
24083 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
24084 +
24085 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
24086 +       hcchar.b.chen = 1;
24087 +       hcchar.b.chdis = 0;
24088 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
24089 +}
24090 +
24091 +/*
24092 + * This function writes a packet into the Tx FIFO associated with the Host
24093 + * Channel. For a channel associated with a non-periodic EP, the non-periodic
24094 + * Tx FIFO is written. For a channel associated with a periodic EP, the
24095 + * periodic Tx FIFO is written. This function should only be called in Slave
24096 + * mode.
24097 + *
24098 + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
24099 + * then number of bytes written to the Tx FIFO.
24100 + */
24101 +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
24102 +{
24103 +       uint32_t i;
24104 +       uint32_t remaining_count;
24105 +       uint32_t byte_count;
24106 +       uint32_t dword_count;
24107 +
24108 +       uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
24109 +       uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
24110 +
24111 +       remaining_count = hc->xfer_len - hc->xfer_count;
24112 +       if (remaining_count > hc->max_packet) {
24113 +               byte_count = hc->max_packet;
24114 +       } else {
24115 +               byte_count = remaining_count;
24116 +       }
24117 +
24118 +       dword_count = (byte_count + 3) / 4;
24119 +
24120 +       if ((((unsigned long)data_buff) & 0x3) == 0) {
24121 +               /* xfer_buff is DWORD aligned. */
24122 +               for (i = 0; i < dword_count; i++, data_buff++) {
24123 +                       DWC_WRITE_REG32(data_fifo, *data_buff);
24124 +               }
24125 +       } else {
24126 +               /* xfer_buff is not DWORD aligned. */
24127 +               for (i = 0; i < dword_count; i++, data_buff++) {
24128 +                       uint32_t data;
24129 +                       data =
24130 +                           (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
24131 +                            16 | data_buff[3] << 24);
24132 +                       DWC_WRITE_REG32(data_fifo, data);
24133 +               }
24134 +       }
24135 +
24136 +       hc->xfer_count += byte_count;
24137 +       hc->xfer_buff += byte_count;
24138 +}
24139 +
24140 +/**
24141 + * Gets the current USB frame number. This is the frame number from the last
24142 + * SOF packet.
24143 + */
24144 +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
24145 +{
24146 +       dsts_data_t dsts;
24147 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
24148 +
24149 +       /* read current frame/microframe number from DSTS register */
24150 +       return dsts.b.soffn;
24151 +}
24152 +
24153 +/**
24154 + * Calculates and gets the frame Interval value of HFIR register according PHY
24155 + * type and speed.The application can modify a value of HFIR register only after
24156 + * the Port Enable bit of the Host Port Control and Status register
24157 + * (HPRT.PrtEnaPort) has been set.
24158 +*/
24159 +
24160 +uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)
24161 +{
24162 +       gusbcfg_data_t usbcfg;
24163 +       hwcfg2_data_t hwcfg2;
24164 +       hprt0_data_t hprt0;
24165 +       int clock = 60;         // default value
24166 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
24167 +       hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
24168 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
24169 +       if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24170 +               clock = 60;
24171 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)
24172 +               clock = 48;
24173 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24174 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24175 +               clock = 30;
24176 +       if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24177 +           !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
24178 +               clock = 60;
24179 +       if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
24180 +           !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
24181 +               clock = 48;
24182 +       if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)
24183 +               clock = 48;
24184 +       if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)
24185 +               clock = 48;
24186 +       if (hprt0.b.prtspd == 0)
24187 +               /* High speed case */
24188 +               return 125 * clock;
24189 +       else
24190 +               /* FS/LS case */
24191 +               return 1000 * clock;
24192 +}
24193 +
24194 +/**
24195 + * This function reads a setup packet from the Rx FIFO into the destination
24196 + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
24197 + * Interrupt routine when a SETUP packet has been received in Slave mode.
24198 + *
24199 + * @param core_if Programming view of DWC_otg controller.
24200 + * @param dest Destination buffer for packet data.
24201 + */
24202 +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
24203 +{
24204 +       device_grxsts_data_t status;
24205 +       /* Get the 8 bytes of a setup transaction data */
24206 +
24207 +       /* Pop 2 DWORDS off the receive data FIFO into memory */
24208 +       dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
24209 +       dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
24210 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
24211 +               status.d32 =
24212 +                   DWC_READ_REG32(&core_if->core_global_regs->grxstsp);
24213 +               DWC_DEBUGPL(DBG_ANY,
24214 +                           "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",
24215 +                           status.b.epnum, status.b.bcnt, status.b.pktsts,
24216 +                           status.b.fn, status.b.fn);
24217 +       }
24218 +}
24219 +
24220 +/**
24221 + * This function enables EP0 OUT to receive SETUP packets and configures EP0
24222 + * IN for transmitting packets. It is normally called when the
24223 + * "Enumeration Done" interrupt occurs.
24224 + *
24225 + * @param core_if Programming view of DWC_otg controller.
24226 + * @param ep The EP0 data.
24227 + */
24228 +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24229 +{
24230 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24231 +       dsts_data_t dsts;
24232 +       depctl_data_t diepctl;
24233 +       depctl_data_t doepctl;
24234 +       dctl_data_t dctl = {.d32 = 0 };
24235 +
24236 +       ep->stp_rollover = 0;
24237 +       /* Read the Device Status and Endpoint 0 Control registers */
24238 +       dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
24239 +       diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
24240 +       doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
24241 +
24242 +       /* Set the MPS of the IN EP based on the enumeration speed */
24243 +       switch (dsts.b.enumspd) {
24244 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
24245 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
24246 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
24247 +               diepctl.b.mps = DWC_DEP0CTL_MPS_64;
24248 +               break;
24249 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
24250 +               diepctl.b.mps = DWC_DEP0CTL_MPS_8;
24251 +               break;
24252 +       }
24253 +
24254 +       DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
24255 +
24256 +       /* Enable OUT EP for receive */
24257 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
24258 +       doepctl.b.epena = 1;
24259 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
24260 +       }
24261 +#ifdef VERBOSE
24262 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
24263 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
24264 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
24265 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
24266 +#endif
24267 +       dctl.b.cgnpinnak = 1;
24268 +
24269 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
24270 +       DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
24271 +                   DWC_READ_REG32(&dev_if->dev_global_regs->dctl));
24272 +
24273 +}
24274 +
24275 +/**
24276 + * This function activates an EP.  The Device EP control register for
24277 + * the EP is configured as defined in the ep structure. Note: This
24278 + * function is not used for EP0.
24279 + *
24280 + * @param core_if Programming view of DWC_otg controller.
24281 + * @param ep The EP to activate.
24282 + */
24283 +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24284 +{
24285 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24286 +       depctl_data_t depctl;
24287 +       volatile uint32_t *addr;
24288 +       daint_data_t daintmsk = {.d32 = 0 };
24289 +       dcfg_data_t dcfg;
24290 +       uint8_t i;
24291 +
24292 +       DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
24293 +                   (ep->is_in ? "IN" : "OUT"));
24294 +
24295 +#ifdef DWC_UTE_PER_IO
24296 +       ep->xiso_frame_num = 0xFFFFFFFF;
24297 +       ep->xiso_active_xfers = 0;
24298 +       ep->xiso_queued_xfers = 0;
24299 +#endif
24300 +       /* Read DEPCTLn register */
24301 +       if (ep->is_in == 1) {
24302 +               addr = &dev_if->in_ep_regs[ep->num]->diepctl;
24303 +               daintmsk.ep.in = 1 << ep->num;
24304 +       } else {
24305 +               addr = &dev_if->out_ep_regs[ep->num]->doepctl;
24306 +               daintmsk.ep.out = 1 << ep->num;
24307 +       }
24308 +
24309 +       /* If the EP is already active don't change the EP Control
24310 +        * register. */
24311 +       depctl.d32 = DWC_READ_REG32(addr);
24312 +       if (!depctl.b.usbactep) {
24313 +               depctl.b.mps = ep->maxpacket;
24314 +               depctl.b.eptype = ep->type;
24315 +               depctl.b.txfnum = ep->tx_fifo_num;
24316 +
24317 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24318 +                       depctl.b.setd0pid = 1;  // ???
24319 +               } else {
24320 +                       depctl.b.setd0pid = 1;
24321 +               }
24322 +               depctl.b.usbactep = 1;
24323 +
24324 +               /* Update nextep_seq array and EPMSCNT in DCFG*/
24325 +               if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) {       // NP IN EP
24326 +                       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24327 +                               if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
24328 +                               break;
24329 +                       }
24330 +                       core_if->nextep_seq[i] = ep->num;
24331 +                       core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
24332 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24333 +                       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
24334 +                       dcfg.b.epmscnt++;
24335 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
24336 +
24337 +                       DWC_DEBUGPL(DBG_PCDV,
24338 +                                   "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24339 +                               __func__, core_if->first_in_nextep_seq);
24340 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24341 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n",
24342 +                                           core_if->nextep_seq[i]);
24343 +                       }
24344 +
24345 +               }
24346 +
24347 +
24348 +               DWC_WRITE_REG32(addr, depctl.d32);
24349 +               DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));
24350 +       }
24351 +
24352 +       /* Enable the Interrupt for this EP */
24353 +       if (core_if->multiproc_int_enable) {
24354 +               if (ep->is_in == 1) {
24355 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
24356 +                       diepmsk.b.xfercompl = 1;
24357 +                       diepmsk.b.timeout = 1;
24358 +                       diepmsk.b.epdisabled = 1;
24359 +                       diepmsk.b.ahberr = 1;
24360 +                       diepmsk.b.intknepmis = 1;
24361 +                       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
24362 +                               diepmsk.b.intknepmis = 0;
24363 +                       diepmsk.b.txfifoundrn = 1;      //?????
24364 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24365 +                               diepmsk.b.nak = 1;
24366 +                       }
24367 +
24368 +
24369 +
24370 +/*
24371 +                       if (core_if->dma_desc_enable) {
24372 +                               diepmsk.b.bna = 1;
24373 +                       }
24374 +*/
24375 +/*
24376 +                       if (core_if->dma_enable) {
24377 +                               doepmsk.b.nak = 1;
24378 +                       }
24379 +*/
24380 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24381 +                                       diepeachintmsk[ep->num], diepmsk.d32);
24382 +
24383 +               } else {
24384 +                       doepmsk_data_t doepmsk = {.d32 = 0 };
24385 +                       doepmsk.b.xfercompl = 1;
24386 +                       doepmsk.b.ahberr = 1;
24387 +                       doepmsk.b.epdisabled = 1;
24388 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24389 +                               doepmsk.b.outtknepdis = 1;
24390 +
24391 +/*
24392 +
24393 +                       if (core_if->dma_desc_enable) {
24394 +                               doepmsk.b.bna = 1;
24395 +                       }
24396 +*/
24397 +/*
24398 +                       doepmsk.b.babble = 1;
24399 +                       doepmsk.b.nyet = 1;
24400 +                       doepmsk.b.nak = 1;
24401 +*/
24402 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->
24403 +                                       doepeachintmsk[ep->num], doepmsk.d32);
24404 +               }
24405 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
24406 +                                0, daintmsk.d32);
24407 +       } else {
24408 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24409 +                       if (ep->is_in) {
24410 +                               diepmsk_data_t diepmsk = {.d32 = 0 };
24411 +                               diepmsk.b.nak = 1;
24412 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
24413 +                       } else {
24414 +                               doepmsk_data_t doepmsk = {.d32 = 0 };
24415 +                               doepmsk.b.outtknepdis = 1;
24416 +                               DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
24417 +                       }
24418 +               }
24419 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
24420 +                                0, daintmsk.d32);
24421 +       }
24422 +
24423 +       DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
24424 +                   DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));
24425 +
24426 +       ep->stall_clear_flag = 0;
24427 +
24428 +       return;
24429 +}
24430 +
24431 +/**
24432 + * This function deactivates an EP. This is done by clearing the USB Active
24433 + * EP bit in the Device EP control register. Note: This function is not used
24434 + * for EP0. EP0 cannot be deactivated.
24435 + *
24436 + * @param core_if Programming view of DWC_otg controller.
24437 + * @param ep The EP to deactivate.
24438 + */
24439 +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24440 +{
24441 +       depctl_data_t depctl = {.d32 = 0 };
24442 +       volatile uint32_t *addr;
24443 +       daint_data_t daintmsk = {.d32 = 0 };
24444 +       dcfg_data_t dcfg;
24445 +       uint8_t i = 0;
24446 +
24447 +#ifdef DWC_UTE_PER_IO
24448 +       ep->xiso_frame_num = 0xFFFFFFFF;
24449 +       ep->xiso_active_xfers = 0;
24450 +       ep->xiso_queued_xfers = 0;
24451 +#endif
24452 +
24453 +       /* Read DEPCTLn register */
24454 +       if (ep->is_in == 1) {
24455 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
24456 +               daintmsk.ep.in = 1 << ep->num;
24457 +       } else {
24458 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
24459 +               daintmsk.ep.out = 1 << ep->num;
24460 +       }
24461 +
24462 +       depctl.d32 = DWC_READ_REG32(addr);
24463 +
24464 +       depctl.b.usbactep = 0;
24465 +
24466 +       /* Update nextep_seq array and EPMSCNT in DCFG*/
24467 +       if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN
24468 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
24469 +                       if (core_if->nextep_seq[i] == ep->num)
24470 +                       break;
24471 +               }
24472 +               core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];
24473 +               if (core_if->first_in_nextep_seq == ep->num)
24474 +                       core_if->first_in_nextep_seq = i;
24475 +               core_if->nextep_seq[ep->num] = 0xff;
24476 +               depctl.b.nextep = 0;
24477 +               dcfg.d32 =
24478 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
24479 +               dcfg.b.epmscnt--;
24480 +               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
24481 +                               dcfg.d32);
24482 +
24483 +               DWC_DEBUGPL(DBG_PCDV,
24484 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
24485 +                               __func__, core_if->first_in_nextep_seq);
24486 +                       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
24487 +                               DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
24488 +                       }
24489 +       }
24490 +
24491 +       if (ep->is_in == 1)
24492 +               depctl.b.txfnum = 0;
24493 +
24494 +       if (core_if->dma_desc_enable)
24495 +               depctl.b.epdis = 1;
24496 +
24497 +       DWC_WRITE_REG32(addr, depctl.d32);
24498 +       depctl.d32 = DWC_READ_REG32(addr);
24499 +       if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC
24500 +           && depctl.b.epena) {
24501 +               depctl_data_t depctl = {.d32 = 0};
24502 +               if (ep->is_in) {
24503 +                       diepint_data_t diepint = {.d32 = 0};
24504 +
24505 +                       depctl.b.snak = 1;
24506 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24507 +                                       diepctl, depctl.d32);
24508 +                       do {
24509 +                               dwc_udelay(10);
24510 +                               diepint.d32 =
24511 +                                   DWC_READ_REG32(&core_if->
24512 +                                                  dev_if->in_ep_regs[ep->num]->
24513 +                                                  diepint);
24514 +                       } while (!diepint.b.inepnakeff);
24515 +                       diepint.b.inepnakeff = 1;
24516 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24517 +                                       diepint, diepint.d32);
24518 +                       depctl.d32 = 0;
24519 +                       depctl.b.epdis = 1;
24520 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24521 +                                       diepctl, depctl.d32);
24522 +                       do {
24523 +                               dwc_udelay(10);
24524 +                               diepint.d32 =
24525 +                                   DWC_READ_REG32(&core_if->
24526 +                                                  dev_if->in_ep_regs[ep->num]->
24527 +                                                  diepint);
24528 +                       } while (!diepint.b.epdisabled);
24529 +                       diepint.b.epdisabled = 1;
24530 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
24531 +                                       diepint, diepint.d32);
24532 +               } else {
24533 +                       dctl_data_t dctl = {.d32 = 0};
24534 +                       gintmsk_data_t gintsts = {.d32 = 0};
24535 +                       doepint_data_t doepint = {.d32 = 0};
24536 +                       dctl.b.sgoutnak = 1;
24537 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
24538 +                                        dctl, 0, dctl.d32);
24539 +                       do {
24540 +                               dwc_udelay(10);
24541 +                               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
24542 +                       } while (!gintsts.b.goutnakeff);
24543 +                       gintsts.d32 = 0;
24544 +                       gintsts.b.goutnakeff = 1;
24545 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
24546 +
24547 +                       depctl.d32 = 0;
24548 +                       depctl.b.epdis = 1;
24549 +                       depctl.b.snak = 1;
24550 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
24551 +                       do
24552 +                       {
24553 +                               dwc_udelay(10);
24554 +                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
24555 +                                                                                       out_ep_regs[ep->num]->doepint);
24556 +                       } while (!doepint.b.epdisabled);
24557 +
24558 +                       doepint.b.epdisabled = 1;
24559 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
24560 +
24561 +                       dctl.d32 = 0;
24562 +                       dctl.b.cgoutnak = 1;
24563 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
24564 +               }
24565 +       }
24566 +
24567 +       /* Disable the Interrupt for this EP */
24568 +       if (core_if->multiproc_int_enable) {
24569 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
24570 +                                daintmsk.d32, 0);
24571 +
24572 +               if (ep->is_in == 1) {
24573 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24574 +                                       diepeachintmsk[ep->num], 0);
24575 +               } else {
24576 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
24577 +                                       doepeachintmsk[ep->num], 0);
24578 +               }
24579 +       } else {
24580 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,
24581 +                                daintmsk.d32, 0);
24582 +       }
24583 +
24584 +}
24585 +
24586 +/**
24587 + * This function initializes dma descriptor chain.
24588 + *
24589 + * @param core_if Programming view of DWC_otg controller.
24590 + * @param ep The EP to start the transfer on.
24591 + */
24592 +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24593 +{
24594 +       dwc_otg_dev_dma_desc_t *dma_desc;
24595 +       uint32_t offset;
24596 +       uint32_t xfer_est;
24597 +       int i;
24598 +       unsigned maxxfer_local, total_len;
24599 +
24600 +       if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&
24601 +                                       (ep->maxpacket%4)) {
24602 +               maxxfer_local = ep->maxpacket;
24603 +               total_len = ep->xfer_len;
24604 +       } else {
24605 +               maxxfer_local = ep->maxxfer;
24606 +               total_len = ep->total_len;
24607 +       }
24608 +
24609 +       ep->desc_cnt = (total_len / maxxfer_local) +
24610 +            ((total_len % maxxfer_local) ? 1 : 0);
24611 +
24612 +       if (!ep->desc_cnt)
24613 +               ep->desc_cnt = 1;
24614 +
24615 +       if (ep->desc_cnt > MAX_DMA_DESC_CNT)
24616 +               ep->desc_cnt = MAX_DMA_DESC_CNT;
24617 +
24618 +       dma_desc = ep->desc_addr;
24619 +       if (maxxfer_local == ep->maxpacket) {
24620 +               if ((total_len % maxxfer_local) &&
24621 +                               (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
24622 +                       xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
24623 +                                       (total_len % maxxfer_local);
24624 +               } else
24625 +                       xfer_est = ep->desc_cnt * maxxfer_local;
24626 +       } else
24627 +               xfer_est = total_len;
24628 +       offset = 0;
24629 +       for (i = 0; i < ep->desc_cnt; ++i) {
24630 +               /** DMA Descriptor Setup */
24631 +               if (xfer_est > maxxfer_local) {
24632 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24633 +                       dma_desc->status.b.l = 0;
24634 +                       dma_desc->status.b.ioc = 0;
24635 +                       dma_desc->status.b.sp = 0;
24636 +                       dma_desc->status.b.bytes = maxxfer_local;
24637 +                       dma_desc->buf = ep->dma_addr + offset;
24638 +                       dma_desc->status.b.sts = 0;
24639 +                       dma_desc->status.b.bs = BS_HOST_READY;
24640 +
24641 +                       xfer_est -= maxxfer_local;
24642 +                       offset += maxxfer_local;
24643 +               } else {
24644 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
24645 +                       dma_desc->status.b.l = 1;
24646 +                       dma_desc->status.b.ioc = 1;
24647 +                       if (ep->is_in) {
24648 +                               dma_desc->status.b.sp =
24649 +                                   (xfer_est %
24650 +                                    ep->maxpacket) ? 1 : ((ep->
24651 +                                                           sent_zlp) ? 1 : 0);
24652 +                               dma_desc->status.b.bytes = xfer_est;
24653 +                       } else {
24654 +                               if (maxxfer_local == ep->maxpacket)
24655 +                                       dma_desc->status.b.bytes = xfer_est;
24656 +                               else
24657 +                                       dma_desc->status.b.bytes =
24658 +                                               xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
24659 +                       }
24660 +
24661 +                       dma_desc->buf = ep->dma_addr + offset;
24662 +                       dma_desc->status.b.sts = 0;
24663 +                       dma_desc->status.b.bs = BS_HOST_READY;
24664 +               }
24665 +               dma_desc++;
24666 +       }
24667 +}
24668 +/**
24669 + * This function is called when to write ISOC data into appropriate dedicated
24670 + * periodic FIFO.
24671 + */
24672 +static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
24673 +{
24674 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
24675 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
24676 +       dtxfsts_data_t txstatus = {.d32 = 0 };
24677 +       uint32_t len = 0;
24678 +       int epnum = dwc_ep->num;
24679 +       int dwords;
24680 +
24681 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
24682 +
24683 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
24684 +
24685 +       len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24686 +
24687 +       if (len > dwc_ep->maxpacket) {
24688 +               len = dwc_ep->maxpacket;
24689 +       }
24690 +
24691 +       dwords = (len + 3) / 4;
24692 +
24693 +       /* While there is space in the queue and space in the FIFO and
24694 +        * More data to tranfer, Write packets to the Tx FIFO */
24695 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24696 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
24697 +
24698 +       while (txstatus.b.txfspcavail > dwords &&
24699 +              dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {
24700 +               /* Write the FIFO */
24701 +               dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
24702 +
24703 +               len = dwc_ep->xfer_len - dwc_ep->xfer_count;
24704 +               if (len > dwc_ep->maxpacket) {
24705 +                       len = dwc_ep->maxpacket;
24706 +               }
24707 +
24708 +               dwords = (len + 3) / 4;
24709 +               txstatus.d32 =
24710 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
24711 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
24712 +                           txstatus.d32);
24713 +       }
24714 +
24715 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
24716 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
24717 +
24718 +       return 1;
24719 +}
24720 +/**
24721 + * This function does the setup for a data transfer for an EP and
24722 + * starts the transfer. For an IN transfer, the packets will be
24723 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
24724 + * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
24725 + *
24726 + * @param core_if Programming view of DWC_otg controller.
24727 + * @param ep The EP to start the transfer on.
24728 + */
24729 +
24730 +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
24731 +{
24732 +       depctl_data_t depctl;
24733 +       deptsiz_data_t deptsiz;
24734 +       gintmsk_data_t intr_mask = {.d32 = 0 };
24735 +
24736 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
24737 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
24738 +                   "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
24739 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
24740 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
24741 +                   ep->total_len);
24742 +       /* IN endpoint */
24743 +       if (ep->is_in == 1) {
24744 +               dwc_otg_dev_in_ep_regs_t *in_regs =
24745 +                   core_if->dev_if->in_ep_regs[ep->num];
24746 +
24747 +               gnptxsts_data_t gtxstatus;
24748 +
24749 +               gtxstatus.d32 =
24750 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
24751 +
24752 +               if (core_if->en_multiple_tx_fifo == 0
24753 +                   && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {
24754 +#ifdef DEBUG
24755 +                       DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
24756 +#endif
24757 +                       return;
24758 +               }
24759 +
24760 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
24761 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
24762 +
24763 +               if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24764 +                       ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24765 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24766 +               else
24767 +                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
24768 +                                MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24769 +
24770 +
24771 +               /* Zero Length Packet? */
24772 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24773 +                       deptsiz.b.xfersize = 0;
24774 +                       deptsiz.b.pktcnt = 1;
24775 +               } else {
24776 +                       /* Program the transfer size and packet count
24777 +                        *      as follows: xfersize = N * maxpacket +
24778 +                        *      short_packet pktcnt = N + (short_packet
24779 +                        *      exist ? 1 : 0)
24780 +                        */
24781 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24782 +                       deptsiz.b.pktcnt =
24783 +                           (ep->xfer_len - ep->xfer_count - 1 +
24784 +                            ep->maxpacket) / ep->maxpacket;
24785 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24786 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24787 +                               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
24788 +                       }
24789 +                       if (ep->type == DWC_OTG_EP_TYPE_ISOC)
24790 +                               deptsiz.b.mc = deptsiz.b.pktcnt;
24791 +               }
24792 +
24793 +               /* Write the DMA register */
24794 +               if (core_if->dma_enable) {
24795 +                       if (core_if->dma_desc_enable == 0) {
24796 +                               if (ep->type != DWC_OTG_EP_TYPE_ISOC)
24797 +                                       deptsiz.b.mc = 1;
24798 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
24799 +                                               deptsiz.d32);
24800 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
24801 +                                               (uint32_t) ep->dma_addr);
24802 +                       } else {
24803 +#ifdef DWC_UTE_CFI
24804 +                               /* The descriptor chain should be already initialized by now */
24805 +                               if (ep->buff_mode != BM_STANDARD) {
24806 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24807 +                                                       ep->descs_dma_addr);
24808 +                               } else {
24809 +#endif
24810 +                                       init_dma_desc_chain(core_if, ep);
24811 +                               /** DIEPDMAn Register write */
24812 +                                       DWC_WRITE_REG32(&in_regs->diepdma,
24813 +                                                       ep->dma_desc_addr);
24814 +#ifdef DWC_UTE_CFI
24815 +                               }
24816 +#endif
24817 +                       }
24818 +               } else {
24819 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
24820 +                       if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
24821 +                               /**
24822 +                                * Enable the Non-Periodic Tx FIFO empty interrupt,
24823 +                                * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
24824 +                                * the data will be written into the fifo by the ISR.
24825 +                                */
24826 +                               if (core_if->en_multiple_tx_fifo == 0) {
24827 +                                       intr_mask.b.nptxfempty = 1;
24828 +                                       DWC_MODIFY_REG32
24829 +                                           (&core_if->core_global_regs->gintmsk,
24830 +                                            intr_mask.d32, intr_mask.d32);
24831 +                               } else {
24832 +                                       /* Enable the Tx FIFO Empty Interrupt for this EP */
24833 +                                       if (ep->xfer_len > 0) {
24834 +                                               uint32_t fifoemptymsk = 0;
24835 +                                               fifoemptymsk = 1 << ep->num;
24836 +                                               DWC_MODIFY_REG32
24837 +                                                   (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
24838 +                                                    0, fifoemptymsk);
24839 +
24840 +                                       }
24841 +                               }
24842 +                       }  else {
24843 +                                        write_isoc_tx_fifo(core_if, ep);
24844 +                       }
24845 +               }
24846 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
24847 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
24848 +
24849 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24850 +                       dsts_data_t dsts = {.d32 = 0};
24851 +                       if (ep->bInterval == 1) {
24852 +                               dsts.d32 =
24853 +                                   DWC_READ_REG32(&core_if->dev_if->
24854 +                                                  dev_global_regs->dsts);
24855 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
24856 +                               if (ep->frame_num > 0x3FFF) {
24857 +                                       ep->frm_overrun = 1;
24858 +                                       ep->frame_num &= 0x3FFF;
24859 +                               } else
24860 +                                       ep->frm_overrun = 0;
24861 +                               if (ep->frame_num & 0x1) {
24862 +                                       depctl.b.setd1pid = 1;
24863 +                               } else {
24864 +                                       depctl.b.setd0pid = 1;
24865 +                               }
24866 +                       }
24867 +               }
24868 +               /* EP enable, IN data in FIFO */
24869 +               depctl.b.cnak = 1;
24870 +               depctl.b.epena = 1;
24871 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
24872 +
24873 +       } else {
24874 +               /* OUT endpoint */
24875 +               dwc_otg_dev_out_ep_regs_t *out_regs =
24876 +                   core_if->dev_if->out_ep_regs[ep->num];
24877 +
24878 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
24879 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
24880 +
24881 +               if (!core_if->dma_desc_enable) {
24882 +                       if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
24883 +                               ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
24884 +                               ep->maxxfer : (ep->total_len - ep->xfer_len);
24885 +                else
24886 +                                       ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len
24887 +                                       - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
24888 +               }
24889 +
24890 +               /* Program the transfer size and packet count as follows:
24891 +                *
24892 +                *      pktcnt = N
24893 +                *      xfersize = N * maxpacket
24894 +                */
24895 +               if ((ep->xfer_len - ep->xfer_count) == 0) {
24896 +                       /* Zero Length Packet */
24897 +                       deptsiz.b.xfersize = ep->maxpacket;
24898 +                       deptsiz.b.pktcnt = 1;
24899 +               } else {
24900 +                       deptsiz.b.pktcnt =
24901 +                           (ep->xfer_len - ep->xfer_count +
24902 +                            (ep->maxpacket - 1)) / ep->maxpacket;
24903 +                       if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
24904 +                               deptsiz.b.pktcnt = MAX_PKT_CNT;
24905 +                       }
24906 +                       if (!core_if->dma_desc_enable) {
24907 +                               ep->xfer_len =
24908 +                                       deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
24909 +                       }
24910 +                       deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
24911 +               }
24912 +
24913 +               DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
24914 +                           ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
24915 +
24916 +               if (core_if->dma_enable) {
24917 +                       if (!core_if->dma_desc_enable) {
24918 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
24919 +                                               deptsiz.d32);
24920 +
24921 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
24922 +                                               (uint32_t) ep->dma_addr);
24923 +                       } else {
24924 +#ifdef DWC_UTE_CFI
24925 +                               /* The descriptor chain should be already initialized by now */
24926 +                               if (ep->buff_mode != BM_STANDARD) {
24927 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
24928 +                                                       ep->descs_dma_addr);
24929 +                               } else {
24930 +#endif
24931 +                                       /** This is used for interrupt out transfers*/
24932 +                                       if (!ep->xfer_len)
24933 +                                               ep->xfer_len = ep->total_len;
24934 +                                       init_dma_desc_chain(core_if, ep);
24935 +
24936 +                                       if (core_if->core_params->dev_out_nak) {
24937 +                                               if (ep->type == DWC_OTG_EP_TYPE_BULK) {
24938 +                                                       deptsiz.b.pktcnt = (ep->total_len +
24939 +                                                               (ep->maxpacket - 1)) / ep->maxpacket;
24940 +                                                       deptsiz.b.xfersize = ep->total_len;
24941 +                                                       /* Remember initial value of doeptsiz */
24942 +                                                       core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
24943 +                                                       DWC_WRITE_REG32(&out_regs->doeptsiz,
24944 +                                                               deptsiz.d32);
24945 +                                               }
24946 +                                       }
24947 +                               /** DOEPDMAn Register write */
24948 +                                       DWC_WRITE_REG32(&out_regs->doepdma,
24949 +                                                       ep->dma_desc_addr);
24950 +#ifdef DWC_UTE_CFI
24951 +                               }
24952 +#endif
24953 +                       }
24954 +               } else {
24955 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
24956 +               }
24957 +
24958 +               if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
24959 +                       dsts_data_t dsts = {.d32 = 0};
24960 +                       if (ep->bInterval == 1) {
24961 +                               dsts.d32 =
24962 +                                   DWC_READ_REG32(&core_if->dev_if->
24963 +                                                  dev_global_regs->dsts);
24964 +                               ep->frame_num = dsts.b.soffn + ep->bInterval;
24965 +                               if (ep->frame_num > 0x3FFF) {
24966 +                                       ep->frm_overrun = 1;
24967 +                                       ep->frame_num &= 0x3FFF;
24968 +                               } else
24969 +                                       ep->frm_overrun = 0;
24970 +
24971 +                               if (ep->frame_num & 0x1) {
24972 +                                       depctl.b.setd1pid = 1;
24973 +                               } else {
24974 +                                       depctl.b.setd0pid = 1;
24975 +                               }
24976 +                       }
24977 +               }
24978 +
24979 +               /* EP enable */
24980 +               depctl.b.cnak = 1;
24981 +               depctl.b.epena = 1;
24982 +
24983 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
24984 +
24985 +               DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
24986 +                           DWC_READ_REG32(&out_regs->doepctl),
24987 +                           DWC_READ_REG32(&out_regs->doeptsiz));
24988 +               DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
24989 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
24990 +                                          daintmsk),
24991 +                           DWC_READ_REG32(&core_if->core_global_regs->
24992 +                                          gintmsk));
24993 +
24994 +               /* Timer is scheduling only for out bulk transfers for
24995 +                * "Device DDMA OUT NAK Enhancement" feature to inform user
24996 +                * about received data payload in case of timeout
24997 +                */
24998 +               if (core_if->core_params->dev_out_nak) {
24999 +                       if (ep->type == DWC_OTG_EP_TYPE_BULK) {
25000 +                               core_if->ep_xfer_info[ep->num].core_if = core_if;
25001 +                               core_if->ep_xfer_info[ep->num].ep = ep;
25002 +                               core_if->ep_xfer_info[ep->num].state = 1;
25003 +
25004 +                               /* Start a timer for this transfer. */
25005 +                               DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);
25006 +                       }
25007 +               }
25008 +       }
25009 +}
25010 +
25011 +/**
25012 + * This function setup a zero length transfer in Buffer DMA and
25013 + * Slave modes for usb requests with zero field set
25014 + *
25015 + * @param core_if Programming view of DWC_otg controller.
25016 + * @param ep The EP to start the transfer on.
25017 + *
25018 + */
25019 +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25020 +{
25021 +
25022 +       depctl_data_t depctl;
25023 +       deptsiz_data_t deptsiz;
25024 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25025 +
25026 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
25027 +       DWC_PRINTF("zero length transfer is called\n");
25028 +
25029 +       /* IN endpoint */
25030 +       if (ep->is_in == 1) {
25031 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25032 +                   core_if->dev_if->in_ep_regs[ep->num];
25033 +
25034 +               depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
25035 +               deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
25036 +
25037 +               deptsiz.b.xfersize = 0;
25038 +               deptsiz.b.pktcnt = 1;
25039 +
25040 +               /* Write the DMA register */
25041 +               if (core_if->dma_enable) {
25042 +                       if (core_if->dma_desc_enable == 0) {
25043 +                               deptsiz.b.mc = 1;
25044 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25045 +                                               deptsiz.d32);
25046 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25047 +                                               (uint32_t) ep->dma_addr);
25048 +                       }
25049 +               } else {
25050 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25051 +                       /**
25052 +                        * Enable the Non-Periodic Tx FIFO empty interrupt,
25053 +                        * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
25054 +                        * the data will be written into the fifo by the ISR.
25055 +                        */
25056 +                       if (core_if->en_multiple_tx_fifo == 0) {
25057 +                               intr_mask.b.nptxfempty = 1;
25058 +                               DWC_MODIFY_REG32(&core_if->
25059 +                                                core_global_regs->gintmsk,
25060 +                                                intr_mask.d32, intr_mask.d32);
25061 +                       } else {
25062 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25063 +                               if (ep->xfer_len > 0) {
25064 +                                       uint32_t fifoemptymsk = 0;
25065 +                                       fifoemptymsk = 1 << ep->num;
25066 +                                       DWC_MODIFY_REG32(&core_if->
25067 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25068 +                                                        0, fifoemptymsk);
25069 +                               }
25070 +                       }
25071 +               }
25072 +
25073 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25074 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25075 +               /* EP enable, IN data in FIFO */
25076 +               depctl.b.cnak = 1;
25077 +               depctl.b.epena = 1;
25078 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25079 +
25080 +       } else {
25081 +               /* OUT endpoint */
25082 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25083 +                   core_if->dev_if->out_ep_regs[ep->num];
25084 +
25085 +               depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
25086 +               deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
25087 +
25088 +               /* Zero Length Packet */
25089 +               deptsiz.b.xfersize = ep->maxpacket;
25090 +               deptsiz.b.pktcnt = 1;
25091 +
25092 +               if (core_if->dma_enable) {
25093 +                       if (!core_if->dma_desc_enable) {
25094 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25095 +                                               deptsiz.d32);
25096 +
25097 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25098 +                                               (uint32_t) ep->dma_addr);
25099 +                       }
25100 +               } else {
25101 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25102 +               }
25103 +
25104 +               /* EP enable */
25105 +               depctl.b.cnak = 1;
25106 +               depctl.b.epena = 1;
25107 +
25108 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25109 +
25110 +       }
25111 +}
25112 +
25113 +/**
25114 + * This function does the setup for a data transfer for EP0 and starts
25115 + * the transfer.  For an IN transfer, the packets will be loaded into
25116 + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
25117 + * unloaded from the Rx FIFO in the ISR.
25118 + *
25119 + * @param core_if Programming view of DWC_otg controller.
25120 + * @param ep The EP0 data.
25121 + */
25122 +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25123 +{
25124 +       depctl_data_t depctl;
25125 +       deptsiz0_data_t deptsiz;
25126 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25127 +       dwc_otg_dev_dma_desc_t *dma_desc;
25128 +
25129 +       DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
25130 +                   "xfer_buff=%p start_xfer_buff=%p \n",
25131 +                   ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
25132 +                   ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
25133 +
25134 +       ep->total_len = ep->xfer_len;
25135 +
25136 +       /* IN endpoint */
25137 +       if (ep->is_in == 1) {
25138 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25139 +                   core_if->dev_if->in_ep_regs[0];
25140 +
25141 +               gnptxsts_data_t gtxstatus;
25142 +
25143 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25144 +                       depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25145 +                       if (depctl.b.epena)
25146 +                               return;
25147 +               }
25148 +
25149 +               gtxstatus.d32 =
25150 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25151 +
25152 +               /* If dedicated FIFO every time flush fifo before enable ep*/
25153 +               if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)
25154 +                       dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
25155 +
25156 +               if (core_if->en_multiple_tx_fifo == 0
25157 +                   && gtxstatus.b.nptxqspcavail == 0
25158 +                   && !core_if->dma_enable) {
25159 +#ifdef DEBUG
25160 +                       deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25161 +                       DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
25162 +                                   DWC_READ_REG32(&in_regs->diepctl));
25163 +                       DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
25164 +                                   deptsiz.d32,
25165 +                                   deptsiz.b.xfersize, deptsiz.b.pktcnt);
25166 +                       DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
25167 +                                  gtxstatus.d32);
25168 +#endif
25169 +                       return;
25170 +               }
25171 +
25172 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25173 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25174 +
25175 +               /* Zero Length Packet? */
25176 +               if (ep->xfer_len == 0) {
25177 +                       deptsiz.b.xfersize = 0;
25178 +                       deptsiz.b.pktcnt = 1;
25179 +               } else {
25180 +                       /* Program the transfer size and packet count
25181 +                        *      as follows: xfersize = N * maxpacket +
25182 +                        *      short_packet pktcnt = N + (short_packet
25183 +                        *      exist ? 1 : 0)
25184 +                        */
25185 +                       if (ep->xfer_len > ep->maxpacket) {
25186 +                               ep->xfer_len = ep->maxpacket;
25187 +                               deptsiz.b.xfersize = ep->maxpacket;
25188 +                       } else {
25189 +                               deptsiz.b.xfersize = ep->xfer_len;
25190 +                       }
25191 +                       deptsiz.b.pktcnt = 1;
25192 +
25193 +               }
25194 +               DWC_DEBUGPL(DBG_PCDV,
25195 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25196 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25197 +                           deptsiz.d32);
25198 +
25199 +               /* Write the DMA register */
25200 +               if (core_if->dma_enable) {
25201 +                       if (core_if->dma_desc_enable == 0) {
25202 +                               DWC_WRITE_REG32(&in_regs->dieptsiz,
25203 +                                               deptsiz.d32);
25204 +
25205 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25206 +                                               (uint32_t) ep->dma_addr);
25207 +                       } else {
25208 +                               dma_desc = core_if->dev_if->in_desc_addr;
25209 +
25210 +                               /** DMA Descriptor Setup */
25211 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25212 +                               dma_desc->status.b.l = 1;
25213 +                               dma_desc->status.b.ioc = 1;
25214 +                               dma_desc->status.b.sp =
25215 +                                   (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25216 +                               dma_desc->status.b.bytes = ep->xfer_len;
25217 +                               dma_desc->buf = ep->dma_addr;
25218 +                               dma_desc->status.b.sts = 0;
25219 +                               dma_desc->status.b.bs = BS_HOST_READY;
25220 +
25221 +                               /** DIEPDMA0 Register write */
25222 +                               DWC_WRITE_REG32(&in_regs->diepdma,
25223 +                                               core_if->
25224 +                                               dev_if->dma_in_desc_addr);
25225 +                       }
25226 +               } else {
25227 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25228 +               }
25229 +
25230 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25231 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25232 +               /* EP enable, IN data in FIFO */
25233 +               depctl.b.cnak = 1;
25234 +               depctl.b.epena = 1;
25235 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25236 +
25237 +               /**
25238 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25239 +                * data will be written into the fifo by the ISR.
25240 +                */
25241 +               if (!core_if->dma_enable) {
25242 +                       if (core_if->en_multiple_tx_fifo == 0) {
25243 +                               intr_mask.b.nptxfempty = 1;
25244 +                               DWC_MODIFY_REG32(&core_if->
25245 +                                                core_global_regs->gintmsk,
25246 +                                                intr_mask.d32, intr_mask.d32);
25247 +                       } else {
25248 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25249 +                               if (ep->xfer_len > 0) {
25250 +                                       uint32_t fifoemptymsk = 0;
25251 +                                       fifoemptymsk |= 1 << ep->num;
25252 +                                       DWC_MODIFY_REG32(&core_if->
25253 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25254 +                                                        0, fifoemptymsk);
25255 +                               }
25256 +                       }
25257 +               }
25258 +       } else {
25259 +               /* OUT endpoint */
25260 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25261 +                   core_if->dev_if->out_ep_regs[0];
25262 +
25263 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25264 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25265 +
25266 +               /* Program the transfer size and packet count as follows:
25267 +                *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))
25268 +                *      pktcnt = N                                                                                      */
25269 +               /* Zero Length Packet */
25270 +               deptsiz.b.xfersize = ep->maxpacket;
25271 +               deptsiz.b.pktcnt = 1;
25272 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
25273 +                       deptsiz.b.supcnt = 3;
25274 +
25275 +               DWC_DEBUGPL(DBG_PCDV, "len=%d  xfersize=%d pktcnt=%d\n",
25276 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
25277 +
25278 +               if (core_if->dma_enable) {
25279 +                       if (!core_if->dma_desc_enable) {
25280 +                               DWC_WRITE_REG32(&out_regs->doeptsiz,
25281 +                                               deptsiz.d32);
25282 +
25283 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25284 +                                               (uint32_t) ep->dma_addr);
25285 +                       } else {
25286 +                               dma_desc = core_if->dev_if->out_desc_addr;
25287 +
25288 +                               /** DMA Descriptor Setup */
25289 +                               dma_desc->status.b.bs = BS_HOST_BUSY;
25290 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
25291 +                                       dma_desc->status.b.mtrf = 0;
25292 +                                       dma_desc->status.b.sr = 0;
25293 +                               }
25294 +                               dma_desc->status.b.l = 1;
25295 +                               dma_desc->status.b.ioc = 1;
25296 +                               dma_desc->status.b.bytes = ep->maxpacket;
25297 +                               dma_desc->buf = ep->dma_addr;
25298 +                               dma_desc->status.b.sts = 0;
25299 +                               dma_desc->status.b.bs = BS_HOST_READY;
25300 +
25301 +                               /** DOEPDMA0 Register write */
25302 +                               DWC_WRITE_REG32(&out_regs->doepdma,
25303 +                                               core_if->dev_if->
25304 +                                               dma_out_desc_addr);
25305 +                       }
25306 +               } else {
25307 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25308 +               }
25309 +
25310 +               /* EP enable */
25311 +               depctl.b.cnak = 1;
25312 +               depctl.b.epena = 1;
25313 +               DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
25314 +       }
25315 +}
25316 +
25317 +/**
25318 + * This function continues control IN transfers started by
25319 + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
25320 + * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
25321 + * bit for the packet count.
25322 + *
25323 + * @param core_if Programming view of DWC_otg controller.
25324 + * @param ep The EP0 data.
25325 + */
25326 +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25327 +{
25328 +       depctl_data_t depctl;
25329 +       deptsiz0_data_t deptsiz;
25330 +       gintmsk_data_t intr_mask = {.d32 = 0 };
25331 +       dwc_otg_dev_dma_desc_t *dma_desc;
25332 +
25333 +       if (ep->is_in == 1) {
25334 +               dwc_otg_dev_in_ep_regs_t *in_regs =
25335 +                   core_if->dev_if->in_ep_regs[0];
25336 +               gnptxsts_data_t tx_status = {.d32 = 0 };
25337 +
25338 +               tx_status.d32 =
25339 +                   DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
25340 +               /** @todo Should there be check for room in the Tx
25341 +                * Status Queue.  If not remove the code above this comment. */
25342 +
25343 +               depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
25344 +               deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
25345 +
25346 +               /* Program the transfer size and packet count
25347 +                *      as follows: xfersize = N * maxpacket +
25348 +                *      short_packet pktcnt = N + (short_packet
25349 +                *      exist ? 1 : 0)
25350 +                */
25351 +
25352 +               if (core_if->dma_desc_enable == 0) {
25353 +                       deptsiz.b.xfersize =
25354 +                           (ep->total_len - ep->xfer_count) >
25355 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25356 +                                                            ep->xfer_count);
25357 +                       deptsiz.b.pktcnt = 1;
25358 +                       if (core_if->dma_enable == 0) {
25359 +                               ep->xfer_len += deptsiz.b.xfersize;
25360 +                       } else {
25361 +                               ep->xfer_len = deptsiz.b.xfersize;
25362 +                       }
25363 +                       DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
25364 +               } else {
25365 +                       ep->xfer_len =
25366 +                           (ep->total_len - ep->xfer_count) >
25367 +                           ep->maxpacket ? ep->maxpacket : (ep->total_len -
25368 +                                                            ep->xfer_count);
25369 +
25370 +                       dma_desc = core_if->dev_if->in_desc_addr;
25371 +
25372 +                       /** DMA Descriptor Setup */
25373 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25374 +                       dma_desc->status.b.l = 1;
25375 +                       dma_desc->status.b.ioc = 1;
25376 +                       dma_desc->status.b.sp =
25377 +                           (ep->xfer_len == ep->maxpacket) ? 0 : 1;
25378 +                       dma_desc->status.b.bytes = ep->xfer_len;
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 +                       /** DIEPDMA0 Register write */
25384 +                       DWC_WRITE_REG32(&in_regs->diepdma,
25385 +                                       core_if->dev_if->dma_in_desc_addr);
25386 +               }
25387 +
25388 +               DWC_DEBUGPL(DBG_PCDV,
25389 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25390 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25391 +                           deptsiz.d32);
25392 +
25393 +               /* Write the DMA register */
25394 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25395 +                       if (core_if->dma_desc_enable == 0)
25396 +                               DWC_WRITE_REG32(&(in_regs->diepdma),
25397 +                                               (uint32_t) ep->dma_addr);
25398 +               }
25399 +               if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
25400 +                       depctl.b.nextep = core_if->nextep_seq[ep->num];
25401 +               /* EP enable, IN data in FIFO */
25402 +               depctl.b.cnak = 1;
25403 +               depctl.b.epena = 1;
25404 +               DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
25405 +
25406 +               /**
25407 +                * Enable the Non-Periodic Tx FIFO empty interrupt, the
25408 +                * data will be written into the fifo by the ISR.
25409 +                */
25410 +               if (!core_if->dma_enable) {
25411 +                       if (core_if->en_multiple_tx_fifo == 0) {
25412 +                               /* First clear it from GINTSTS */
25413 +                               intr_mask.b.nptxfempty = 1;
25414 +                               DWC_MODIFY_REG32(&core_if->
25415 +                                                core_global_regs->gintmsk,
25416 +                                                intr_mask.d32, intr_mask.d32);
25417 +
25418 +                       } else {
25419 +                               /* Enable the Tx FIFO Empty Interrupt for this EP */
25420 +                               if (ep->xfer_len > 0) {
25421 +                                       uint32_t fifoemptymsk = 0;
25422 +                                       fifoemptymsk |= 1 << ep->num;
25423 +                                       DWC_MODIFY_REG32(&core_if->
25424 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
25425 +                                                        0, fifoemptymsk);
25426 +                               }
25427 +                       }
25428 +               }
25429 +       } else {
25430 +               dwc_otg_dev_out_ep_regs_t *out_regs =
25431 +                   core_if->dev_if->out_ep_regs[0];
25432 +
25433 +               depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
25434 +               deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
25435 +
25436 +               /* Program the transfer size and packet count
25437 +                *      as follows: xfersize = N * maxpacket +
25438 +                *      short_packet pktcnt = N + (short_packet
25439 +                *      exist ? 1 : 0)
25440 +                */
25441 +               deptsiz.b.xfersize = ep->maxpacket;
25442 +               deptsiz.b.pktcnt = 1;
25443 +
25444 +               if (core_if->dma_desc_enable == 0) {
25445 +                       DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
25446 +               } else {
25447 +                       dma_desc = core_if->dev_if->out_desc_addr;
25448 +
25449 +                       /** DMA Descriptor Setup */
25450 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
25451 +                       dma_desc->status.b.l = 1;
25452 +                       dma_desc->status.b.ioc = 1;
25453 +                       dma_desc->status.b.bytes = ep->maxpacket;
25454 +                       dma_desc->buf = ep->dma_addr;
25455 +                       dma_desc->status.b.sts = 0;
25456 +                       dma_desc->status.b.bs = BS_HOST_READY;
25457 +
25458 +                       /** DOEPDMA0 Register write */
25459 +                       DWC_WRITE_REG32(&out_regs->doepdma,
25460 +                                       core_if->dev_if->dma_out_desc_addr);
25461 +               }
25462 +
25463 +               DWC_DEBUGPL(DBG_PCDV,
25464 +                           "IN len=%d  xfersize=%d pktcnt=%d [%08x]\n",
25465 +                           ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
25466 +                           deptsiz.d32);
25467 +
25468 +               /* Write the DMA register */
25469 +               if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
25470 +                       if (core_if->dma_desc_enable == 0)
25471 +                               DWC_WRITE_REG32(&(out_regs->doepdma),
25472 +                                               (uint32_t) ep->dma_addr);
25473 +
25474 +               }
25475 +
25476 +               /* EP enable, IN data in FIFO */
25477 +               depctl.b.cnak = 1;
25478 +               depctl.b.epena = 1;
25479 +               DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
25480 +
25481 +       }
25482 +}
25483 +
25484 +#ifdef DEBUG
25485 +void dump_msg(const u8 * buf, unsigned int length)
25486 +{
25487 +       unsigned int start, num, i;
25488 +       char line[52], *p;
25489 +
25490 +       if (length >= 512)
25491 +               return;
25492 +       start = 0;
25493 +       while (length > 0) {
25494 +               num = length < 16u ? length : 16u;
25495 +               p = line;
25496 +               for (i = 0; i < num; ++i) {
25497 +                       if (i == 8)
25498 +                               *p++ = ' ';
25499 +                       DWC_SPRINTF(p, " %02x", buf[i]);
25500 +                       p += 3;
25501 +               }
25502 +               *p = 0;
25503 +               DWC_PRINTF("%6x: %s\n", start, line);
25504 +               buf += num;
25505 +               start += num;
25506 +               length -= num;
25507 +       }
25508 +}
25509 +#else
25510 +static inline void dump_msg(const u8 * buf, unsigned int length)
25511 +{
25512 +}
25513 +#endif
25514 +
25515 +/**
25516 + * This function writes a packet into the Tx FIFO associated with the
25517 + * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For
25518 + * periodic EPs the periodic Tx FIFO associated with the EP is written
25519 + * with all packets for the next micro-frame.
25520 + *
25521 + * @param core_if Programming view of DWC_otg controller.
25522 + * @param ep The EP to write packet for.
25523 + * @param dma Indicates if DMA is being used.
25524 + */
25525 +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
25526 +                            int dma)
25527 +{
25528 +       /**
25529 +        * The buffer is padded to DWORD on a per packet basis in
25530 +        * slave/dma mode if the MPS is not DWORD aligned. The last
25531 +        * packet, if short, is also padded to a multiple of DWORD.
25532 +        *
25533 +        * ep->xfer_buff always starts DWORD aligned in memory and is a
25534 +        * multiple of DWORD in length
25535 +        *
25536 +        * ep->xfer_len can be any number of bytes
25537 +        *
25538 +        * ep->xfer_count is a multiple of ep->maxpacket until the last
25539 +        *      packet
25540 +        *
25541 +        * FIFO access is DWORD */
25542 +
25543 +       uint32_t i;
25544 +       uint32_t byte_count;
25545 +       uint32_t dword_count;
25546 +       uint32_t *fifo;
25547 +       uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
25548 +
25549 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
25550 +                   ep);
25551 +       if (ep->xfer_count >= ep->xfer_len) {
25552 +               DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
25553 +               return;
25554 +       }
25555 +
25556 +       /* Find the byte length of the packet either short packet or MPS */
25557 +       if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
25558 +               byte_count = ep->xfer_len - ep->xfer_count;
25559 +       } else {
25560 +               byte_count = ep->maxpacket;
25561 +       }
25562 +
25563 +       /* Find the DWORD length, padded by extra bytes as neccessary if MPS
25564 +        * is not a multiple of DWORD */
25565 +       dword_count = (byte_count + 3) / 4;
25566 +
25567 +#ifdef VERBOSE
25568 +       dump_msg(ep->xfer_buff, byte_count);
25569 +#endif
25570 +
25571 +       /**@todo NGS Where are the Periodic Tx FIFO addresses
25572 +        * intialized?  What should this be? */
25573 +
25574 +       fifo = core_if->data_fifo[ep->num];
25575 +
25576 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
25577 +                   fifo, data_buff, *data_buff, byte_count);
25578 +
25579 +       if (!dma) {
25580 +               for (i = 0; i < dword_count; i++, data_buff++) {
25581 +                       DWC_WRITE_REG32(fifo, *data_buff);
25582 +               }
25583 +       }
25584 +
25585 +       ep->xfer_count += byte_count;
25586 +       ep->xfer_buff += byte_count;
25587 +       ep->dma_addr += byte_count;
25588 +}
25589 +
25590 +/**
25591 + * Set the EP STALL.
25592 + *
25593 + * @param core_if Programming view of DWC_otg controller.
25594 + * @param ep The EP to set the stall on.
25595 + */
25596 +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25597 +{
25598 +       depctl_data_t depctl;
25599 +       volatile uint32_t *depctl_addr;
25600 +
25601 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25602 +                   (ep->is_in ? "IN" : "OUT"));
25603 +
25604 +       if (ep->is_in == 1) {
25605 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25606 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25607 +
25608 +               /* set the disable and stall bits */
25609 +               if (depctl.b.epena) {
25610 +                       depctl.b.epdis = 1;
25611 +               }
25612 +               depctl.b.stall = 1;
25613 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25614 +       } else {
25615 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25616 +               depctl.d32 = DWC_READ_REG32(depctl_addr);
25617 +
25618 +               /* set the stall bit */
25619 +               depctl.b.stall = 1;
25620 +               DWC_WRITE_REG32(depctl_addr, depctl.d32);
25621 +       }
25622 +
25623 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25624 +
25625 +       return;
25626 +}
25627 +
25628 +/**
25629 + * Clear the EP STALL.
25630 + *
25631 + * @param core_if Programming view of DWC_otg controller.
25632 + * @param ep The EP to clear stall from.
25633 + */
25634 +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
25635 +{
25636 +       depctl_data_t depctl;
25637 +       volatile uint32_t *depctl_addr;
25638 +
25639 +       DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
25640 +                   (ep->is_in ? "IN" : "OUT"));
25641 +
25642 +       if (ep->is_in == 1) {
25643 +               depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
25644 +       } else {
25645 +               depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
25646 +       }
25647 +
25648 +       depctl.d32 = DWC_READ_REG32(depctl_addr);
25649 +
25650 +       /* clear the stall bits */
25651 +       depctl.b.stall = 0;
25652 +
25653 +       /*
25654 +        * USB Spec 9.4.5: For endpoints using data toggle, regardless
25655 +        * of whether an endpoint has the Halt feature set, a
25656 +        * ClearFeature(ENDPOINT_HALT) request always results in the
25657 +        * data toggle being reinitialized to DATA0.
25658 +        */
25659 +       if (ep->type == DWC_OTG_EP_TYPE_INTR ||
25660 +           ep->type == DWC_OTG_EP_TYPE_BULK) {
25661 +               depctl.b.setd0pid = 1;  /* DATA0 */
25662 +       }
25663 +
25664 +       DWC_WRITE_REG32(depctl_addr, depctl.d32);
25665 +       DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
25666 +       return;
25667 +}
25668 +
25669 +/**
25670 + * This function reads a packet from the Rx FIFO into the destination
25671 + * buffer. To read SETUP data use dwc_otg_read_setup_packet.
25672 + *
25673 + * @param core_if Programming view of DWC_otg controller.
25674 + * @param dest   Destination buffer for the packet.
25675 + * @param bytes  Number of bytes to copy to the destination.
25676 + */
25677 +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
25678 +                        uint8_t * dest, uint16_t bytes)
25679 +{
25680 +       int i;
25681 +       int word_count = (bytes + 3) / 4;
25682 +
25683 +       volatile uint32_t *fifo = core_if->data_fifo[0];
25684 +       uint32_t *data_buff = (uint32_t *) dest;
25685 +
25686 +       /**
25687 +        * @todo Account for the case where _dest is not dword aligned. This
25688 +        * requires reading data from the FIFO into a uint32_t temp buffer,
25689 +        * then moving it into the data buffer.
25690 +        */
25691 +
25692 +       DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
25693 +                   core_if, dest, bytes);
25694 +
25695 +       for (i = 0; i < word_count; i++, data_buff++) {
25696 +               *data_buff = DWC_READ_REG32(fifo);
25697 +       }
25698 +
25699 +       return;
25700 +}
25701 +
25702 +/**
25703 + * This functions reads the device registers and prints them
25704 + *
25705 + * @param core_if Programming view of DWC_otg controller.
25706 + */
25707 +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
25708 +{
25709 +       int i;
25710 +       volatile uint32_t *addr;
25711 +
25712 +       DWC_PRINTF("Device Global Registers\n");
25713 +       addr = &core_if->dev_if->dev_global_regs->dcfg;
25714 +       DWC_PRINTF("DCFG                 @0x%08lX : 0x%08X\n",
25715 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25716 +       addr = &core_if->dev_if->dev_global_regs->dctl;
25717 +       DWC_PRINTF("DCTL                 @0x%08lX : 0x%08X\n",
25718 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25719 +       addr = &core_if->dev_if->dev_global_regs->dsts;
25720 +       DWC_PRINTF("DSTS                 @0x%08lX : 0x%08X\n",
25721 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25722 +       addr = &core_if->dev_if->dev_global_regs->diepmsk;
25723 +       DWC_PRINTF("DIEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25724 +                  DWC_READ_REG32(addr));
25725 +       addr = &core_if->dev_if->dev_global_regs->doepmsk;
25726 +       DWC_PRINTF("DOEPMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25727 +                  DWC_READ_REG32(addr));
25728 +       addr = &core_if->dev_if->dev_global_regs->daint;
25729 +       DWC_PRINTF("DAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25730 +                  DWC_READ_REG32(addr));
25731 +       addr = &core_if->dev_if->dev_global_regs->daintmsk;
25732 +       DWC_PRINTF("DAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25733 +                  DWC_READ_REG32(addr));
25734 +       addr = &core_if->dev_if->dev_global_regs->dtknqr1;
25735 +       DWC_PRINTF("DTKNQR1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25736 +                  DWC_READ_REG32(addr));
25737 +       if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
25738 +               addr = &core_if->dev_if->dev_global_regs->dtknqr2;
25739 +               DWC_PRINTF("DTKNQR2      @0x%08lX : 0x%08X\n",
25740 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25741 +       }
25742 +
25743 +       addr = &core_if->dev_if->dev_global_regs->dvbusdis;
25744 +       DWC_PRINTF("DVBUSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25745 +                  DWC_READ_REG32(addr));
25746 +
25747 +       addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
25748 +       DWC_PRINTF("DVBUSPULSE  @0x%08lX : 0x%08X\n",
25749 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25750 +
25751 +       addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
25752 +       DWC_PRINTF("DTKNQR3_DTHRCTL      @0x%08lX : 0x%08X\n",
25753 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25754 +
25755 +       if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
25756 +               addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25757 +               DWC_PRINTF("DTKNQR4      @0x%08lX : 0x%08X\n",
25758 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25759 +       }
25760 +
25761 +       addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
25762 +       DWC_PRINTF("FIFOEMPMSK   @0x%08lX : 0x%08X\n", (unsigned long)addr,
25763 +                  DWC_READ_REG32(addr));
25764 +
25765 +       if (core_if->hwcfg2.b.multi_proc_int) {
25766 +
25767 +               addr = &core_if->dev_if->dev_global_regs->deachint;
25768 +               DWC_PRINTF("DEACHINT     @0x%08lX : 0x%08X\n",
25769 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25770 +               addr = &core_if->dev_if->dev_global_regs->deachintmsk;
25771 +               DWC_PRINTF("DEACHINTMSK  @0x%08lX : 0x%08X\n",
25772 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25773 +
25774 +               for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25775 +                       addr =
25776 +                           &core_if->dev_if->
25777 +                           dev_global_regs->diepeachintmsk[i];
25778 +                       DWC_PRINTF("DIEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25779 +                                  i, (unsigned long)addr,
25780 +                                  DWC_READ_REG32(addr));
25781 +               }
25782 +
25783 +               for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25784 +                       addr =
25785 +                           &core_if->dev_if->
25786 +                           dev_global_regs->doepeachintmsk[i];
25787 +                       DWC_PRINTF("DOEPEACHINTMSK[%d]   @0x%08lX : 0x%08X\n",
25788 +                                  i, (unsigned long)addr,
25789 +                                  DWC_READ_REG32(addr));
25790 +               }
25791 +       }
25792 +
25793 +       for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
25794 +               DWC_PRINTF("Device IN EP %d Registers\n", i);
25795 +               addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
25796 +               DWC_PRINTF("DIEPCTL      @0x%08lX : 0x%08X\n",
25797 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25798 +               addr = &core_if->dev_if->in_ep_regs[i]->diepint;
25799 +               DWC_PRINTF("DIEPINT      @0x%08lX : 0x%08X\n",
25800 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25801 +               addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
25802 +               DWC_PRINTF("DIETSIZ      @0x%08lX : 0x%08X\n",
25803 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25804 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
25805 +               DWC_PRINTF("DIEPDMA      @0x%08lX : 0x%08X\n",
25806 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25807 +               addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
25808 +               DWC_PRINTF("DTXFSTS      @0x%08lX : 0x%08X\n",
25809 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25810 +               addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
25811 +               DWC_PRINTF("DIEPDMAB     @0x%08lX : 0x%08X\n",
25812 +                          (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );
25813 +       }
25814 +
25815 +       for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
25816 +               DWC_PRINTF("Device OUT EP %d Registers\n", i);
25817 +               addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
25818 +               DWC_PRINTF("DOEPCTL      @0x%08lX : 0x%08X\n",
25819 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25820 +               addr = &core_if->dev_if->out_ep_regs[i]->doepint;
25821 +               DWC_PRINTF("DOEPINT      @0x%08lX : 0x%08X\n",
25822 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25823 +               addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
25824 +               DWC_PRINTF("DOETSIZ      @0x%08lX : 0x%08X\n",
25825 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25826 +               addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
25827 +               DWC_PRINTF("DOEPDMA      @0x%08lX : 0x%08X\n",
25828 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25829 +               if (core_if->dma_enable) {      /* Don't access this register in SLAVE mode */
25830 +                       addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
25831 +                       DWC_PRINTF("DOEPDMAB     @0x%08lX : 0x%08X\n",
25832 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
25833 +               }
25834 +
25835 +       }
25836 +}
25837 +
25838 +/**
25839 + * This functions reads the SPRAM and prints its content
25840 + *
25841 + * @param core_if Programming view of DWC_otg controller.
25842 + */
25843 +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
25844 +{
25845 +       volatile uint8_t *addr, *start_addr, *end_addr;
25846 +
25847 +       DWC_PRINTF("SPRAM Data:\n");
25848 +       start_addr = (void *)core_if->core_global_regs;
25849 +       DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);
25850 +       start_addr += 0x00028000;
25851 +       end_addr = (void *)core_if->core_global_regs;
25852 +       end_addr += 0x000280e0;
25853 +
25854 +       for (addr = start_addr; addr < end_addr; addr += 16) {
25855 +               DWC_PRINTF
25856 +                   ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
25857 +                    (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],
25858 +                    addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
25859 +                    addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
25860 +                   );
25861 +       }
25862 +
25863 +       return;
25864 +}
25865 +
25866 +/**
25867 + * This function reads the host registers and prints them
25868 + *
25869 + * @param core_if Programming view of DWC_otg controller.
25870 + */
25871 +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
25872 +{
25873 +       int i;
25874 +       volatile uint32_t *addr;
25875 +
25876 +       DWC_PRINTF("Host Global Registers\n");
25877 +       addr = &core_if->host_if->host_global_regs->hcfg;
25878 +       DWC_PRINTF("HCFG                 @0x%08lX : 0x%08X\n",
25879 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25880 +       addr = &core_if->host_if->host_global_regs->hfir;
25881 +       DWC_PRINTF("HFIR                 @0x%08lX : 0x%08X\n",
25882 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25883 +       addr = &core_if->host_if->host_global_regs->hfnum;
25884 +       DWC_PRINTF("HFNUM        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25885 +                  DWC_READ_REG32(addr));
25886 +       addr = &core_if->host_if->host_global_regs->hptxsts;
25887 +       DWC_PRINTF("HPTXSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25888 +                  DWC_READ_REG32(addr));
25889 +       addr = &core_if->host_if->host_global_regs->haint;
25890 +       DWC_PRINTF("HAINT        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25891 +                  DWC_READ_REG32(addr));
25892 +       addr = &core_if->host_if->host_global_regs->haintmsk;
25893 +       DWC_PRINTF("HAINTMSK     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25894 +                  DWC_READ_REG32(addr));
25895 +       if (core_if->dma_desc_enable) {
25896 +               addr = &core_if->host_if->host_global_regs->hflbaddr;
25897 +               DWC_PRINTF("HFLBADDR     @0x%08lX : 0x%08X\n",
25898 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25899 +       }
25900 +
25901 +       addr = core_if->host_if->hprt0;
25902 +       DWC_PRINTF("HPRT0        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25903 +                  DWC_READ_REG32(addr));
25904 +
25905 +       for (i = 0; i < core_if->core_params->host_channels; i++) {
25906 +               DWC_PRINTF("Host Channel %d Specific Registers\n", i);
25907 +               addr = &core_if->host_if->hc_regs[i]->hcchar;
25908 +               DWC_PRINTF("HCCHAR       @0x%08lX : 0x%08X\n",
25909 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25910 +               addr = &core_if->host_if->hc_regs[i]->hcsplt;
25911 +               DWC_PRINTF("HCSPLT       @0x%08lX : 0x%08X\n",
25912 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25913 +               addr = &core_if->host_if->hc_regs[i]->hcint;
25914 +               DWC_PRINTF("HCINT        @0x%08lX : 0x%08X\n",
25915 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25916 +               addr = &core_if->host_if->hc_regs[i]->hcintmsk;
25917 +               DWC_PRINTF("HCINTMSK     @0x%08lX : 0x%08X\n",
25918 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25919 +               addr = &core_if->host_if->hc_regs[i]->hctsiz;
25920 +               DWC_PRINTF("HCTSIZ       @0x%08lX : 0x%08X\n",
25921 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25922 +               addr = &core_if->host_if->hc_regs[i]->hcdma;
25923 +               DWC_PRINTF("HCDMA        @0x%08lX : 0x%08X\n",
25924 +                          (unsigned long)addr, DWC_READ_REG32(addr));
25925 +               if (core_if->dma_desc_enable) {
25926 +                       addr = &core_if->host_if->hc_regs[i]->hcdmab;
25927 +                       DWC_PRINTF("HCDMAB       @0x%08lX : 0x%08X\n",
25928 +                                  (unsigned long)addr, DWC_READ_REG32(addr));
25929 +               }
25930 +
25931 +       }
25932 +       return;
25933 +}
25934 +
25935 +/**
25936 + * This function reads the core global registers and prints them
25937 + *
25938 + * @param core_if Programming view of DWC_otg controller.
25939 + */
25940 +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
25941 +{
25942 +       int i, ep_num;
25943 +       volatile uint32_t *addr;
25944 +       char *txfsiz;
25945 +
25946 +       DWC_PRINTF("Core Global Registers\n");
25947 +       addr = &core_if->core_global_regs->gotgctl;
25948 +       DWC_PRINTF("GOTGCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25949 +                  DWC_READ_REG32(addr));
25950 +       addr = &core_if->core_global_regs->gotgint;
25951 +       DWC_PRINTF("GOTGINT      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25952 +                  DWC_READ_REG32(addr));
25953 +       addr = &core_if->core_global_regs->gahbcfg;
25954 +       DWC_PRINTF("GAHBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25955 +                  DWC_READ_REG32(addr));
25956 +       addr = &core_if->core_global_regs->gusbcfg;
25957 +       DWC_PRINTF("GUSBCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25958 +                  DWC_READ_REG32(addr));
25959 +       addr = &core_if->core_global_regs->grstctl;
25960 +       DWC_PRINTF("GRSTCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25961 +                  DWC_READ_REG32(addr));
25962 +       addr = &core_if->core_global_regs->gintsts;
25963 +       DWC_PRINTF("GINTSTS      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25964 +                  DWC_READ_REG32(addr));
25965 +       addr = &core_if->core_global_regs->gintmsk;
25966 +       DWC_PRINTF("GINTMSK      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25967 +                  DWC_READ_REG32(addr));
25968 +       addr = &core_if->core_global_regs->grxstsr;
25969 +       DWC_PRINTF("GRXSTSR      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25970 +                  DWC_READ_REG32(addr));
25971 +       addr = &core_if->core_global_regs->grxfsiz;
25972 +       DWC_PRINTF("GRXFSIZ      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25973 +                  DWC_READ_REG32(addr));
25974 +       addr = &core_if->core_global_regs->gnptxfsiz;
25975 +       DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
25976 +                  DWC_READ_REG32(addr));
25977 +       addr = &core_if->core_global_regs->gnptxsts;
25978 +       DWC_PRINTF("GNPTXSTS     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25979 +                  DWC_READ_REG32(addr));
25980 +       addr = &core_if->core_global_regs->gi2cctl;
25981 +       DWC_PRINTF("GI2CCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25982 +                  DWC_READ_REG32(addr));
25983 +       addr = &core_if->core_global_regs->gpvndctl;
25984 +       DWC_PRINTF("GPVNDCTL     @0x%08lX : 0x%08X\n", (unsigned long)addr,
25985 +                  DWC_READ_REG32(addr));
25986 +       addr = &core_if->core_global_regs->ggpio;
25987 +       DWC_PRINTF("GGPIO        @0x%08lX : 0x%08X\n", (unsigned long)addr,
25988 +                  DWC_READ_REG32(addr));
25989 +       addr = &core_if->core_global_regs->guid;
25990 +       DWC_PRINTF("GUID                 @0x%08lX : 0x%08X\n",
25991 +                  (unsigned long)addr, DWC_READ_REG32(addr));
25992 +       addr = &core_if->core_global_regs->gsnpsid;
25993 +       DWC_PRINTF("GSNPSID      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25994 +                  DWC_READ_REG32(addr));
25995 +       addr = &core_if->core_global_regs->ghwcfg1;
25996 +       DWC_PRINTF("GHWCFG1      @0x%08lX : 0x%08X\n", (unsigned long)addr,
25997 +                  DWC_READ_REG32(addr));
25998 +       addr = &core_if->core_global_regs->ghwcfg2;
25999 +       DWC_PRINTF("GHWCFG2      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26000 +                  DWC_READ_REG32(addr));
26001 +       addr = &core_if->core_global_regs->ghwcfg3;
26002 +       DWC_PRINTF("GHWCFG3      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26003 +                  DWC_READ_REG32(addr));
26004 +       addr = &core_if->core_global_regs->ghwcfg4;
26005 +       DWC_PRINTF("GHWCFG4      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26006 +                  DWC_READ_REG32(addr));
26007 +       addr = &core_if->core_global_regs->glpmcfg;
26008 +       DWC_PRINTF("GLPMCFG      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26009 +                  DWC_READ_REG32(addr));
26010 +       addr = &core_if->core_global_regs->gpwrdn;
26011 +       DWC_PRINTF("GPWRDN       @0x%08lX : 0x%08X\n", (unsigned long)addr,
26012 +                  DWC_READ_REG32(addr));
26013 +       addr = &core_if->core_global_regs->gdfifocfg;
26014 +       DWC_PRINTF("GDFIFOCFG    @0x%08lX : 0x%08X\n", (unsigned long)addr,
26015 +                  DWC_READ_REG32(addr));
26016 +       addr = &core_if->core_global_regs->adpctl;
26017 +       DWC_PRINTF("ADPCTL       @0x%08lX : 0x%08X\n", (unsigned long)addr,
26018 +                  dwc_otg_adp_read_reg(core_if));
26019 +       addr = &core_if->core_global_regs->hptxfsiz;
26020 +       DWC_PRINTF("HPTXFSIZ     @0x%08lX : 0x%08X\n", (unsigned long)addr,
26021 +                  DWC_READ_REG32(addr));
26022 +
26023 +       if (core_if->en_multiple_tx_fifo == 0) {
26024 +               ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;
26025 +               txfsiz = "DPTXFSIZ";
26026 +       } else {
26027 +               ep_num = core_if->hwcfg4.b.num_in_eps;
26028 +               txfsiz = "DIENPTXF";
26029 +       }
26030 +       for (i = 0; i < ep_num; i++) {
26031 +               addr = &core_if->core_global_regs->dtxfsiz[i];
26032 +               DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
26033 +                          (unsigned long)addr, DWC_READ_REG32(addr));
26034 +       }
26035 +       addr = core_if->pcgcctl;
26036 +       DWC_PRINTF("PCGCCTL      @0x%08lX : 0x%08X\n", (unsigned long)addr,
26037 +                  DWC_READ_REG32(addr));
26038 +}
26039 +
26040 +/**
26041 + * Flush a Tx FIFO.
26042 + *
26043 + * @param core_if Programming view of DWC_otg controller.
26044 + * @param num Tx FIFO to flush.
26045 + */
26046 +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
26047 +{
26048 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26049 +       volatile grstctl_t greset = {.d32 = 0 };
26050 +       int count = 0;
26051 +
26052 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
26053 +
26054 +       greset.b.txfflsh = 1;
26055 +       greset.b.txfnum = num;
26056 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26057 +
26058 +       do {
26059 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26060 +               if (++count > 10000) {
26061 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
26062 +                                __func__, greset.d32,
26063 +                                DWC_READ_REG32(&global_regs->gnptxsts));
26064 +                       break;
26065 +               }
26066 +               dwc_udelay(1);
26067 +       } while (greset.b.txfflsh == 1);
26068 +
26069 +       /* Wait for 3 PHY Clocks */
26070 +       dwc_udelay(1);
26071 +}
26072 +
26073 +/**
26074 + * Flush Rx FIFO.
26075 + *
26076 + * @param core_if Programming view of DWC_otg controller.
26077 + */
26078 +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
26079 +{
26080 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26081 +       volatile grstctl_t greset = {.d32 = 0 };
26082 +       int count = 0;
26083 +
26084 +       DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
26085 +       /*
26086 +        *
26087 +        */
26088 +       greset.b.rxfflsh = 1;
26089 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26090 +
26091 +       do {
26092 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26093 +               if (++count > 10000) {
26094 +                       DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
26095 +                                greset.d32);
26096 +                       break;
26097 +               }
26098 +               dwc_udelay(1);
26099 +       } while (greset.b.rxfflsh == 1);
26100 +
26101 +       /* Wait for 3 PHY Clocks */
26102 +       dwc_udelay(1);
26103 +}
26104 +
26105 +/**
26106 + * Do core a soft reset of the core.  Be careful with this because it
26107 + * resets all the internal state machines of the core.
26108 + */
26109 +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
26110 +{
26111 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
26112 +       volatile grstctl_t greset = {.d32 = 0 };
26113 +       int count = 0;
26114 +
26115 +       DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
26116 +       /* Wait for AHB master IDLE state. */
26117 +       do {
26118 +               dwc_udelay(10);
26119 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26120 +               if (++count > 100000) {
26121 +                       DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
26122 +                                greset.d32);
26123 +                       return;
26124 +               }
26125 +       }
26126 +       while (greset.b.ahbidle == 0);
26127 +
26128 +       /* Core Soft Reset */
26129 +       count = 0;
26130 +       greset.b.csftrst = 1;
26131 +       DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
26132 +       do {
26133 +               greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
26134 +               if (++count > 10000) {
26135 +                       DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
26136 +                                __func__, greset.d32);
26137 +                       break;
26138 +               }
26139 +               dwc_udelay(1);
26140 +       }
26141 +       while (greset.b.csftrst == 1);
26142 +
26143 +       /* Wait for 3 PHY Clocks */
26144 +       dwc_mdelay(100);
26145 +}
26146 +
26147 +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
26148 +{
26149 +       return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
26150 +}
26151 +
26152 +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
26153 +{
26154 +       return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
26155 +}
26156 +
26157 +/**
26158 + * Register HCD callbacks. The callbacks are used to start and stop
26159 + * the HCD for interrupt processing.
26160 + *
26161 + * @param core_if Programming view of DWC_otg controller.
26162 + * @param cb the HCD callback structure.
26163 + * @param p pointer to be passed to callback function (usb_hcd*).
26164 + */
26165 +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
26166 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26167 +{
26168 +       core_if->hcd_cb = cb;
26169 +       cb->p = p;
26170 +}
26171 +
26172 +/**
26173 + * Register PCD callbacks. The callbacks are used to start and stop
26174 + * the PCD for interrupt processing.
26175 + *
26176 + * @param core_if Programming view of DWC_otg controller.
26177 + * @param cb the PCD callback structure.
26178 + * @param p pointer to be passed to callback function (pcd*).
26179 + */
26180 +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
26181 +                                       dwc_otg_cil_callbacks_t * cb, void *p)
26182 +{
26183 +       core_if->pcd_cb = cb;
26184 +       cb->p = p;
26185 +}
26186 +
26187 +#ifdef DWC_EN_ISOC
26188 +
26189 +/**
26190 + * This function writes isoc data per 1 (micro)frame into tx fifo
26191 + *
26192 + * @param core_if Programming view of DWC_otg controller.
26193 + * @param ep The EP to start the transfer on.
26194 + *
26195 + */
26196 +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
26197 +{
26198 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
26199 +       dtxfsts_data_t txstatus = {.d32 = 0 };
26200 +       uint32_t len = 0;
26201 +       uint32_t dwords;
26202 +
26203 +       ep->xfer_len = ep->data_per_frame;
26204 +       ep->xfer_count = 0;
26205 +
26206 +       ep_regs = core_if->dev_if->in_ep_regs[ep->num];
26207 +
26208 +       len = ep->xfer_len - ep->xfer_count;
26209 +
26210 +       if (len > ep->maxpacket) {
26211 +               len = ep->maxpacket;
26212 +       }
26213 +
26214 +       dwords = (len + 3) / 4;
26215 +
26216 +       /* While there is space in the queue and space in the FIFO and
26217 +        * More data to tranfer, Write packets to the Tx FIFO */
26218 +       txstatus.d32 =
26219 +           DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
26220 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
26221 +
26222 +       while (txstatus.b.txfspcavail > dwords &&
26223 +              ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
26224 +               /* Write the FIFO */
26225 +               dwc_otg_ep_write_packet(core_if, ep, 0);
26226 +
26227 +               len = ep->xfer_len - ep->xfer_count;
26228 +               if (len > ep->maxpacket) {
26229 +                       len = ep->maxpacket;
26230 +               }
26231 +
26232 +               dwords = (len + 3) / 4;
26233 +               txstatus.d32 =
26234 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
26235 +                                  dtxfsts);
26236 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
26237 +                           txstatus.d32);
26238 +       }
26239 +}
26240 +
26241 +/**
26242 + * This function initializes a descriptor chain for Isochronous transfer
26243 + *
26244 + * @param core_if Programming view of DWC_otg controller.
26245 + * @param ep The EP to start the transfer on.
26246 + *
26247 + */
26248 +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
26249 +                                      dwc_ep_t * ep)
26250 +{
26251 +       deptsiz_data_t deptsiz = {.d32 = 0 };
26252 +       depctl_data_t depctl = {.d32 = 0 };
26253 +       dsts_data_t dsts = {.d32 = 0 };
26254 +       volatile uint32_t *addr;
26255 +
26256 +       if (ep->is_in) {
26257 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
26258 +       } else {
26259 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
26260 +       }
26261 +
26262 +       ep->xfer_len = ep->data_per_frame;
26263 +       ep->xfer_count = 0;
26264 +       ep->xfer_buff = ep->cur_pkt_addr;
26265 +       ep->dma_addr = ep->cur_pkt_dma_addr;
26266 +
26267 +       if (ep->is_in) {
26268 +               /* Program the transfer size and packet count
26269 +                *      as follows: xfersize = N * maxpacket +
26270 +                *      short_packet pktcnt = N + (short_packet
26271 +                *      exist ? 1 : 0)
26272 +                */
26273 +               deptsiz.b.xfersize = ep->xfer_len;
26274 +               deptsiz.b.pktcnt =
26275 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
26276 +               deptsiz.b.mc = deptsiz.b.pktcnt;
26277 +               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
26278 +                               deptsiz.d32);
26279 +
26280 +               /* Write the DMA register */
26281 +               if (core_if->dma_enable) {
26282 +                       DWC_WRITE_REG32(&
26283 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
26284 +                                        diepdma), (uint32_t) ep->dma_addr);
26285 +               }
26286 +       } else {
26287 +               deptsiz.b.pktcnt =
26288 +                   (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
26289 +               deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
26290 +
26291 +               DWC_WRITE_REG32(&core_if->dev_if->
26292 +                               out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);
26293 +
26294 +               if (core_if->dma_enable) {
26295 +                       DWC_WRITE_REG32(&
26296 +                                       (core_if->dev_if->
26297 +                                        out_ep_regs[ep->num]->doepdma),
26298 +                                       (uint32_t) ep->dma_addr);
26299 +               }
26300 +       }
26301 +
26302 +       /** Enable endpoint, clear nak  */
26303 +
26304 +       depctl.d32 = 0;
26305 +       if (ep->bInterval == 1) {
26306 +               dsts.d32 =
26307 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
26308 +               ep->next_frame = dsts.b.soffn + ep->bInterval;
26309 +
26310 +               if (ep->next_frame & 0x1) {
26311 +                       depctl.b.setd1pid = 1;
26312 +               } else {
26313 +                       depctl.b.setd0pid = 1;
26314 +               }
26315 +       } else {
26316 +               ep->next_frame += ep->bInterval;
26317 +
26318 +               if (ep->next_frame & 0x1) {
26319 +                       depctl.b.setd1pid = 1;
26320 +               } else {
26321 +                       depctl.b.setd0pid = 1;
26322 +               }
26323 +       }
26324 +       depctl.b.epena = 1;
26325 +       depctl.b.cnak = 1;
26326 +
26327 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
26328 +       depctl.d32 = DWC_READ_REG32(addr);
26329 +
26330 +       if (ep->is_in && core_if->dma_enable == 0) {
26331 +               write_isoc_frame_data(core_if, ep);
26332 +       }
26333 +
26334 +}
26335 +#endif /* DWC_EN_ISOC */
26336 +
26337 +static void dwc_otg_set_uninitialized(int32_t * p, int size)
26338 +{
26339 +       int i;
26340 +       for (i = 0; i < size; i++) {
26341 +               p[i] = -1;
26342 +       }
26343 +}
26344 +
26345 +static int dwc_otg_param_initialized(int32_t val)
26346 +{
26347 +       return val != -1;
26348 +}
26349 +
26350 +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
26351 +{
26352 +       int i;
26353 +       core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
26354 +       if (!core_if->core_params) {
26355 +               return -DWC_E_NO_MEMORY;
26356 +       }
26357 +       dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
26358 +                                 sizeof(*core_if->core_params) /
26359 +                                 sizeof(int32_t));
26360 +       DWC_PRINTF("Setting default values for core params\n");
26361 +       dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
26362 +       dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
26363 +       dwc_otg_set_param_dma_desc_enable(core_if,
26364 +                                         dwc_param_dma_desc_enable_default);
26365 +       dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
26366 +       dwc_otg_set_param_dma_burst_size(core_if,
26367 +                                        dwc_param_dma_burst_size_default);
26368 +       dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
26369 +                                                      dwc_param_host_support_fs_ls_low_power_default);
26370 +       dwc_otg_set_param_enable_dynamic_fifo(core_if,
26371 +                                             dwc_param_enable_dynamic_fifo_default);
26372 +       dwc_otg_set_param_data_fifo_size(core_if,
26373 +                                        dwc_param_data_fifo_size_default);
26374 +       dwc_otg_set_param_dev_rx_fifo_size(core_if,
26375 +                                          dwc_param_dev_rx_fifo_size_default);
26376 +       dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
26377 +                                                 dwc_param_dev_nperio_tx_fifo_size_default);
26378 +       dwc_otg_set_param_host_rx_fifo_size(core_if,
26379 +                                           dwc_param_host_rx_fifo_size_default);
26380 +       dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
26381 +                                                  dwc_param_host_nperio_tx_fifo_size_default);
26382 +       dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
26383 +                                                 dwc_param_host_perio_tx_fifo_size_default);
26384 +       dwc_otg_set_param_max_transfer_size(core_if,
26385 +                                           dwc_param_max_transfer_size_default);
26386 +       dwc_otg_set_param_max_packet_count(core_if,
26387 +                                          dwc_param_max_packet_count_default);
26388 +       dwc_otg_set_param_host_channels(core_if,
26389 +                                       dwc_param_host_channels_default);
26390 +       dwc_otg_set_param_dev_endpoints(core_if,
26391 +                                       dwc_param_dev_endpoints_default);
26392 +       dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
26393 +       dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
26394 +       dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
26395 +                                                   dwc_param_host_ls_low_power_phy_clk_default);
26396 +       dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
26397 +       dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
26398 +                                           dwc_param_phy_ulpi_ext_vbus_default);
26399 +       dwc_otg_set_param_phy_utmi_width(core_if,
26400 +                                        dwc_param_phy_utmi_width_default);
26401 +       dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
26402 +       dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
26403 +       dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
26404 +       dwc_otg_set_param_en_multiple_tx_fifo(core_if,
26405 +                                             dwc_param_en_multiple_tx_fifo_default);
26406 +       for (i = 0; i < 15; i++) {
26407 +               dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
26408 +                                                        dwc_param_dev_perio_tx_fifo_size_default,
26409 +                                                        i);
26410 +       }
26411 +
26412 +       for (i = 0; i < 15; i++) {
26413 +               dwc_otg_set_param_dev_tx_fifo_size(core_if,
26414 +                                                  dwc_param_dev_tx_fifo_size_default,
26415 +                                                  i);
26416 +       }
26417 +       dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
26418 +       dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
26419 +       dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
26420 +       dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
26421 +       dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
26422 +       dwc_otg_set_param_tx_thr_length(core_if,
26423 +                                       dwc_param_tx_thr_length_default);
26424 +       dwc_otg_set_param_rx_thr_length(core_if,
26425 +                                       dwc_param_rx_thr_length_default);
26426 +       dwc_otg_set_param_ahb_thr_ratio(core_if,
26427 +                                       dwc_param_ahb_thr_ratio_default);
26428 +       dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
26429 +       dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
26430 +       dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
26431 +       dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
26432 +       dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
26433 +       dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
26434 +       dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
26435 +       DWC_PRINTF("Finished setting default values for core params\n");
26436 +
26437 +       return 0;
26438 +}
26439 +
26440 +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
26441 +{
26442 +       return core_if->dma_enable;
26443 +}
26444 +
26445 +/* Checks if the parameter is outside of its valid range of values */
26446 +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
26447 +               (((_param_) < (_low_)) || \
26448 +               ((_param_) > (_high_)))
26449 +
26450 +/* Parameter access functions */
26451 +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
26452 +{
26453 +       int valid;
26454 +       int retval = 0;
26455 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26456 +               DWC_WARN("Wrong value for otg_cap parameter\n");
26457 +               DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
26458 +               retval = -DWC_E_INVALID;
26459 +               goto out;
26460 +       }
26461 +
26462 +       valid = 1;
26463 +       switch (val) {
26464 +       case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
26465 +               if (core_if->hwcfg2.b.op_mode !=
26466 +                   DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26467 +                       valid = 0;
26468 +               break;
26469 +       case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
26470 +               if ((core_if->hwcfg2.b.op_mode !=
26471 +                    DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26472 +                   && (core_if->hwcfg2.b.op_mode !=
26473 +                       DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26474 +                   && (core_if->hwcfg2.b.op_mode !=
26475 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26476 +                   && (core_if->hwcfg2.b.op_mode !=
26477 +                       DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
26478 +                       valid = 0;
26479 +               }
26480 +               break;
26481 +       case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
26482 +               /* always valid */
26483 +               break;
26484 +       }
26485 +       if (!valid) {
26486 +               if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
26487 +                       DWC_ERROR
26488 +                           ("%d invalid for otg_cap paremter. Check HW configuration.\n",
26489 +                            val);
26490 +               }
26491 +               val =
26492 +                   (((core_if->hwcfg2.b.op_mode ==
26493 +                      DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
26494 +                     || (core_if->hwcfg2.b.op_mode ==
26495 +                         DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
26496 +                     || (core_if->hwcfg2.b.op_mode ==
26497 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
26498 +                     || (core_if->hwcfg2.b.op_mode ==
26499 +                         DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
26500 +                    DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
26501 +                    DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
26502 +               retval = -DWC_E_INVALID;
26503 +       }
26504 +
26505 +       core_if->core_params->otg_cap = val;
26506 +out:
26507 +       return retval;
26508 +}
26509 +
26510 +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
26511 +{
26512 +       return core_if->core_params->otg_cap;
26513 +}
26514 +
26515 +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
26516 +{
26517 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26518 +               DWC_WARN("Wrong value for opt parameter\n");
26519 +               return -DWC_E_INVALID;
26520 +       }
26521 +       core_if->core_params->opt = val;
26522 +       return 0;
26523 +}
26524 +
26525 +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
26526 +{
26527 +       return core_if->core_params->opt;
26528 +}
26529 +
26530 +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
26531 +{
26532 +       int retval = 0;
26533 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26534 +               DWC_WARN("Wrong value for dma enable\n");
26535 +               return -DWC_E_INVALID;
26536 +       }
26537 +
26538 +       if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
26539 +               if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
26540 +                       DWC_ERROR
26541 +                           ("%d invalid for dma_enable paremter. Check HW configuration.\n",
26542 +                            val);
26543 +               }
26544 +               val = 0;
26545 +               retval = -DWC_E_INVALID;
26546 +       }
26547 +
26548 +       core_if->core_params->dma_enable = val;
26549 +       if (val == 0) {
26550 +               dwc_otg_set_param_dma_desc_enable(core_if, 0);
26551 +       }
26552 +       return retval;
26553 +}
26554 +
26555 +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
26556 +{
26557 +       return core_if->core_params->dma_enable;
26558 +}
26559 +
26560 +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
26561 +{
26562 +       int retval = 0;
26563 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26564 +               DWC_WARN("Wrong value for dma_enable\n");
26565 +               DWC_WARN("dma_desc_enable must be 0 or 1\n");
26566 +               return -DWC_E_INVALID;
26567 +       }
26568 +
26569 +       if ((val == 1)
26570 +           && ((dwc_otg_get_param_dma_enable(core_if) == 0)
26571 +               || (core_if->hwcfg4.b.desc_dma == 0))) {
26572 +               if (dwc_otg_param_initialized
26573 +                   (core_if->core_params->dma_desc_enable)) {
26574 +                       DWC_ERROR
26575 +                           ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
26576 +                            val);
26577 +               }
26578 +               val = 0;
26579 +               retval = -DWC_E_INVALID;
26580 +       }
26581 +       core_if->core_params->dma_desc_enable = val;
26582 +       return retval;
26583 +}
26584 +
26585 +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
26586 +{
26587 +       return core_if->core_params->dma_desc_enable;
26588 +}
26589 +
26590 +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
26591 +                                                  int32_t val)
26592 +{
26593 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26594 +               DWC_WARN("Wrong value for host_support_fs_low_power\n");
26595 +               DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
26596 +               return -DWC_E_INVALID;
26597 +       }
26598 +       core_if->core_params->host_support_fs_ls_low_power = val;
26599 +       return 0;
26600 +}
26601 +
26602 +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
26603 +                                                      core_if)
26604 +{
26605 +       return core_if->core_params->host_support_fs_ls_low_power;
26606 +}
26607 +
26608 +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
26609 +                                         int32_t val)
26610 +{
26611 +       int retval = 0;
26612 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26613 +               DWC_WARN("Wrong value for enable_dynamic_fifo\n");
26614 +               DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
26615 +               return -DWC_E_INVALID;
26616 +       }
26617 +
26618 +       if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
26619 +               if (dwc_otg_param_initialized
26620 +                   (core_if->core_params->enable_dynamic_fifo)) {
26621 +                       DWC_ERROR
26622 +                           ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
26623 +                            val);
26624 +               }
26625 +               val = 0;
26626 +               retval = -DWC_E_INVALID;
26627 +       }
26628 +       core_if->core_params->enable_dynamic_fifo = val;
26629 +       return retval;
26630 +}
26631 +
26632 +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
26633 +{
26634 +       return core_if->core_params->enable_dynamic_fifo;
26635 +}
26636 +
26637 +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26638 +{
26639 +       int retval = 0;
26640 +       if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
26641 +               DWC_WARN("Wrong value for data_fifo_size\n");
26642 +               DWC_WARN("data_fifo_size must be 32-32768\n");
26643 +               return -DWC_E_INVALID;
26644 +       }
26645 +
26646 +       if (val > core_if->hwcfg3.b.dfifo_depth) {
26647 +               if (dwc_otg_param_initialized
26648 +                   (core_if->core_params->data_fifo_size)) {
26649 +                       DWC_ERROR
26650 +                           ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
26651 +                            val);
26652 +               }
26653 +               val = core_if->hwcfg3.b.dfifo_depth;
26654 +               retval = -DWC_E_INVALID;
26655 +       }
26656 +
26657 +       core_if->core_params->data_fifo_size = val;
26658 +       return retval;
26659 +}
26660 +
26661 +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
26662 +{
26663 +       return core_if->core_params->data_fifo_size;
26664 +}
26665 +
26666 +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
26667 +{
26668 +       int retval = 0;
26669 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26670 +               DWC_WARN("Wrong value for dev_rx_fifo_size\n");
26671 +               DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
26672 +               return -DWC_E_INVALID;
26673 +       }
26674 +
26675 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26676 +               if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
26677 +               DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
26678 +               }
26679 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26680 +               retval = -DWC_E_INVALID;
26681 +       }
26682 +
26683 +       core_if->core_params->dev_rx_fifo_size = val;
26684 +       return retval;
26685 +}
26686 +
26687 +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
26688 +{
26689 +       return core_if->core_params->dev_rx_fifo_size;
26690 +}
26691 +
26692 +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26693 +                                             int32_t val)
26694 +{
26695 +       int retval = 0;
26696 +
26697 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26698 +               DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
26699 +               DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
26700 +               return -DWC_E_INVALID;
26701 +       }
26702 +
26703 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26704 +               if (dwc_otg_param_initialized
26705 +                   (core_if->core_params->dev_nperio_tx_fifo_size)) {
26706 +                       DWC_ERROR
26707 +                           ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
26708 +                            val);
26709 +               }
26710 +               val =
26711 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26712 +                    16);
26713 +               retval = -DWC_E_INVALID;
26714 +       }
26715 +
26716 +       core_if->core_params->dev_nperio_tx_fifo_size = val;
26717 +       return retval;
26718 +}
26719 +
26720 +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26721 +{
26722 +       return core_if->core_params->dev_nperio_tx_fifo_size;
26723 +}
26724 +
26725 +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
26726 +                                       int32_t val)
26727 +{
26728 +       int retval = 0;
26729 +
26730 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26731 +               DWC_WARN("Wrong value for host_rx_fifo_size\n");
26732 +               DWC_WARN("host_rx_fifo_size must be 16-32768\n");
26733 +               return -DWC_E_INVALID;
26734 +       }
26735 +
26736 +       if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
26737 +               if (dwc_otg_param_initialized
26738 +                   (core_if->core_params->host_rx_fifo_size)) {
26739 +                       DWC_ERROR
26740 +                           ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
26741 +                            val);
26742 +               }
26743 +               val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
26744 +               retval = -DWC_E_INVALID;
26745 +       }
26746 +
26747 +       core_if->core_params->host_rx_fifo_size = val;
26748 +       return retval;
26749 +
26750 +}
26751 +
26752 +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
26753 +{
26754 +       return core_if->core_params->host_rx_fifo_size;
26755 +}
26756 +
26757 +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26758 +                                              int32_t val)
26759 +{
26760 +       int retval = 0;
26761 +
26762 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26763 +               DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
26764 +               DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
26765 +               return -DWC_E_INVALID;
26766 +       }
26767 +
26768 +       if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
26769 +               if (dwc_otg_param_initialized
26770 +                   (core_if->core_params->host_nperio_tx_fifo_size)) {
26771 +                       DWC_ERROR
26772 +                           ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
26773 +                            val);
26774 +               }
26775 +               val =
26776 +                   (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
26777 +                    16);
26778 +               retval = -DWC_E_INVALID;
26779 +       }
26780 +
26781 +       core_if->core_params->host_nperio_tx_fifo_size = val;
26782 +       return retval;
26783 +}
26784 +
26785 +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26786 +{
26787 +       return core_if->core_params->host_nperio_tx_fifo_size;
26788 +}
26789 +
26790 +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
26791 +                                             int32_t val)
26792 +{
26793 +       int retval = 0;
26794 +       if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
26795 +               DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
26796 +               DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
26797 +               return -DWC_E_INVALID;
26798 +       }
26799 +
26800 +       if (val > ((core_if->hptxfsiz.d32) >> 16)) {
26801 +               if (dwc_otg_param_initialized
26802 +                   (core_if->core_params->host_perio_tx_fifo_size)) {
26803 +                       DWC_ERROR
26804 +                           ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
26805 +                            val);
26806 +               }
26807 +               val = (core_if->hptxfsiz.d32) >> 16;
26808 +               retval = -DWC_E_INVALID;
26809 +       }
26810 +
26811 +       core_if->core_params->host_perio_tx_fifo_size = val;
26812 +       return retval;
26813 +}
26814 +
26815 +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
26816 +{
26817 +       return core_if->core_params->host_perio_tx_fifo_size;
26818 +}
26819 +
26820 +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
26821 +                                       int32_t val)
26822 +{
26823 +       int retval = 0;
26824 +
26825 +       if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
26826 +               DWC_WARN("Wrong value for max_transfer_size\n");
26827 +               DWC_WARN("max_transfer_size must be 2047-524288\n");
26828 +               return -DWC_E_INVALID;
26829 +       }
26830 +
26831 +       if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
26832 +               if (dwc_otg_param_initialized
26833 +                   (core_if->core_params->max_transfer_size)) {
26834 +                       DWC_ERROR
26835 +                           ("%d invalid for max_transfer_size. Check HW configuration.\n",
26836 +                            val);
26837 +               }
26838 +               val =
26839 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
26840 +                    1);
26841 +               retval = -DWC_E_INVALID;
26842 +       }
26843 +
26844 +       core_if->core_params->max_transfer_size = val;
26845 +       return retval;
26846 +}
26847 +
26848 +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
26849 +{
26850 +       return core_if->core_params->max_transfer_size;
26851 +}
26852 +
26853 +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
26854 +{
26855 +       int retval = 0;
26856 +
26857 +       if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
26858 +               DWC_WARN("Wrong value for max_packet_count\n");
26859 +               DWC_WARN("max_packet_count must be 15-511\n");
26860 +               return -DWC_E_INVALID;
26861 +       }
26862 +
26863 +       if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
26864 +               if (dwc_otg_param_initialized
26865 +                   (core_if->core_params->max_packet_count)) {
26866 +                       DWC_ERROR
26867 +                           ("%d invalid for max_packet_count. Check HW configuration.\n",
26868 +                            val);
26869 +               }
26870 +               val =
26871 +                   ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
26872 +               retval = -DWC_E_INVALID;
26873 +       }
26874 +
26875 +       core_if->core_params->max_packet_count = val;
26876 +       return retval;
26877 +}
26878 +
26879 +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
26880 +{
26881 +       return core_if->core_params->max_packet_count;
26882 +}
26883 +
26884 +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
26885 +{
26886 +       int retval = 0;
26887 +
26888 +       if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
26889 +               DWC_WARN("Wrong value for host_channels\n");
26890 +               DWC_WARN("host_channels must be 1-16\n");
26891 +               return -DWC_E_INVALID;
26892 +       }
26893 +
26894 +       if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
26895 +               if (dwc_otg_param_initialized
26896 +                   (core_if->core_params->host_channels)) {
26897 +                       DWC_ERROR
26898 +                           ("%d invalid for host_channels. Check HW configurations.\n",
26899 +                            val);
26900 +               }
26901 +               val = (core_if->hwcfg2.b.num_host_chan + 1);
26902 +               retval = -DWC_E_INVALID;
26903 +       }
26904 +
26905 +       core_if->core_params->host_channels = val;
26906 +       return retval;
26907 +}
26908 +
26909 +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
26910 +{
26911 +       return core_if->core_params->host_channels;
26912 +}
26913 +
26914 +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
26915 +{
26916 +       int retval = 0;
26917 +
26918 +       if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
26919 +               DWC_WARN("Wrong value for dev_endpoints\n");
26920 +               DWC_WARN("dev_endpoints must be 1-15\n");
26921 +               return -DWC_E_INVALID;
26922 +       }
26923 +
26924 +       if (val > (core_if->hwcfg2.b.num_dev_ep)) {
26925 +               if (dwc_otg_param_initialized
26926 +                   (core_if->core_params->dev_endpoints)) {
26927 +                       DWC_ERROR
26928 +                           ("%d invalid for dev_endpoints. Check HW configurations.\n",
26929 +                            val);
26930 +               }
26931 +               val = core_if->hwcfg2.b.num_dev_ep;
26932 +               retval = -DWC_E_INVALID;
26933 +       }
26934 +
26935 +       core_if->core_params->dev_endpoints = val;
26936 +       return retval;
26937 +}
26938 +
26939 +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
26940 +{
26941 +       return core_if->core_params->dev_endpoints;
26942 +}
26943 +
26944 +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
26945 +{
26946 +       int retval = 0;
26947 +       int valid = 0;
26948 +
26949 +       if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
26950 +               DWC_WARN("Wrong value for phy_type\n");
26951 +               DWC_WARN("phy_type must be 0,1 or 2\n");
26952 +               return -DWC_E_INVALID;
26953 +       }
26954 +#ifndef NO_FS_PHY_HW_CHECKS
26955 +       if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
26956 +           ((core_if->hwcfg2.b.hs_phy_type == 1) ||
26957 +            (core_if->hwcfg2.b.hs_phy_type == 3))) {
26958 +               valid = 1;
26959 +       } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
26960 +                  ((core_if->hwcfg2.b.hs_phy_type == 2) ||
26961 +                   (core_if->hwcfg2.b.hs_phy_type == 3))) {
26962 +               valid = 1;
26963 +       } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
26964 +                  (core_if->hwcfg2.b.fs_phy_type == 1)) {
26965 +               valid = 1;
26966 +       }
26967 +       if (!valid) {
26968 +               if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
26969 +                       DWC_ERROR
26970 +                           ("%d invalid for phy_type. Check HW configurations.\n",
26971 +                            val);
26972 +               }
26973 +               if (core_if->hwcfg2.b.hs_phy_type) {
26974 +                       if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
26975 +                           (core_if->hwcfg2.b.hs_phy_type == 1)) {
26976 +                               val = DWC_PHY_TYPE_PARAM_UTMI;
26977 +                       } else {
26978 +                               val = DWC_PHY_TYPE_PARAM_ULPI;
26979 +                       }
26980 +               }
26981 +               retval = -DWC_E_INVALID;
26982 +       }
26983 +#endif
26984 +       core_if->core_params->phy_type = val;
26985 +       return retval;
26986 +}
26987 +
26988 +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
26989 +{
26990 +       return core_if->core_params->phy_type;
26991 +}
26992 +
26993 +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
26994 +{
26995 +       int retval = 0;
26996 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
26997 +               DWC_WARN("Wrong value for speed parameter\n");
26998 +               DWC_WARN("max_speed parameter must be 0 or 1\n");
26999 +               return -DWC_E_INVALID;
27000 +       }
27001 +       if ((val == 0)
27002 +           && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
27003 +               if (dwc_otg_param_initialized(core_if->core_params->speed)) {
27004 +                       DWC_ERROR
27005 +                           ("%d invalid for speed paremter. Check HW configuration.\n",
27006 +                            val);
27007 +               }
27008 +               val =
27009 +                   (dwc_otg_get_param_phy_type(core_if) ==
27010 +                    DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
27011 +               retval = -DWC_E_INVALID;
27012 +       }
27013 +       core_if->core_params->speed = val;
27014 +       return retval;
27015 +}
27016 +
27017 +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
27018 +{
27019 +       return core_if->core_params->speed;
27020 +}
27021 +
27022 +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
27023 +                                               int32_t val)
27024 +{
27025 +       int retval = 0;
27026 +
27027 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27028 +               DWC_WARN
27029 +                   ("Wrong value for host_ls_low_power_phy_clk parameter\n");
27030 +               DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
27031 +               return -DWC_E_INVALID;
27032 +       }
27033 +
27034 +       if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
27035 +           && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
27036 +               if (dwc_otg_param_initialized
27037 +                   (core_if->core_params->host_ls_low_power_phy_clk)) {
27038 +                       DWC_ERROR
27039 +                           ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
27040 +                            val);
27041 +               }
27042 +               val =
27043 +                   (dwc_otg_get_param_phy_type(core_if) ==
27044 +                    DWC_PHY_TYPE_PARAM_FS) ?
27045 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
27046 +                   DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
27047 +               retval = -DWC_E_INVALID;
27048 +       }
27049 +
27050 +       core_if->core_params->host_ls_low_power_phy_clk = val;
27051 +       return retval;
27052 +}
27053 +
27054 +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
27055 +{
27056 +       return core_if->core_params->host_ls_low_power_phy_clk;
27057 +}
27058 +
27059 +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
27060 +{
27061 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27062 +               DWC_WARN("Wrong value for phy_ulpi_ddr\n");
27063 +               DWC_WARN("phy_upli_ddr must be 0 or 1\n");
27064 +               return -DWC_E_INVALID;
27065 +       }
27066 +
27067 +       core_if->core_params->phy_ulpi_ddr = val;
27068 +       return 0;
27069 +}
27070 +
27071 +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
27072 +{
27073 +       return core_if->core_params->phy_ulpi_ddr;
27074 +}
27075 +
27076 +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
27077 +                                       int32_t val)
27078 +{
27079 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27080 +               DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
27081 +               DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
27082 +               return -DWC_E_INVALID;
27083 +       }
27084 +
27085 +       core_if->core_params->phy_ulpi_ext_vbus = val;
27086 +       return 0;
27087 +}
27088 +
27089 +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
27090 +{
27091 +       return core_if->core_params->phy_ulpi_ext_vbus;
27092 +}
27093 +
27094 +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
27095 +{
27096 +       if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
27097 +               DWC_WARN("Wrong valaue for phy_utmi_width\n");
27098 +               DWC_WARN("phy_utmi_width must be 8 or 16\n");
27099 +               return -DWC_E_INVALID;
27100 +       }
27101 +
27102 +       core_if->core_params->phy_utmi_width = val;
27103 +       return 0;
27104 +}
27105 +
27106 +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
27107 +{
27108 +       return core_if->core_params->phy_utmi_width;
27109 +}
27110 +
27111 +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
27112 +{
27113 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27114 +               DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
27115 +               DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
27116 +               return -DWC_E_INVALID;
27117 +       }
27118 +
27119 +       core_if->core_params->ulpi_fs_ls = val;
27120 +       return 0;
27121 +}
27122 +
27123 +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
27124 +{
27125 +       return core_if->core_params->ulpi_fs_ls;
27126 +}
27127 +
27128 +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
27129 +{
27130 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27131 +               DWC_WARN("Wrong valaue for ts_dline\n");
27132 +               DWC_WARN("ts_dline must be 0 or 1\n");
27133 +               return -DWC_E_INVALID;
27134 +       }
27135 +
27136 +       core_if->core_params->ts_dline = val;
27137 +       return 0;
27138 +}
27139 +
27140 +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
27141 +{
27142 +       return core_if->core_params->ts_dline;
27143 +}
27144 +
27145 +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
27146 +{
27147 +       int retval = 0;
27148 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27149 +               DWC_WARN("Wrong valaue for i2c_enable\n");
27150 +               DWC_WARN("i2c_enable must be 0 or 1\n");
27151 +               return -DWC_E_INVALID;
27152 +       }
27153 +#ifndef NO_FS_PHY_HW_CHECK
27154 +       if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
27155 +               if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
27156 +                       DWC_ERROR
27157 +                           ("%d invalid for i2c_enable. Check HW configuration.\n",
27158 +                            val);
27159 +               }
27160 +               val = 0;
27161 +               retval = -DWC_E_INVALID;
27162 +       }
27163 +#endif
27164 +
27165 +       core_if->core_params->i2c_enable = val;
27166 +       return retval;
27167 +}
27168 +
27169 +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
27170 +{
27171 +       return core_if->core_params->i2c_enable;
27172 +}
27173 +
27174 +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27175 +                                            int32_t val, int fifo_num)
27176 +{
27177 +       int retval = 0;
27178 +
27179 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27180 +               DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
27181 +               DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
27182 +               return -DWC_E_INVALID;
27183 +       }
27184 +
27185 +       if (val >
27186 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27187 +               if (dwc_otg_param_initialized
27188 +                   (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
27189 +                       DWC_ERROR
27190 +                           ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
27191 +                            val, fifo_num);
27192 +               }
27193 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27194 +               retval = -DWC_E_INVALID;
27195 +       }
27196 +
27197 +       core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
27198 +       return retval;
27199 +}
27200 +
27201 +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
27202 +                                                int fifo_num)
27203 +{
27204 +       return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
27205 +}
27206 +
27207 +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
27208 +                                         int32_t val)
27209 +{
27210 +       int retval = 0;
27211 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27212 +               DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
27213 +               DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
27214 +               return -DWC_E_INVALID;
27215 +       }
27216 +
27217 +       if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
27218 +               if (dwc_otg_param_initialized
27219 +                   (core_if->core_params->en_multiple_tx_fifo)) {
27220 +                       DWC_ERROR
27221 +                           ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
27222 +                            val);
27223 +               }
27224 +               val = 0;
27225 +               retval = -DWC_E_INVALID;
27226 +       }
27227 +
27228 +       core_if->core_params->en_multiple_tx_fifo = val;
27229 +       return retval;
27230 +}
27231 +
27232 +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
27233 +{
27234 +       return core_if->core_params->en_multiple_tx_fifo;
27235 +}
27236 +
27237 +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
27238 +                                      int fifo_num)
27239 +{
27240 +       int retval = 0;
27241 +
27242 +       if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
27243 +               DWC_WARN("Wrong value for dev_tx_fifo_size\n");
27244 +               DWC_WARN("dev_tx_fifo_size must be 4-768\n");
27245 +               return -DWC_E_INVALID;
27246 +       }
27247 +
27248 +       if (val >
27249 +           (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
27250 +               if (dwc_otg_param_initialized
27251 +                   (core_if->core_params->dev_tx_fifo_size[fifo_num])) {
27252 +                       DWC_ERROR
27253 +                           ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
27254 +                            val, fifo_num);
27255 +               }
27256 +               val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
27257 +               retval = -DWC_E_INVALID;
27258 +       }
27259 +
27260 +       core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
27261 +       return retval;
27262 +}
27263 +
27264 +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
27265 +                                          int fifo_num)
27266 +{
27267 +       return core_if->core_params->dev_tx_fifo_size[fifo_num];
27268 +}
27269 +
27270 +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27271 +{
27272 +       int retval = 0;
27273 +
27274 +       if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
27275 +               DWC_WARN("Wrong value for thr_ctl\n");
27276 +               DWC_WARN("thr_ctl must be 0-7\n");
27277 +               return -DWC_E_INVALID;
27278 +       }
27279 +
27280 +       if ((val != 0) &&
27281 +           (!dwc_otg_get_param_dma_enable(core_if) ||
27282 +            !core_if->hwcfg4.b.ded_fifo_en)) {
27283 +               if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
27284 +                       DWC_ERROR
27285 +                           ("%d invalid for parameter thr_ctl. Check HW configuration.\n",
27286 +                            val);
27287 +               }
27288 +               val = 0;
27289 +               retval = -DWC_E_INVALID;
27290 +       }
27291 +
27292 +       core_if->core_params->thr_ctl = val;
27293 +       return retval;
27294 +}
27295 +
27296 +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
27297 +{
27298 +       return core_if->core_params->thr_ctl;
27299 +}
27300 +
27301 +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
27302 +{
27303 +       int retval = 0;
27304 +
27305 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27306 +               DWC_WARN("Wrong value for lpm_enable\n");
27307 +               DWC_WARN("lpm_enable must be 0 or 1\n");
27308 +               return -DWC_E_INVALID;
27309 +       }
27310 +
27311 +       if (val && !core_if->hwcfg3.b.otg_lpm_en) {
27312 +               if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
27313 +                       DWC_ERROR
27314 +                           ("%d invalid for parameter lpm_enable. Check HW configuration.\n",
27315 +                            val);
27316 +               }
27317 +               val = 0;
27318 +               retval = -DWC_E_INVALID;
27319 +       }
27320 +
27321 +       core_if->core_params->lpm_enable = val;
27322 +       return retval;
27323 +}
27324 +
27325 +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
27326 +{
27327 +       return core_if->core_params->lpm_enable;
27328 +}
27329 +
27330 +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27331 +{
27332 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27333 +               DWC_WARN("Wrong valaue for tx_thr_length\n");
27334 +               DWC_WARN("tx_thr_length must be 8 - 128\n");
27335 +               return -DWC_E_INVALID;
27336 +       }
27337 +
27338 +       core_if->core_params->tx_thr_length = val;
27339 +       return 0;
27340 +}
27341 +
27342 +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
27343 +{
27344 +       return core_if->core_params->tx_thr_length;
27345 +}
27346 +
27347 +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
27348 +{
27349 +       if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
27350 +               DWC_WARN("Wrong valaue for rx_thr_length\n");
27351 +               DWC_WARN("rx_thr_length must be 8 - 128\n");
27352 +               return -DWC_E_INVALID;
27353 +       }
27354 +
27355 +       core_if->core_params->rx_thr_length = val;
27356 +       return 0;
27357 +}
27358 +
27359 +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
27360 +{
27361 +       return core_if->core_params->rx_thr_length;
27362 +}
27363 +
27364 +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
27365 +{
27366 +       if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
27367 +           DWC_OTG_PARAM_TEST(val, 4, 4) &&
27368 +           DWC_OTG_PARAM_TEST(val, 8, 8) &&
27369 +           DWC_OTG_PARAM_TEST(val, 16, 16) &&
27370 +           DWC_OTG_PARAM_TEST(val, 32, 32) &&
27371 +           DWC_OTG_PARAM_TEST(val, 64, 64) &&
27372 +           DWC_OTG_PARAM_TEST(val, 128, 128) &&
27373 +           DWC_OTG_PARAM_TEST(val, 256, 256)) {
27374 +               DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
27375 +               return -DWC_E_INVALID;
27376 +       }
27377 +       core_if->core_params->dma_burst_size = val;
27378 +       return 0;
27379 +}
27380 +
27381 +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
27382 +{
27383 +       return core_if->core_params->dma_burst_size;
27384 +}
27385 +
27386 +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
27387 +{
27388 +       int retval = 0;
27389 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27390 +               DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
27391 +               return -DWC_E_INVALID;
27392 +       }
27393 +       if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
27394 +               if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
27395 +                       DWC_ERROR
27396 +                           ("%d invalid for parameter pti_enable. Check HW configuration.\n",
27397 +                            val);
27398 +               }
27399 +               retval = -DWC_E_INVALID;
27400 +               val = 0;
27401 +       }
27402 +       core_if->core_params->pti_enable = val;
27403 +       return retval;
27404 +}
27405 +
27406 +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
27407 +{
27408 +       return core_if->core_params->pti_enable;
27409 +}
27410 +
27411 +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
27412 +{
27413 +       int retval = 0;
27414 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27415 +               DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
27416 +               return -DWC_E_INVALID;
27417 +       }
27418 +       if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
27419 +               if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
27420 +                       DWC_ERROR
27421 +                           ("%d invalid for parameter mpi_enable. Check HW configuration.\n",
27422 +                            val);
27423 +               }
27424 +               retval = -DWC_E_INVALID;
27425 +               val = 0;
27426 +       }
27427 +       core_if->core_params->mpi_enable = val;
27428 +       return retval;
27429 +}
27430 +
27431 +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
27432 +{
27433 +       return core_if->core_params->mpi_enable;
27434 +}
27435 +
27436 +int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)
27437 +{
27438 +       int retval = 0;
27439 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27440 +               DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);
27441 +               return -DWC_E_INVALID;
27442 +       }
27443 +       if (val && (core_if->hwcfg3.b.adp_supp == 0)) {
27444 +               if (dwc_otg_param_initialized
27445 +                   (core_if->core_params->adp_supp_enable)) {
27446 +                       DWC_ERROR
27447 +                           ("%d invalid for parameter adp_enable. Check HW configuration.\n",
27448 +                            val);
27449 +               }
27450 +               retval = -DWC_E_INVALID;
27451 +               val = 0;
27452 +       }
27453 +       core_if->core_params->adp_supp_enable = val;
27454 +       /*Set OTG version 2.0 in case of enabling ADP*/
27455 +       if (val)
27456 +               dwc_otg_set_param_otg_ver(core_if, 1);
27457 +
27458 +       return retval;
27459 +}
27460 +
27461 +int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)
27462 +{
27463 +       return core_if->core_params->adp_supp_enable;
27464 +}
27465 +
27466 +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)
27467 +{
27468 +       int retval = 0;
27469 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27470 +               DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
27471 +               DWC_WARN("ic_usb_cap must be 0 or 1\n");
27472 +               return -DWC_E_INVALID;
27473 +       }
27474 +
27475 +       if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {
27476 +               if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
27477 +                       DWC_ERROR
27478 +                           ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
27479 +                            val);
27480 +               }
27481 +               retval = -DWC_E_INVALID;
27482 +               val = 0;
27483 +       }
27484 +       core_if->core_params->ic_usb_cap = val;
27485 +       return retval;
27486 +}
27487 +
27488 +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
27489 +{
27490 +       return core_if->core_params->ic_usb_cap;
27491 +}
27492 +
27493 +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
27494 +{
27495 +       int retval = 0;
27496 +       int valid = 1;
27497 +
27498 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27499 +               DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
27500 +               DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
27501 +               return -DWC_E_INVALID;
27502 +       }
27503 +
27504 +       if (val
27505 +           && (core_if->snpsid < OTG_CORE_REV_2_81a
27506 +               || !dwc_otg_get_param_thr_ctl(core_if))) {
27507 +               valid = 0;
27508 +       } else if (val
27509 +                  && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <
27510 +                      4)) {
27511 +               valid = 0;
27512 +       }
27513 +       if (valid == 0) {
27514 +               if (dwc_otg_param_initialized
27515 +                   (core_if->core_params->ahb_thr_ratio)) {
27516 +                       DWC_ERROR
27517 +                           ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",
27518 +                            val);
27519 +               }
27520 +               retval = -DWC_E_INVALID;
27521 +               val = 0;
27522 +       }
27523 +
27524 +       core_if->core_params->ahb_thr_ratio = val;
27525 +       return retval;
27526 +}
27527 +
27528 +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
27529 +{
27530 +       return core_if->core_params->ahb_thr_ratio;
27531 +}
27532 +
27533 +int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)
27534 +{
27535 +       int retval = 0;
27536 +       int valid = 1;
27537 +       hwcfg4_data_t hwcfg4 = {.d32 = 0 };
27538 +       hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
27539 +
27540 +       if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
27541 +               DWC_WARN("`%d' invalid for parameter `power_down'\n", val);
27542 +               DWC_WARN("power_down must be 0 - 2\n");
27543 +               return -DWC_E_INVALID;
27544 +       }
27545 +
27546 +       if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {
27547 +               valid = 0;
27548 +       }
27549 +       if ((val == 3)
27550 +           && ((core_if->snpsid < OTG_CORE_REV_3_00a)
27551 +               || (hwcfg4.b.xhiber == 0))) {
27552 +               valid = 0;
27553 +       }
27554 +       if (valid == 0) {
27555 +               if (dwc_otg_param_initialized(core_if->core_params->power_down)) {
27556 +                       DWC_ERROR
27557 +                           ("%d invalid for parameter power_down. Check HW configuration.\n",
27558 +                            val);
27559 +               }
27560 +               retval = -DWC_E_INVALID;
27561 +               val = 0;
27562 +       }
27563 +       core_if->core_params->power_down = val;
27564 +       return retval;
27565 +}
27566 +
27567 +int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)
27568 +{
27569 +       return core_if->core_params->power_down;
27570 +}
27571 +
27572 +int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)
27573 +{
27574 +       int retval = 0;
27575 +       int valid = 1;
27576 +
27577 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27578 +               DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);
27579 +               DWC_WARN("reload_ctl must be 0 or 1\n");
27580 +               return -DWC_E_INVALID;
27581 +       }
27582 +
27583 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {
27584 +               valid = 0;
27585 +       }
27586 +       if (valid == 0) {
27587 +               if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {
27588 +                       DWC_ERROR("%d invalid for parameter reload_ctl."
27589 +                                 "Check HW configuration.\n", val);
27590 +               }
27591 +               retval = -DWC_E_INVALID;
27592 +               val = 0;
27593 +       }
27594 +       core_if->core_params->reload_ctl = val;
27595 +       return retval;
27596 +}
27597 +
27598 +int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)
27599 +{
27600 +       return core_if->core_params->reload_ctl;
27601 +}
27602 +
27603 +int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)
27604 +{
27605 +       int retval = 0;
27606 +       int valid = 1;
27607 +
27608 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27609 +               DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);
27610 +               DWC_WARN("dev_out_nak must be 0 or 1\n");
27611 +               return -DWC_E_INVALID;
27612 +       }
27613 +
27614 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||
27615 +               !(core_if->core_params->dma_desc_enable))) {
27616 +               valid = 0;
27617 +       }
27618 +       if (valid == 0) {
27619 +               if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {
27620 +                       DWC_ERROR("%d invalid for parameter dev_out_nak."
27621 +                               "Check HW configuration.\n", val);
27622 +               }
27623 +               retval = -DWC_E_INVALID;
27624 +               val = 0;
27625 +       }
27626 +       core_if->core_params->dev_out_nak = val;
27627 +       return retval;
27628 +}
27629 +
27630 +int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)
27631 +{
27632 +       return core_if->core_params->dev_out_nak;
27633 +}
27634 +
27635 +int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
27636 +{
27637 +       int retval = 0;
27638 +       int valid = 1;
27639 +
27640 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27641 +               DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
27642 +               DWC_WARN("cont_on_bna must be 0 or 1\n");
27643 +               return -DWC_E_INVALID;
27644 +       }
27645 +
27646 +       if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
27647 +               !(core_if->core_params->dma_desc_enable))) {
27648 +                       valid = 0;
27649 +       }
27650 +       if (valid == 0) {
27651 +               if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
27652 +                       DWC_ERROR("%d invalid for parameter cont_on_bna."
27653 +                               "Check HW configuration.\n", val);
27654 +               }
27655 +               retval = -DWC_E_INVALID;
27656 +               val = 0;
27657 +       }
27658 +       core_if->core_params->cont_on_bna = val;
27659 +       return retval;
27660 +}
27661 +
27662 +int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
27663 +{
27664 +       return core_if->core_params->cont_on_bna;
27665 +}
27666 +
27667 +int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
27668 +{
27669 +       int retval = 0;
27670 +       int valid = 1;
27671 +
27672 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27673 +               DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
27674 +               DWC_WARN("ahb_single must be 0 or 1\n");
27675 +               return -DWC_E_INVALID;
27676 +       }
27677 +
27678 +       if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
27679 +                       valid = 0;
27680 +       }
27681 +       if (valid == 0) {
27682 +               if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
27683 +                       DWC_ERROR("%d invalid for parameter ahb_single."
27684 +                               "Check HW configuration.\n", val);
27685 +               }
27686 +               retval = -DWC_E_INVALID;
27687 +               val = 0;
27688 +       }
27689 +       core_if->core_params->ahb_single = val;
27690 +       return retval;
27691 +}
27692 +
27693 +int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
27694 +{
27695 +       return core_if->core_params->ahb_single;
27696 +}
27697 +
27698 +int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
27699 +{
27700 +       int retval = 0;
27701 +
27702 +       if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
27703 +               DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);
27704 +               DWC_WARN
27705 +                   ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");
27706 +               return -DWC_E_INVALID;
27707 +       }
27708 +
27709 +       core_if->core_params->otg_ver = val;
27710 +       return retval;
27711 +}
27712 +
27713 +int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)
27714 +{
27715 +       return core_if->core_params->otg_ver;
27716 +}
27717 +
27718 +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
27719 +{
27720 +       gotgctl_data_t otgctl;
27721 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27722 +       return otgctl.b.hstnegscs;
27723 +}
27724 +
27725 +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
27726 +{
27727 +       gotgctl_data_t otgctl;
27728 +       otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27729 +       return otgctl.b.sesreqscs;
27730 +}
27731 +
27732 +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
27733 +{
27734 +       if(core_if->otg_ver == 0) {
27735 +               gotgctl_data_t otgctl;
27736 +               otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
27737 +               otgctl.b.hnpreq = val;
27738 +               DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);
27739 +       } else {
27740 +               core_if->otg_sts = val;
27741 +       }
27742 +}
27743 +
27744 +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
27745 +{
27746 +       return core_if->snpsid;
27747 +}
27748 +
27749 +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
27750 +{
27751 +       gintsts_data_t gintsts;
27752 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
27753 +       return gintsts.b.curmode;
27754 +}
27755 +
27756 +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
27757 +{
27758 +       gusbcfg_data_t usbcfg;
27759 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27760 +       return usbcfg.b.hnpcap;
27761 +}
27762 +
27763 +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27764 +{
27765 +       gusbcfg_data_t usbcfg;
27766 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27767 +       usbcfg.b.hnpcap = val;
27768 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27769 +}
27770 +
27771 +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
27772 +{
27773 +       gusbcfg_data_t usbcfg;
27774 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27775 +       return usbcfg.b.srpcap;
27776 +}
27777 +
27778 +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
27779 +{
27780 +       gusbcfg_data_t usbcfg;
27781 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
27782 +       usbcfg.b.srpcap = val;
27783 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
27784 +}
27785 +
27786 +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
27787 +{
27788 +       dcfg_data_t dcfg;
27789 +       /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */
27790 +
27791 +        dcfg.d32 = -1; //GRAYG
27792 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
27793 +        if (NULL == core_if)
27794 +                DWC_ERROR("reg request with NULL core_if\n");
27795 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
27796 +                    core_if, core_if->dev_if);
27797 +        if (NULL == core_if->dev_if)
27798 +                DWC_ERROR("reg request with NULL dev_if\n");
27799 +        DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
27800 +                    "dev_global_regs(%p)\n", __func__,
27801 +                    core_if, core_if->dev_if,
27802 +                    core_if->dev_if->dev_global_regs);
27803 +        if (NULL == core_if->dev_if->dev_global_regs)
27804 +                DWC_ERROR("reg request with NULL dev_global_regs\n");
27805 +        else {
27806 +                DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
27807 +                            "dev_global_regs(%p)->dcfg = %p\n", __func__,
27808 +                            core_if, core_if->dev_if,
27809 +                            core_if->dev_if->dev_global_regs,
27810 +                            &core_if->dev_if->dev_global_regs->dcfg);
27811 +               dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27812 +        }
27813 +       return dcfg.b.devspd;
27814 +}
27815 +
27816 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
27817 +{
27818 +       dcfg_data_t dcfg;
27819 +       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
27820 +       dcfg.b.devspd = val;
27821 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
27822 +}
27823 +
27824 +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
27825 +{
27826 +       hprt0_data_t hprt0;
27827 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27828 +       return hprt0.b.prtconnsts;
27829 +}
27830 +
27831 +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
27832 +{
27833 +       dsts_data_t dsts;
27834 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
27835 +       return dsts.b.enumspd;
27836 +}
27837 +
27838 +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
27839 +{
27840 +       hprt0_data_t hprt0;
27841 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27842 +       return hprt0.b.prtpwr;
27843 +
27844 +}
27845 +
27846 +uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)
27847 +{
27848 +       return core_if->hibernation_suspend;
27849 +}
27850 +
27851 +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
27852 +{
27853 +       hprt0_data_t hprt0;
27854 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27855 +       hprt0.b.prtpwr = val;
27856 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27857 +}
27858 +
27859 +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
27860 +{
27861 +       hprt0_data_t hprt0;
27862 +       hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
27863 +       return hprt0.b.prtsusp;
27864 +
27865 +}
27866 +
27867 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
27868 +{
27869 +       hprt0_data_t hprt0;
27870 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27871 +       hprt0.b.prtsusp = val;
27872 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27873 +}
27874 +
27875 +uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)
27876 +{
27877 +       hfir_data_t hfir;
27878 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27879 +       return hfir.b.frint;
27880 +
27881 +}
27882 +
27883 +void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)
27884 +{
27885 +       hfir_data_t hfir;
27886 +       uint32_t fram_int;
27887 +       fram_int = calc_frame_interval(core_if);
27888 +       hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
27889 +       if (!core_if->core_params->reload_ctl) {
27890 +               DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"
27891 +                        "not set to 1.\nShould load driver with reload_ctl=1"
27892 +                        " module parameter\n");
27893 +               return;
27894 +       }
27895 +       switch (fram_int) {
27896 +       case 3750:
27897 +               if ((val < 3350) || (val > 4150)) {
27898 +                       DWC_WARN("HFIR interval for HS core and 30 MHz"
27899 +                                "clock freq should be from 3350 to 4150\n");
27900 +                       return;
27901 +               }
27902 +               break;
27903 +       case 30000:
27904 +               if ((val < 26820) || (val > 33180)) {
27905 +                       DWC_WARN("HFIR interval for FS/LS core and 30 MHz"
27906 +                                "clock freq should be from 26820 to 33180\n");
27907 +                       return;
27908 +               }
27909 +               break;
27910 +       case 6000:
27911 +               if ((val < 5360) || (val > 6640)) {
27912 +                       DWC_WARN("HFIR interval for HS core and 48 MHz"
27913 +                                "clock freq should be from 5360 to 6640\n");
27914 +                       return;
27915 +               }
27916 +               break;
27917 +       case 48000:
27918 +               if ((val < 42912) || (val > 53088)) {
27919 +                       DWC_WARN("HFIR interval for FS/LS core and 48 MHz"
27920 +                                "clock freq should be from 42912 to 53088\n");
27921 +                       return;
27922 +               }
27923 +               break;
27924 +       case 7500:
27925 +               if ((val < 6700) || (val > 8300)) {
27926 +                       DWC_WARN("HFIR interval for HS core and 60 MHz"
27927 +                                "clock freq should be from 6700 to 8300\n");
27928 +                       return;
27929 +               }
27930 +               break;
27931 +       case 60000:
27932 +               if ((val < 53640) || (val > 65536)) {
27933 +                       DWC_WARN("HFIR interval for FS/LS core and 60 MHz"
27934 +                                "clock freq should be from 53640 to 65536\n");
27935 +                       return;
27936 +               }
27937 +               break;
27938 +       default:
27939 +               DWC_WARN("Unknown frame interval\n");
27940 +               return;
27941 +               break;
27942 +
27943 +       }
27944 +       hfir.b.frint = val;
27945 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);
27946 +}
27947 +
27948 +uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)
27949 +{
27950 +       hcfg_data_t hcfg;
27951 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
27952 +       return hcfg.b.modechtimen;
27953 +
27954 +}
27955 +
27956 +void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)
27957 +{
27958 +       hcfg_data_t hcfg;
27959 +       hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
27960 +       hcfg.b.modechtimen = val;
27961 +       DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
27962 +}
27963 +
27964 +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
27965 +{
27966 +       hprt0_data_t hprt0;
27967 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
27968 +       hprt0.b.prtres = val;
27969 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
27970 +}
27971 +
27972 +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
27973 +{
27974 +       dctl_data_t dctl;
27975 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
27976 +       return dctl.b.rmtwkupsig;
27977 +}
27978 +
27979 +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
27980 +{
27981 +       glpmcfg_data_t lpmcfg;
27982 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27983 +
27984 +       DWC_ASSERT(!
27985 +                  ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
27986 +                  "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
27987 +                  core_if->lx_state, lpmcfg.b.prt_sleep_sts);
27988 +
27989 +       return lpmcfg.b.prt_sleep_sts;
27990 +}
27991 +
27992 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
27993 +{
27994 +       glpmcfg_data_t lpmcfg;
27995 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
27996 +       return lpmcfg.b.rem_wkup_en;
27997 +}
27998 +
27999 +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
28000 +{
28001 +       glpmcfg_data_t lpmcfg;
28002 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28003 +       return lpmcfg.b.appl_resp;
28004 +}
28005 +
28006 +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
28007 +{
28008 +       glpmcfg_data_t lpmcfg;
28009 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28010 +       lpmcfg.b.appl_resp = val;
28011 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28012 +}
28013 +
28014 +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
28015 +{
28016 +       glpmcfg_data_t lpmcfg;
28017 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28018 +       return lpmcfg.b.hsic_connect;
28019 +}
28020 +
28021 +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
28022 +{
28023 +       glpmcfg_data_t lpmcfg;
28024 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28025 +       lpmcfg.b.hsic_connect = val;
28026 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28027 +}
28028 +
28029 +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
28030 +{
28031 +       glpmcfg_data_t lpmcfg;
28032 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28033 +       return lpmcfg.b.inv_sel_hsic;
28034 +
28035 +}
28036 +
28037 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
28038 +{
28039 +       glpmcfg_data_t lpmcfg;
28040 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
28041 +       lpmcfg.b.inv_sel_hsic = val;
28042 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
28043 +}
28044 +
28045 +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
28046 +{
28047 +       return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
28048 +}
28049 +
28050 +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
28051 +{
28052 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);
28053 +}
28054 +
28055 +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
28056 +{
28057 +       return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
28058 +}
28059 +
28060 +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
28061 +{
28062 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);
28063 +}
28064 +
28065 +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
28066 +{
28067 +       return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
28068 +}
28069 +
28070 +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28071 +{
28072 +       DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);
28073 +}
28074 +
28075 +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
28076 +{
28077 +       return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
28078 +}
28079 +
28080 +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
28081 +{
28082 +       DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);
28083 +}
28084 +
28085 +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
28086 +{
28087 +       return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);
28088 +}
28089 +
28090 +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
28091 +{
28092 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);
28093 +}
28094 +
28095 +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
28096 +{
28097 +       return DWC_READ_REG32(&core_if->core_global_regs->ggpio);
28098 +}
28099 +
28100 +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
28101 +{
28102 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);
28103 +}
28104 +
28105 +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
28106 +{
28107 +       return DWC_READ_REG32(core_if->host_if->hprt0);
28108 +
28109 +}
28110 +
28111 +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
28112 +{
28113 +       DWC_WRITE_REG32(core_if->host_if->hprt0, val);
28114 +}
28115 +
28116 +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
28117 +{
28118 +       return DWC_READ_REG32(&core_if->core_global_regs->guid);
28119 +}
28120 +
28121 +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
28122 +{
28123 +       DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);
28124 +}
28125 +
28126 +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
28127 +{
28128 +       return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
28129 +}
28130 +
28131 +uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)
28132 +{
28133 +       return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);
28134 +}
28135 +
28136 +/**
28137 + * Start the SRP timer to detect when the SRP does not complete within
28138 + * 6 seconds.
28139 + *
28140 + * @param core_if the pointer to core_if strucure.
28141 + */
28142 +void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)
28143 +{
28144 +       core_if->srp_timer_started = 1;
28145 +       DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );
28146 +}
28147 +
28148 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)
28149 +{
28150 +       uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);
28151 +       gotgctl_data_t mem;
28152 +       gotgctl_data_t val;
28153 +
28154 +       val.d32 = DWC_READ_REG32(addr);
28155 +       if (val.b.sesreq) {
28156 +               DWC_ERROR("Session Request Already active!\n");
28157 +               return;
28158 +       }
28159 +
28160 +       DWC_INFO("Session Request Initated\n"); //NOTICE
28161 +       mem.d32 = DWC_READ_REG32(addr);
28162 +       mem.b.sesreq = 1;
28163 +       DWC_WRITE_REG32(addr, mem.d32);
28164 +
28165 +       /* Start the SRP timer */
28166 +       dwc_otg_pcd_start_srp_timer(core_if);
28167 +       return;
28168 +}
28169 --- /dev/null
28170 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
28171 @@ -0,0 +1,1464 @@
28172 +/* ==========================================================================
28173 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
28174 + * $Revision: #123 $
28175 + * $Date: 2012/08/10 $
28176 + * $Change: 2047372 $
28177 + *
28178 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
28179 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
28180 + * otherwise expressly agreed to in writing between Synopsys and you.
28181 + *
28182 + * The Software IS NOT an item of Licensed Software or Licensed Product under
28183 + * any End User Software License Agreement or Agreement for Licensed Product
28184 + * with Synopsys or any supplement thereto. You are permitted to use and
28185 + * redistribute this Software in source and binary forms, with or without
28186 + * modification, provided that redistributions of source code must retain this
28187 + * notice. You may not view, use, disclose, copy or distribute this file or
28188 + * any information contained herein except pursuant to this license grant from
28189 + * Synopsys. If you do not agree with this notice, including the disclaimer
28190 + * below, then you are not authorized to use the Software.
28191 + *
28192 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
28193 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28194 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28195 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
28196 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28197 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28198 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28199 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28200 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28201 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28202 + * DAMAGE.
28203 + * ========================================================================== */
28204 +
28205 +#if !defined(__DWC_CIL_H__)
28206 +#define __DWC_CIL_H__
28207 +
28208 +#include "dwc_list.h"
28209 +#include "dwc_otg_dbg.h"
28210 +#include "dwc_otg_regs.h"
28211 +
28212 +#include "dwc_otg_core_if.h"
28213 +#include "dwc_otg_adp.h"
28214 +
28215 +/**
28216 + * @file
28217 + * This file contains the interface to the Core Interface Layer.
28218 + */
28219 +
28220 +#ifdef DWC_UTE_CFI
28221 +
28222 +#define MAX_DMA_DESCS_PER_EP   256
28223 +
28224 +/**
28225 + * Enumeration for the data buffer mode
28226 + */
28227 +typedef enum _data_buffer_mode {
28228 +       BM_STANDARD = 0,        /* data buffer is in normal mode */
28229 +       BM_SG = 1,              /* data buffer uses the scatter/gather mode */
28230 +       BM_CONCAT = 2,          /* data buffer uses the concatenation mode */
28231 +       BM_CIRCULAR = 3,        /* data buffer uses the circular DMA mode */
28232 +       BM_ALIGN = 4            /* data buffer is in buffer alignment mode */
28233 +} data_buffer_mode_e;
28234 +#endif //DWC_UTE_CFI
28235 +
28236 +/** Macros defined for DWC OTG HW Release version */
28237 +
28238 +#define OTG_CORE_REV_2_60a     0x4F54260A
28239 +#define OTG_CORE_REV_2_71a     0x4F54271A
28240 +#define OTG_CORE_REV_2_72a     0x4F54272A
28241 +#define OTG_CORE_REV_2_80a     0x4F54280A
28242 +#define OTG_CORE_REV_2_81a     0x4F54281A
28243 +#define OTG_CORE_REV_2_90a     0x4F54290A
28244 +#define OTG_CORE_REV_2_91a     0x4F54291A
28245 +#define OTG_CORE_REV_2_92a     0x4F54292A
28246 +#define OTG_CORE_REV_2_93a     0x4F54293A
28247 +#define OTG_CORE_REV_2_94a     0x4F54294A
28248 +#define OTG_CORE_REV_3_00a     0x4F54300A
28249 +
28250 +/**
28251 + * Information for each ISOC packet.
28252 + */
28253 +typedef struct iso_pkt_info {
28254 +       uint32_t offset;
28255 +       uint32_t length;
28256 +       int32_t status;
28257 +} iso_pkt_info_t;
28258 +
28259 +/**
28260 + * The <code>dwc_ep</code> structure represents the state of a single
28261 + * endpoint when acting in device mode. It contains the data items
28262 + * needed for an endpoint to be activated and transfer packets.
28263 + */
28264 +typedef struct dwc_ep {
28265 +       /** EP number used for register address lookup */
28266 +       uint8_t num;
28267 +       /** EP direction 0 = OUT */
28268 +       unsigned is_in:1;
28269 +       /** EP active. */
28270 +       unsigned active:1;
28271 +
28272 +       /**
28273 +        * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
28274 +        * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
28275 +       unsigned tx_fifo_num:4;
28276 +       /** EP type: 0 - Control, 1 - ISOC,      2 - BULK,      3 - INTR */
28277 +       unsigned type:2;
28278 +#define DWC_OTG_EP_TYPE_CONTROL           0
28279 +#define DWC_OTG_EP_TYPE_ISOC      1
28280 +#define DWC_OTG_EP_TYPE_BULK      2
28281 +#define DWC_OTG_EP_TYPE_INTR      3
28282 +
28283 +       /** DATA start PID for INTR and BULK EP */
28284 +       unsigned data_pid_start:1;
28285 +       /** Frame (even/odd) for ISOC EP */
28286 +       unsigned even_odd_frame:1;
28287 +       /** Max Packet bytes */
28288 +       unsigned maxpacket:11;
28289 +
28290 +       /** Max Transfer size */
28291 +       uint32_t maxxfer;
28292 +
28293 +       /** @name Transfer state */
28294 +       /** @{ */
28295 +
28296 +       /**
28297 +        * Pointer to the beginning of the transfer buffer -- do not modify
28298 +        * during transfer.
28299 +        */
28300 +
28301 +       dwc_dma_t dma_addr;
28302 +
28303 +       dwc_dma_t dma_desc_addr;
28304 +       dwc_otg_dev_dma_desc_t *desc_addr;
28305 +
28306 +       uint8_t *start_xfer_buff;
28307 +       /** pointer to the transfer buffer */
28308 +       uint8_t *xfer_buff;
28309 +       /** Number of bytes to transfer */
28310 +       unsigned xfer_len:19;
28311 +       /** Number of bytes transferred. */
28312 +       unsigned xfer_count:19;
28313 +       /** Sent ZLP */
28314 +       unsigned sent_zlp:1;
28315 +       /** Total len for control transfer */
28316 +       unsigned total_len:19;
28317 +
28318 +       /** stall clear flag */
28319 +       unsigned stall_clear_flag:1;
28320 +
28321 +       /** SETUP pkt cnt rollover flag for EP0 out*/
28322 +       unsigned stp_rollover;
28323 +
28324 +#ifdef DWC_UTE_CFI
28325 +       /* The buffer mode */
28326 +       data_buffer_mode_e buff_mode;
28327 +
28328 +       /* The chain of DMA descriptors.
28329 +        * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
28330 +        */
28331 +       dwc_otg_dma_desc_t *descs;
28332 +
28333 +       /* The DMA address of the descriptors chain start */
28334 +       dma_addr_t descs_dma_addr;
28335 +       /** This variable stores the length of the last enqueued request */
28336 +       uint32_t cfi_req_len;
28337 +#endif                         //DWC_UTE_CFI
28338 +
28339 +/** Max DMA Descriptor count for any EP */
28340 +#define MAX_DMA_DESC_CNT 256
28341 +       /** Allocated DMA Desc count */
28342 +       uint32_t desc_cnt;
28343 +
28344 +       /** bInterval */
28345 +       uint32_t bInterval;
28346 +       /** Next frame num to setup next ISOC transfer */
28347 +       uint32_t frame_num;
28348 +       /** Indicates SOF number overrun in DSTS */
28349 +       uint8_t frm_overrun;
28350 +
28351 +#ifdef DWC_UTE_PER_IO
28352 +       /** Next frame num for which will be setup DMA Desc */
28353 +       uint32_t xiso_frame_num;
28354 +       /** bInterval */
28355 +       uint32_t xiso_bInterval;
28356 +       /** Count of currently active transfers - shall be either 0 or 1 */
28357 +       int xiso_active_xfers;
28358 +       int xiso_queued_xfers;
28359 +#endif
28360 +#ifdef DWC_EN_ISOC
28361 +       /**
28362 +        * Variables specific for ISOC EPs
28363 +        *
28364 +        */
28365 +       /** DMA addresses of ISOC buffers */
28366 +       dwc_dma_t dma_addr0;
28367 +       dwc_dma_t dma_addr1;
28368 +
28369 +       dwc_dma_t iso_dma_desc_addr;
28370 +       dwc_otg_dev_dma_desc_t *iso_desc_addr;
28371 +
28372 +       /** pointer to the transfer buffers */
28373 +       uint8_t *xfer_buff0;
28374 +       uint8_t *xfer_buff1;
28375 +
28376 +       /** number of ISOC Buffer is processing */
28377 +       uint32_t proc_buf_num;
28378 +       /** Interval of ISOC Buffer processing */
28379 +       uint32_t buf_proc_intrvl;
28380 +       /** Data size for regular frame */
28381 +       uint32_t data_per_frame;
28382 +
28383 +       /* todo - pattern data support is to be implemented in the future */
28384 +       /** Data size for pattern frame */
28385 +       uint32_t data_pattern_frame;
28386 +       /** Frame number of pattern data */
28387 +       uint32_t sync_frame;
28388 +
28389 +       /** bInterval */
28390 +       uint32_t bInterval;
28391 +       /** ISO Packet number per frame */
28392 +       uint32_t pkt_per_frm;
28393 +       /** Next frame num for which will be setup DMA Desc */
28394 +       uint32_t next_frame;
28395 +       /** Number of packets per buffer processing */
28396 +       uint32_t pkt_cnt;
28397 +       /** Info for all isoc packets */
28398 +       iso_pkt_info_t *pkt_info;
28399 +       /** current pkt number */
28400 +       uint32_t cur_pkt;
28401 +       /** current pkt number */
28402 +       uint8_t *cur_pkt_addr;
28403 +       /** current pkt number */
28404 +       uint32_t cur_pkt_dma_addr;
28405 +#endif                         /* DWC_EN_ISOC */
28406 +
28407 +/** @} */
28408 +} dwc_ep_t;
28409 +
28410 +/*
28411 + * Reasons for halting a host channel.
28412 + */
28413 +typedef enum dwc_otg_halt_status {
28414 +       DWC_OTG_HC_XFER_NO_HALT_STATUS,
28415 +       DWC_OTG_HC_XFER_COMPLETE,
28416 +       DWC_OTG_HC_XFER_URB_COMPLETE,
28417 +       DWC_OTG_HC_XFER_ACK,
28418 +       DWC_OTG_HC_XFER_NAK,
28419 +       DWC_OTG_HC_XFER_NYET,
28420 +       DWC_OTG_HC_XFER_STALL,
28421 +       DWC_OTG_HC_XFER_XACT_ERR,
28422 +       DWC_OTG_HC_XFER_FRAME_OVERRUN,
28423 +       DWC_OTG_HC_XFER_BABBLE_ERR,
28424 +       DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
28425 +       DWC_OTG_HC_XFER_AHB_ERR,
28426 +       DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
28427 +       DWC_OTG_HC_XFER_URB_DEQUEUE
28428 +} dwc_otg_halt_status_e;
28429 +
28430 +/**
28431 + * Host channel descriptor. This structure represents the state of a single
28432 + * host channel when acting in host mode. It contains the data items needed to
28433 + * transfer packets to an endpoint via a host channel.
28434 + */
28435 +typedef struct dwc_hc {
28436 +       /** Host channel number used for register address lookup */
28437 +       uint8_t hc_num;
28438 +
28439 +       /** Device to access */
28440 +       unsigned dev_addr:7;
28441 +
28442 +       /** EP to access */
28443 +       unsigned ep_num:4;
28444 +
28445 +       /** EP direction. 0: OUT, 1: IN */
28446 +       unsigned ep_is_in:1;
28447 +
28448 +       /**
28449 +        * EP speed.
28450 +        * One of the following values:
28451 +        *      - DWC_OTG_EP_SPEED_LOW
28452 +        *      - DWC_OTG_EP_SPEED_FULL
28453 +        *      - DWC_OTG_EP_SPEED_HIGH
28454 +        */
28455 +       unsigned speed:2;
28456 +#define DWC_OTG_EP_SPEED_LOW   0
28457 +#define DWC_OTG_EP_SPEED_FULL  1
28458 +#define DWC_OTG_EP_SPEED_HIGH  2
28459 +
28460 +       /**
28461 +        * Endpoint type.
28462 +        * One of the following values:
28463 +        *      - DWC_OTG_EP_TYPE_CONTROL: 0
28464 +        *      - DWC_OTG_EP_TYPE_ISOC: 1
28465 +        *      - DWC_OTG_EP_TYPE_BULK: 2
28466 +        *      - DWC_OTG_EP_TYPE_INTR: 3
28467 +        */
28468 +       unsigned ep_type:2;
28469 +
28470 +       /** Max packet size in bytes */
28471 +       unsigned max_packet:11;
28472 +
28473 +       /**
28474 +        * PID for initial transaction.
28475 +        * 0: DATA0,<br>
28476 +        * 1: DATA2,<br>
28477 +        * 2: DATA1,<br>
28478 +        * 3: MDATA (non-Control EP),
28479 +        *        SETUP (Control EP)
28480 +        */
28481 +       unsigned data_pid_start:2;
28482 +#define DWC_OTG_HC_PID_DATA0 0
28483 +#define DWC_OTG_HC_PID_DATA2 1
28484 +#define DWC_OTG_HC_PID_DATA1 2
28485 +#define DWC_OTG_HC_PID_MDATA 3
28486 +#define DWC_OTG_HC_PID_SETUP 3
28487 +
28488 +       /** Number of periodic transactions per (micro)frame */
28489 +       unsigned multi_count:2;
28490 +
28491 +       /** @name Transfer State */
28492 +       /** @{ */
28493 +
28494 +       /** Pointer to the current transfer buffer position. */
28495 +       uint8_t *xfer_buff;
28496 +       /**
28497 +        * In Buffer DMA mode this buffer will be used
28498 +        * if xfer_buff is not DWORD aligned.
28499 +        */
28500 +       dwc_dma_t align_buff;
28501 +       /** Total number of bytes to transfer. */
28502 +       uint32_t xfer_len;
28503 +       /** Number of bytes transferred so far. */
28504 +       uint32_t xfer_count;
28505 +       /** Packet count at start of transfer.*/
28506 +       uint16_t start_pkt_count;
28507 +
28508 +       /**
28509 +        * Flag to indicate whether the transfer has been started. Set to 1 if
28510 +        * it has been started, 0 otherwise.
28511 +        */
28512 +       uint8_t xfer_started;
28513 +
28514 +       /**
28515 +        * Set to 1 to indicate that a PING request should be issued on this
28516 +        * channel. If 0, process normally.
28517 +        */
28518 +       uint8_t do_ping;
28519 +
28520 +       /**
28521 +        * Set to 1 to indicate that the error count for this transaction is
28522 +        * non-zero. Set to 0 if the error count is 0.
28523 +        */
28524 +       uint8_t error_state;
28525 +
28526 +       /**
28527 +        * Set to 1 to indicate that this channel should be halted the next
28528 +        * time a request is queued for the channel. This is necessary in
28529 +        * slave mode if no request queue space is available when an attempt
28530 +        * is made to halt the channel.
28531 +        */
28532 +       uint8_t halt_on_queue;
28533 +
28534 +       /**
28535 +        * Set to 1 if the host channel has been halted, but the core is not
28536 +        * finished flushing queued requests. Otherwise 0.
28537 +        */
28538 +       uint8_t halt_pending;
28539 +
28540 +       /**
28541 +        * Reason for halting the host channel.
28542 +        */
28543 +       dwc_otg_halt_status_e halt_status;
28544 +
28545 +       /*
28546 +        * Split settings for the host channel
28547 +        */
28548 +       uint8_t do_split;                  /**< Enable split for the channel */
28549 +       uint8_t complete_split;    /**< Enable complete split */
28550 +       uint8_t hub_addr;                  /**< Address of high speed hub */
28551 +
28552 +       uint8_t port_addr;                 /**< Port of the low/full speed device */
28553 +       /** Split transaction position
28554 +        * One of the following values:
28555 +        *        - DWC_HCSPLIT_XACTPOS_MID
28556 +        *        - DWC_HCSPLIT_XACTPOS_BEGIN
28557 +        *        - DWC_HCSPLIT_XACTPOS_END
28558 +        *        - DWC_HCSPLIT_XACTPOS_ALL */
28559 +       uint8_t xact_pos;
28560 +
28561 +       /** Set when the host channel does a short read. */
28562 +       uint8_t short_read;
28563 +
28564 +       /**
28565 +        * Number of requests issued for this channel since it was assigned to
28566 +        * the current transfer (not counting PINGs).
28567 +        */
28568 +       uint8_t requests;
28569 +
28570 +       /**
28571 +        * Queue Head for the transfer being processed by this channel.
28572 +        */
28573 +       struct dwc_otg_qh *qh;
28574 +
28575 +       /** @} */
28576 +
28577 +       /** Entry in list of host channels. */
28578 +        DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
28579 +
28580 +       /** @name Descriptor DMA support */
28581 +       /** @{ */
28582 +
28583 +       /** Number of Transfer Descriptors */
28584 +       uint16_t ntd;
28585 +
28586 +       /** Descriptor List DMA address */
28587 +       dwc_dma_t desc_list_addr;
28588 +
28589 +       /** Scheduling micro-frame bitmap. */
28590 +       uint8_t schinfo;
28591 +
28592 +       /** @} */
28593 +} dwc_hc_t;
28594 +
28595 +/**
28596 + * The following parameters may be specified when starting the module. These
28597 + * parameters define how the DWC_otg controller should be configured.
28598 + */
28599 +typedef struct dwc_otg_core_params {
28600 +       int32_t opt;
28601 +
28602 +       /**
28603 +        * Specifies the OTG capabilities. The driver will automatically
28604 +        * detect the value for this parameter if none is specified.
28605 +        * 0 - HNP and SRP capable (default)
28606 +        * 1 - SRP Only capable
28607 +        * 2 - No HNP/SRP capable
28608 +        */
28609 +       int32_t otg_cap;
28610 +
28611 +       /**
28612 +        * Specifies whether to use slave or DMA mode for accessing the data
28613 +        * FIFOs. The driver will automatically detect the value for this
28614 +        * parameter if none is specified.
28615 +        * 0 - Slave
28616 +        * 1 - DMA (default, if available)
28617 +        */
28618 +       int32_t dma_enable;
28619 +
28620 +       /**
28621 +        * When DMA mode is enabled specifies whether to use address DMA or DMA
28622 +        * Descriptor mode for accessing the data FIFOs in device mode. The driver
28623 +        * will automatically detect the value for this if none is specified.
28624 +        * 0 - address DMA
28625 +        * 1 - DMA Descriptor(default, if available)
28626 +        */
28627 +       int32_t dma_desc_enable;
28628 +       /** The DMA Burst size (applicable only for External DMA
28629 +        * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
28630 +        */
28631 +       int32_t dma_burst_size; /* Translate this to GAHBCFG values */
28632 +
28633 +       /**
28634 +        * Specifies the maximum speed of operation in host and device mode.
28635 +        * The actual speed depends on the speed of the attached device and
28636 +        * the value of phy_type. The actual speed depends on the speed of the
28637 +        * attached device.
28638 +        * 0 - High Speed (default)
28639 +        * 1 - Full Speed
28640 +        */
28641 +       int32_t speed;
28642 +       /** Specifies whether low power mode is supported when attached
28643 +        *      to a Full Speed or Low Speed device in host mode.
28644 +        * 0 - Don't support low power mode (default)
28645 +        * 1 - Support low power mode
28646 +        */
28647 +       int32_t host_support_fs_ls_low_power;
28648 +
28649 +       /** Specifies the PHY clock rate in low power mode when connected to a
28650 +        * Low Speed device in host mode. This parameter is applicable only if
28651 +        * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
28652 +        * then defaults to 6 MHZ otherwise 48 MHZ.
28653 +        *
28654 +        * 0 - 48 MHz
28655 +        * 1 - 6 MHz
28656 +        */
28657 +       int32_t host_ls_low_power_phy_clk;
28658 +
28659 +       /**
28660 +        * 0 - Use cC FIFO size parameters
28661 +        * 1 - Allow dynamic FIFO sizing (default)
28662 +        */
28663 +       int32_t enable_dynamic_fifo;
28664 +
28665 +       /** Total number of 4-byte words in the data FIFO memory. This
28666 +        * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
28667 +        * Tx FIFOs.
28668 +        * 32 to 32768 (default 8192)
28669 +        * Note: The total FIFO memory depth in the FPGA configuration is 8192.
28670 +        */
28671 +       int32_t data_fifo_size;
28672 +
28673 +       /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
28674 +        * FIFO sizing is enabled.
28675 +        * 16 to 32768 (default 1064)
28676 +        */
28677 +       int32_t dev_rx_fifo_size;
28678 +
28679 +       /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
28680 +        * when dynamic FIFO sizing is enabled.
28681 +        * 16 to 32768 (default 1024)
28682 +        */
28683 +       int32_t dev_nperio_tx_fifo_size;
28684 +
28685 +       /** Number of 4-byte words in each of the periodic Tx FIFOs in device
28686 +        * mode when dynamic FIFO sizing is enabled.
28687 +        * 4 to 768 (default 256)
28688 +        */
28689 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
28690 +
28691 +       /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
28692 +        * FIFO sizing is enabled.
28693 +        * 16 to 32768 (default 1024)
28694 +        */
28695 +       int32_t host_rx_fifo_size;
28696 +
28697 +       /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
28698 +        * when Dynamic FIFO sizing is enabled in the core.
28699 +        * 16 to 32768 (default 1024)
28700 +        */
28701 +       int32_t host_nperio_tx_fifo_size;
28702 +
28703 +       /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
28704 +        * FIFO sizing is enabled.
28705 +        * 16 to 32768 (default 1024)
28706 +        */
28707 +       int32_t host_perio_tx_fifo_size;
28708 +
28709 +       /** The maximum transfer size supported in bytes.
28710 +        * 2047 to 65,535  (default 65,535)
28711 +        */
28712 +       int32_t max_transfer_size;
28713 +
28714 +       /** The maximum number of packets in a transfer.
28715 +        * 15 to 511  (default 511)
28716 +        */
28717 +       int32_t max_packet_count;
28718 +
28719 +       /** The number of host channel registers to use.
28720 +        * 1 to 16 (default 12)
28721 +        * Note: The FPGA configuration supports a maximum of 12 host channels.
28722 +        */
28723 +       int32_t host_channels;
28724 +
28725 +       /** The number of endpoints in addition to EP0 available for device
28726 +        * mode operations.
28727 +        * 1 to 15 (default 6 IN and OUT)
28728 +        * Note: The FPGA configuration supports a maximum of 6 IN and OUT
28729 +        * endpoints in addition to EP0.
28730 +        */
28731 +       int32_t dev_endpoints;
28732 +
28733 +               /**
28734 +                * Specifies the type of PHY interface to use. By default, the driver
28735 +                * will automatically detect the phy_type.
28736 +                *
28737 +                * 0 - Full Speed PHY
28738 +                * 1 - UTMI+ (default)
28739 +                * 2 - ULPI
28740 +                */
28741 +       int32_t phy_type;
28742 +
28743 +       /**
28744 +        * Specifies the UTMI+ Data Width. This parameter is
28745 +        * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
28746 +        * PHY_TYPE, this parameter indicates the data width between
28747 +        * the MAC and the ULPI Wrapper.) Also, this parameter is
28748 +        * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
28749 +        * to "8 and 16 bits", meaning that the core has been
28750 +        * configured to work at either data path width.
28751 +        *
28752 +        * 8 or 16 bits (default 16)
28753 +        */
28754 +       int32_t phy_utmi_width;
28755 +
28756 +       /**
28757 +        * Specifies whether the ULPI operates at double or single
28758 +        * data rate. This parameter is only applicable if PHY_TYPE is
28759 +        * ULPI.
28760 +        *
28761 +        * 0 - single data rate ULPI interface with 8 bit wide data
28762 +        * bus (default)
28763 +        * 1 - double data rate ULPI interface with 4 bit wide data
28764 +        * bus
28765 +        */
28766 +       int32_t phy_ulpi_ddr;
28767 +
28768 +       /**
28769 +        * Specifies whether to use the internal or external supply to
28770 +        * drive the vbus with a ULPI phy.
28771 +        */
28772 +       int32_t phy_ulpi_ext_vbus;
28773 +
28774 +       /**
28775 +        * Specifies whether to use the I2Cinterface for full speed PHY. This
28776 +        * parameter is only applicable if PHY_TYPE is FS.
28777 +        * 0 - No (default)
28778 +        * 1 - Yes
28779 +        */
28780 +       int32_t i2c_enable;
28781 +
28782 +       int32_t ulpi_fs_ls;
28783 +
28784 +       int32_t ts_dline;
28785 +
28786 +       /**
28787 +        * Specifies whether dedicated transmit FIFOs are
28788 +        * enabled for non periodic IN endpoints in device mode
28789 +        * 0 - No
28790 +        * 1 - Yes
28791 +        */
28792 +       int32_t en_multiple_tx_fifo;
28793 +
28794 +       /** Number of 4-byte words in each of the Tx FIFOs in device
28795 +        * mode when dynamic FIFO sizing is enabled.
28796 +        * 4 to 768 (default 256)
28797 +        */
28798 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
28799 +
28800 +       /** Thresholding enable flag-
28801 +        * bit 0 - enable non-ISO Tx thresholding
28802 +        * bit 1 - enable ISO Tx thresholding
28803 +        * bit 2 - enable Rx thresholding
28804 +        */
28805 +       uint32_t thr_ctl;
28806 +
28807 +       /** Thresholding length for Tx
28808 +        *      FIFOs in 32 bit DWORDs
28809 +        */
28810 +       uint32_t tx_thr_length;
28811 +
28812 +       /** Thresholding length for Rx
28813 +        *      FIFOs in 32 bit DWORDs
28814 +        */
28815 +       uint32_t rx_thr_length;
28816 +
28817 +       /**
28818 +        * Specifies whether LPM (Link Power Management) support is enabled
28819 +        */
28820 +       int32_t lpm_enable;
28821 +
28822 +       /** Per Transfer Interrupt
28823 +        *      mode enable flag
28824 +        * 1 - Enabled
28825 +        * 0 - Disabled
28826 +        */
28827 +       int32_t pti_enable;
28828 +
28829 +       /** Multi Processor Interrupt
28830 +        *      mode enable flag
28831 +        * 1 - Enabled
28832 +        * 0 - Disabled
28833 +        */
28834 +       int32_t mpi_enable;
28835 +
28836 +       /** IS_USB Capability
28837 +        * 1 - Enabled
28838 +        * 0 - Disabled
28839 +        */
28840 +       int32_t ic_usb_cap;
28841 +
28842 +       /** AHB Threshold Ratio
28843 +        * 2'b00 AHB Threshold =        MAC Threshold
28844 +        * 2'b01 AHB Threshold = 1/2    MAC Threshold
28845 +        * 2'b10 AHB Threshold = 1/4    MAC Threshold
28846 +        * 2'b11 AHB Threshold = 1/8    MAC Threshold
28847 +        */
28848 +       int32_t ahb_thr_ratio;
28849 +
28850 +       /** ADP Support
28851 +        * 1 - Enabled
28852 +        * 0 - Disabled
28853 +        */
28854 +       int32_t adp_supp_enable;
28855 +
28856 +       /** HFIR Reload Control
28857 +        * 0 - The HFIR cannot be reloaded dynamically.
28858 +        * 1 - Allow dynamic reloading of the HFIR register during runtime.
28859 +        */
28860 +       int32_t reload_ctl;
28861 +
28862 +       /** DCFG: Enable device Out NAK
28863 +        * 0 - The core does not set NAK after Bulk Out transfer complete.
28864 +        * 1 - The core sets NAK after Bulk OUT transfer complete.
28865 +        */
28866 +       int32_t dev_out_nak;
28867 +
28868 +       /** DCFG: Enable Continue on BNA
28869 +        * After receiving BNA interrupt the core disables the endpoint,when the
28870 +        * endpoint is re-enabled by the application the core starts processing
28871 +        * 0 - from the DOEPDMA descriptor
28872 +        * 1 - from the descriptor which received the BNA.
28873 +        */
28874 +       int32_t cont_on_bna;
28875 +
28876 +       /** GAHBCFG: AHB Single Support
28877 +        * This bit when programmed supports SINGLE transfers for remainder
28878 +        * data in a transfer for DMA mode of operation.
28879 +        * 0 - in this case the remainder data will be sent using INCR burst size.
28880 +        * 1 - in this case the remainder data will be sent using SINGLE burst size.
28881 +        */
28882 +       int32_t ahb_single;
28883 +
28884 +       /** Core Power down mode
28885 +        * 0 - No Power Down is enabled
28886 +        * 1 - Reserved
28887 +        * 2 - Complete Power Down (Hibernation)
28888 +        */
28889 +       int32_t power_down;
28890 +
28891 +       /** OTG revision supported
28892 +        * 0 - OTG 1.3 revision
28893 +        * 1 - OTG 2.0 revision
28894 +        */
28895 +       int32_t otg_ver;
28896 +
28897 +} dwc_otg_core_params_t;
28898 +
28899 +#ifdef DEBUG
28900 +struct dwc_otg_core_if;
28901 +typedef struct hc_xfer_info {
28902 +       struct dwc_otg_core_if *core_if;
28903 +       dwc_hc_t *hc;
28904 +} hc_xfer_info_t;
28905 +#endif
28906 +
28907 +typedef struct ep_xfer_info {
28908 +       struct dwc_otg_core_if *core_if;
28909 +       dwc_ep_t *ep;
28910 +       uint8_t state;
28911 +} ep_xfer_info_t;
28912 +/*
28913 + * Device States
28914 + */
28915 +typedef enum dwc_otg_lx_state {
28916 +       /** On state */
28917 +       DWC_OTG_L0,
28918 +       /** LPM sleep state*/
28919 +       DWC_OTG_L1,
28920 +       /** USB suspend state*/
28921 +       DWC_OTG_L2,
28922 +       /** Off state*/
28923 +       DWC_OTG_L3
28924 +} dwc_otg_lx_state_e;
28925 +
28926 +struct dwc_otg_global_regs_backup {
28927 +       uint32_t gotgctl_local;
28928 +       uint32_t gintmsk_local;
28929 +       uint32_t gahbcfg_local;
28930 +       uint32_t gusbcfg_local;
28931 +       uint32_t grxfsiz_local;
28932 +       uint32_t gnptxfsiz_local;
28933 +#ifdef CONFIG_USB_DWC_OTG_LPM
28934 +       uint32_t glpmcfg_local;
28935 +#endif
28936 +       uint32_t gi2cctl_local;
28937 +       uint32_t hptxfsiz_local;
28938 +       uint32_t pcgcctl_local;
28939 +       uint32_t gdfifocfg_local;
28940 +       uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];
28941 +       uint32_t gpwrdn_local;
28942 +       uint32_t xhib_pcgcctl;
28943 +       uint32_t xhib_gpwrdn;
28944 +};
28945 +
28946 +struct dwc_otg_host_regs_backup {
28947 +       uint32_t hcfg_local;
28948 +       uint32_t haintmsk_local;
28949 +       uint32_t hcintmsk_local[MAX_EPS_CHANNELS];
28950 +       uint32_t hprt0_local;
28951 +       uint32_t hfir_local;
28952 +};
28953 +
28954 +struct dwc_otg_dev_regs_backup {
28955 +       uint32_t dcfg;
28956 +       uint32_t dctl;
28957 +       uint32_t daintmsk;
28958 +       uint32_t diepmsk;
28959 +       uint32_t doepmsk;
28960 +       uint32_t diepctl[MAX_EPS_CHANNELS];
28961 +       uint32_t dieptsiz[MAX_EPS_CHANNELS];
28962 +       uint32_t diepdma[MAX_EPS_CHANNELS];
28963 +};
28964 +/**
28965 + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
28966 + * the DWC_otg controller acting in either host or device mode. It
28967 + * represents the programming view of the controller as a whole.
28968 + */
28969 +struct dwc_otg_core_if {
28970 +       /** Parameters that define how the core should be configured.*/
28971 +       dwc_otg_core_params_t *core_params;
28972 +
28973 +       /** Core Global registers starting at offset 000h. */
28974 +       dwc_otg_core_global_regs_t *core_global_regs;
28975 +
28976 +       /** Device-specific information */
28977 +       dwc_otg_dev_if_t *dev_if;
28978 +       /** Host-specific information */
28979 +       dwc_otg_host_if_t *host_if;
28980 +
28981 +       /** Value from SNPSID register */
28982 +       uint32_t snpsid;
28983 +
28984 +       /*
28985 +        * Set to 1 if the core PHY interface bits in USBCFG have been
28986 +        * initialized.
28987 +        */
28988 +       uint8_t phy_init_done;
28989 +
28990 +       /*
28991 +        * SRP Success flag, set by srp success interrupt in FS I2C mode
28992 +        */
28993 +       uint8_t srp_success;
28994 +       uint8_t srp_timer_started;
28995 +       /** Timer for SRP. If it expires before SRP is successful
28996 +        * clear the SRP. */
28997 +       dwc_timer_t *srp_timer;
28998 +
28999 +#ifdef DWC_DEV_SRPCAP
29000 +       /* This timer is needed to power on the hibernated host core if SRP is not
29001 +        * initiated on connected SRP capable device for limited period of time
29002 +        */
29003 +       uint8_t pwron_timer_started;
29004 +       dwc_timer_t *pwron_timer;
29005 +#endif
29006 +       /* Common configuration information */
29007 +       /** Power and Clock Gating Control Register */
29008 +       volatile uint32_t *pcgcctl;
29009 +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
29010 +
29011 +       /** Push/pop addresses for endpoints or host channels.*/
29012 +       uint32_t *data_fifo[MAX_EPS_CHANNELS];
29013 +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
29014 +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
29015 +
29016 +       /** Total RAM for FIFOs (Bytes) */
29017 +       uint16_t total_fifo_size;
29018 +       /** Size of Rx FIFO (Bytes) */
29019 +       uint16_t rx_fifo_size;
29020 +       /** Size of Non-periodic Tx FIFO (Bytes) */
29021 +       uint16_t nperio_tx_fifo_size;
29022 +
29023 +       /** 1 if DMA is enabled, 0 otherwise. */
29024 +       uint8_t dma_enable;
29025 +
29026 +       /** 1 if DMA descriptor is enabled, 0 otherwise. */
29027 +       uint8_t dma_desc_enable;
29028 +
29029 +       /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
29030 +       uint8_t pti_enh_enable;
29031 +
29032 +       /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
29033 +       uint8_t multiproc_int_enable;
29034 +
29035 +       /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
29036 +       uint8_t en_multiple_tx_fifo;
29037 +
29038 +       /** Set to 1 if multiple packets of a high-bandwidth transfer is in
29039 +        * process of being queued */
29040 +       uint8_t queuing_high_bandwidth;
29041 +
29042 +       /** Hardware Configuration -- stored here for convenience.*/
29043 +       hwcfg1_data_t hwcfg1;
29044 +       hwcfg2_data_t hwcfg2;
29045 +       hwcfg3_data_t hwcfg3;
29046 +       hwcfg4_data_t hwcfg4;
29047 +       fifosize_data_t hptxfsiz;
29048 +
29049 +       /** Host and Device Configuration -- stored here for convenience.*/
29050 +       hcfg_data_t hcfg;
29051 +       dcfg_data_t dcfg;
29052 +
29053 +       /** The operational State, during transations
29054 +        * (a_host>>a_peripherial and b_device=>b_host) this may not
29055 +        * match the core but allows the software to determine
29056 +        * transitions.
29057 +        */
29058 +       uint8_t op_state;
29059 +
29060 +       /**
29061 +        * Set to 1 if the HCD needs to be restarted on a session request
29062 +        * interrupt. This is required if no connector ID status change has
29063 +        * occurred since the HCD was last disconnected.
29064 +        */
29065 +       uint8_t restart_hcd_on_session_req;
29066 +
29067 +       /** HCD callbacks */
29068 +       /** A-Device is a_host */
29069 +#define A_HOST         (1)
29070 +       /** A-Device is a_suspend */
29071 +#define A_SUSPEND      (2)
29072 +       /** A-Device is a_peripherial */
29073 +#define A_PERIPHERAL   (3)
29074 +       /** B-Device is operating as a Peripheral. */
29075 +#define B_PERIPHERAL   (4)
29076 +       /** B-Device is operating as a Host. */
29077 +#define B_HOST         (5)
29078 +
29079 +       /** HCD callbacks */
29080 +       struct dwc_otg_cil_callbacks *hcd_cb;
29081 +       /** PCD callbacks */
29082 +       struct dwc_otg_cil_callbacks *pcd_cb;
29083 +
29084 +       /** Device mode Periodic Tx FIFO Mask */
29085 +       uint32_t p_tx_msk;
29086 +       /** Device mode Periodic Tx FIFO Mask */
29087 +       uint32_t tx_msk;
29088 +
29089 +       /** Workqueue object used for handling several interrupts */
29090 +       dwc_workq_t *wq_otg;
29091 +
29092 +       /** Timer object used for handling "Wakeup Detected" Interrupt */
29093 +       dwc_timer_t *wkp_timer;
29094 +       /** This arrays used for debug purposes for DEV OUT NAK enhancement */
29095 +       uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];
29096 +       ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];
29097 +       dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];
29098 +#ifdef DEBUG
29099 +       uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
29100 +
29101 +       hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
29102 +       dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
29103 +
29104 +       uint32_t hfnum_7_samples;
29105 +       uint64_t hfnum_7_frrem_accum;
29106 +       uint32_t hfnum_0_samples;
29107 +       uint64_t hfnum_0_frrem_accum;
29108 +       uint32_t hfnum_other_samples;
29109 +       uint64_t hfnum_other_frrem_accum;
29110 +#endif
29111 +
29112 +#ifdef DWC_UTE_CFI
29113 +       uint16_t pwron_rxfsiz;
29114 +       uint16_t pwron_gnptxfsiz;
29115 +       uint16_t pwron_txfsiz[15];
29116 +
29117 +       uint16_t init_rxfsiz;
29118 +       uint16_t init_gnptxfsiz;
29119 +       uint16_t init_txfsiz[15];
29120 +#endif
29121 +
29122 +       /** Lx state of device */
29123 +       dwc_otg_lx_state_e lx_state;
29124 +
29125 +       /** Saved Core Global registers */
29126 +       struct dwc_otg_global_regs_backup *gr_backup;
29127 +       /** Saved Host registers */
29128 +       struct dwc_otg_host_regs_backup *hr_backup;
29129 +       /** Saved Device registers */
29130 +       struct dwc_otg_dev_regs_backup *dr_backup;
29131 +
29132 +       /** Power Down Enable */
29133 +       uint32_t power_down;
29134 +
29135 +       /** ADP support Enable */
29136 +       uint32_t adp_enable;
29137 +
29138 +       /** ADP structure object */
29139 +       dwc_otg_adp_t adp;
29140 +
29141 +       /** hibernation/suspend flag */
29142 +       int hibernation_suspend;
29143 +
29144 +       /** Device mode extended hibernation flag */
29145 +       int xhib;
29146 +
29147 +       /** OTG revision supported */
29148 +       uint32_t otg_ver;
29149 +
29150 +       /** OTG status flag used for HNP polling */
29151 +       uint8_t otg_sts;
29152 +
29153 +       /** Pointer to either hcd->lock or pcd->lock */
29154 +       dwc_spinlock_t *lock;
29155 +
29156 +       /** Start predict NextEP based on Learning Queue if equal 1,
29157 +        * also used as counter of disabled NP IN EP's */
29158 +       uint8_t start_predict;
29159 +
29160 +       /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and
29161 +        * active, 0xff otherwise */
29162 +       uint8_t nextep_seq[MAX_EPS_CHANNELS];
29163 +
29164 +       /** Index of fisrt EP in nextep_seq array which should be re-enabled **/
29165 +       uint8_t first_in_nextep_seq;
29166 +
29167 +       /** Frame number while entering to ISR - needed for ISOCs **/
29168 +       uint32_t frame_num;
29169 +
29170 +};
29171 +
29172 +#ifdef DEBUG
29173 +/*
29174 + * This function is called when transfer is timed out.
29175 + */
29176 +extern void hc_xfer_timeout(void *ptr);
29177 +#endif
29178 +
29179 +/*
29180 + * This function is called when transfer is timed out on endpoint.
29181 + */
29182 +extern void ep_xfer_timeout(void *ptr);
29183 +
29184 +/*
29185 + * The following functions are functions for works
29186 + * using during handling some interrupts
29187 + */
29188 +extern void w_conn_id_status_change(void *p);
29189 +
29190 +extern void w_wakeup_detected(void *p);
29191 +
29192 +/** Saves global register values into system memory. */
29193 +extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);
29194 +/** Saves device register values into system memory. */
29195 +extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);
29196 +/** Saves host register values into system memory. */
29197 +extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);
29198 +/** Restore global register values. */
29199 +extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);
29200 +/** Restore host register values. */
29201 +extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);
29202 +/** Restore device register values. */
29203 +extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,
29204 +                                   int rem_wakeup);
29205 +extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);
29206 +extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,
29207 +                                 int is_host);
29208 +
29209 +extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
29210 +                                           int restore_mode, int reset);
29211 +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
29212 +                                             int rem_wakeup, int reset);
29213 +
29214 +/*
29215 + * The following functions support initialization of the CIL driver component
29216 + * and the DWC_otg controller.
29217 + */
29218 +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
29219 +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
29220 +
29221 +/** @name Device CIL Functions
29222 + * The following functions support managing the DWC_otg controller in device
29223 + * mode.
29224 + */
29225 +/**@{*/
29226 +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
29227 +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
29228 +                                     uint32_t * _dest);
29229 +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
29230 +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29231 +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29232 +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29233 +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
29234 +                                     dwc_ep_t * _ep);
29235 +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
29236 +                                        dwc_ep_t * _ep);
29237 +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
29238 +                                      dwc_ep_t * _ep);
29239 +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
29240 +                                         dwc_ep_t * _ep);
29241 +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
29242 +                                   dwc_ep_t * _ep, int _dma);
29243 +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
29244 +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
29245 +                                  dwc_ep_t * _ep);
29246 +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
29247 +
29248 +#ifdef DWC_EN_ISOC
29249 +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
29250 +                                             dwc_ep_t * ep);
29251 +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
29252 +                                             dwc_ep_t * ep);
29253 +#endif /* DWC_EN_ISOC */
29254 +/**@}*/
29255 +
29256 +/** @name Host CIL Functions
29257 + * The following functions support managing the DWC_otg controller in host
29258 + * mode.
29259 + */
29260 +/**@{*/
29261 +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29262 +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
29263 +                           dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
29264 +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29265 +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
29266 +                                     dwc_hc_t * _hc);
29267 +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
29268 +                                       dwc_hc_t * _hc);
29269 +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
29270 +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
29271 +                                   dwc_hc_t * _hc);
29272 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
29273 +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
29274 +
29275 +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,
29276 +                                          dwc_hc_t * hc);
29277 +
29278 +extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);
29279 +
29280 +/* Macro used to clear one channel interrupt */
29281 +#define clear_hc_int(_hc_regs_, _intr_) \
29282 +do { \
29283 +       hcint_data_t hcint_clear = {.d32 = 0}; \
29284 +       hcint_clear.b._intr_ = 1; \
29285 +       DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \
29286 +} while (0)
29287 +
29288 +/*
29289 + * Macro used to disable one channel interrupt. Channel interrupts are
29290 + * disabled when the channel is halted or released by the interrupt handler.
29291 + * There is no need to handle further interrupts of that type until the
29292 + * channel is re-assigned. In fact, subsequent handling may cause crashes
29293 + * because the channel structures are cleaned up when the channel is released.
29294 + */
29295 +#define disable_hc_int(_hc_regs_, _intr_) \
29296 +do { \
29297 +       hcintmsk_data_t hcintmsk = {.d32 = 0}; \
29298 +       hcintmsk.b._intr_ = 1; \
29299 +       DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
29300 +} while (0)
29301 +
29302 +/**
29303 + * This function Reads HPRT0 in preparation to modify. It keeps the
29304 + * WC bits 0 so that if they are read as 1, they won't clear when you
29305 + * write it back
29306 + */
29307 +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
29308 +{
29309 +       hprt0_data_t hprt0;
29310 +       hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);
29311 +       hprt0.b.prtena = 0;
29312 +       hprt0.b.prtconndet = 0;
29313 +       hprt0.b.prtenchng = 0;
29314 +       hprt0.b.prtovrcurrchng = 0;
29315 +       return hprt0.d32;
29316 +}
29317 +
29318 +/**@}*/
29319 +
29320 +/** @name Common CIL Functions
29321 + * The following functions support managing the DWC_otg controller in either
29322 + * device or host mode.
29323 + */
29324 +/**@{*/
29325 +
29326 +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
29327 +                               uint8_t * dest, uint16_t bytes);
29328 +
29329 +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
29330 +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
29331 +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
29332 +
29333 +/**
29334 + * This function returns the Core Interrupt register.
29335 + */
29336 +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
29337 +{
29338 +       return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
29339 +               DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
29340 +}
29341 +
29342 +/**
29343 + * This function returns the OTG Interrupt register.
29344 + */
29345 +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
29346 +{
29347 +       return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));
29348 +}
29349 +
29350 +/**
29351 + * This function reads the Device All Endpoints Interrupt register and
29352 + * returns the IN endpoint interrupt bits.
29353 + */
29354 +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
29355 +                                                      core_if)
29356 +{
29357 +
29358 +       uint32_t v;
29359 +
29360 +       if (core_if->multiproc_int_enable) {
29361 +               v = DWC_READ_REG32(&core_if->dev_if->
29362 +                                  dev_global_regs->deachint) &
29363 +                   DWC_READ_REG32(&core_if->
29364 +                                  dev_if->dev_global_regs->deachintmsk);
29365 +       } else {
29366 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29367 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29368 +       }
29369 +       return (v & 0xffff);
29370 +}
29371 +
29372 +/**
29373 + * This function reads the Device All Endpoints Interrupt register and
29374 + * returns the OUT endpoint interrupt bits.
29375 + */
29376 +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
29377 +                                                       core_if)
29378 +{
29379 +       uint32_t v;
29380 +
29381 +       if (core_if->multiproc_int_enable) {
29382 +               v = DWC_READ_REG32(&core_if->dev_if->
29383 +                                  dev_global_regs->deachint) &
29384 +                   DWC_READ_REG32(&core_if->
29385 +                                  dev_if->dev_global_regs->deachintmsk);
29386 +       } else {
29387 +               v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
29388 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
29389 +       }
29390 +
29391 +       return ((v & 0xffff0000) >> 16);
29392 +}
29393 +
29394 +/**
29395 + * This function returns the Device IN EP Interrupt register
29396 + */
29397 +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
29398 +                                                  dwc_ep_t * ep)
29399 +{
29400 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
29401 +       uint32_t v, msk, emp;
29402 +
29403 +       if (core_if->multiproc_int_enable) {
29404 +               msk =
29405 +                   DWC_READ_REG32(&dev_if->
29406 +                                  dev_global_regs->diepeachintmsk[ep->num]);
29407 +               emp =
29408 +                   DWC_READ_REG32(&dev_if->
29409 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29410 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29411 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29412 +       } else {
29413 +               msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
29414 +               emp =
29415 +                   DWC_READ_REG32(&dev_if->
29416 +                                  dev_global_regs->dtknqr4_fifoemptymsk);
29417 +               msk |= ((emp >> ep->num) & 0x1) << 7;
29418 +               v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
29419 +       }
29420 +
29421 +       return v;
29422 +}
29423 +
29424 +/**
29425 + * This function returns the Device OUT EP Interrupt register
29426 + */
29427 +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
29428 +                                                   _core_if, dwc_ep_t * _ep)
29429 +{
29430 +       dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
29431 +       uint32_t v;
29432 +       doepmsk_data_t msk = {.d32 = 0 };
29433 +
29434 +       if (_core_if->multiproc_int_enable) {
29435 +               msk.d32 =
29436 +                   DWC_READ_REG32(&dev_if->
29437 +                                  dev_global_regs->doepeachintmsk[_ep->num]);
29438 +               if (_core_if->pti_enh_enable) {
29439 +                       msk.b.pktdrpsts = 1;
29440 +               }
29441 +               v = DWC_READ_REG32(&dev_if->
29442 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29443 +       } else {
29444 +               msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
29445 +               if (_core_if->pti_enh_enable) {
29446 +                       msk.b.pktdrpsts = 1;
29447 +               }
29448 +               v = DWC_READ_REG32(&dev_if->
29449 +                                  out_ep_regs[_ep->num]->doepint) & msk.d32;
29450 +       }
29451 +       return v;
29452 +}
29453 +
29454 +/**
29455 + * This function returns the Host All Channel Interrupt register
29456 + */
29457 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
29458 +                                                          _core_if)
29459 +{
29460 +       return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));
29461 +}
29462 +
29463 +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
29464 +                                                     _core_if, dwc_hc_t * _hc)
29465 +{
29466 +       return (DWC_READ_REG32
29467 +               (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
29468 +}
29469 +
29470 +/**
29471 + * This function returns the mode of the operation, host or device.
29472 + *
29473 + * @return 0 - Device Mode, 1 - Host Mode
29474 + */
29475 +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
29476 +{
29477 +       return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
29478 +}
29479 +
29480 +/**@}*/
29481 +
29482 +/**
29483 + * DWC_otg CIL callback structure. This structure allows the HCD and
29484 + * PCD to register functions used for starting and stopping the PCD
29485 + * and HCD for role change on for a DRD.
29486 + */
29487 +typedef struct dwc_otg_cil_callbacks {
29488 +       /** Start function for role change */
29489 +       int (*start) (void *_p);
29490 +       /** Stop Function for role change */
29491 +       int (*stop) (void *_p);
29492 +       /** Disconnect Function for role change */
29493 +       int (*disconnect) (void *_p);
29494 +       /** Resume/Remote wakeup Function */
29495 +       int (*resume_wakeup) (void *_p);
29496 +       /** Suspend function */
29497 +       int (*suspend) (void *_p);
29498 +       /** Session Start (SRP) */
29499 +       int (*session_start) (void *_p);
29500 +#ifdef CONFIG_USB_DWC_OTG_LPM
29501 +       /** Sleep (switch to L0 state) */
29502 +       int (*sleep) (void *_p);
29503 +#endif
29504 +       /** Pointer passed to start() and stop() */
29505 +       void *p;
29506 +} dwc_otg_cil_callbacks_t;
29507 +
29508 +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
29509 +                                              dwc_otg_cil_callbacks_t * _cb,
29510 +                                              void *_p);
29511 +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
29512 +                                              dwc_otg_cil_callbacks_t * _cb,
29513 +                                              void *_p);
29514 +
29515 +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);
29516 +
29517 +//////////////////////////////////////////////////////////////////////
29518 +/** Start the HCD.  Helper function for using the HCD callbacks.
29519 + *
29520 + * @param core_if Programming view of DWC_otg controller.
29521 + */
29522 +static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)
29523 +{
29524 +       if (core_if->hcd_cb && core_if->hcd_cb->start) {
29525 +               core_if->hcd_cb->start(core_if->hcd_cb->p);
29526 +       }
29527 +}
29528 +
29529 +/** Stop the HCD.  Helper function for using the HCD callbacks.
29530 + *
29531 + * @param core_if Programming view of DWC_otg controller.
29532 + */
29533 +static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)
29534 +{
29535 +       if (core_if->hcd_cb && core_if->hcd_cb->stop) {
29536 +               core_if->hcd_cb->stop(core_if->hcd_cb->p);
29537 +       }
29538 +}
29539 +
29540 +/** Disconnect the HCD.  Helper function for using the HCD callbacks.
29541 + *
29542 + * @param core_if Programming view of DWC_otg controller.
29543 + */
29544 +static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)
29545 +{
29546 +       if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
29547 +               core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
29548 +       }
29549 +}
29550 +
29551 +/** Inform the HCD the a New Session has begun.  Helper function for
29552 + * using the HCD callbacks.
29553 + *
29554 + * @param core_if Programming view of DWC_otg controller.
29555 + */
29556 +static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)
29557 +{
29558 +       if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
29559 +               core_if->hcd_cb->session_start(core_if->hcd_cb->p);
29560 +       }
29561 +}
29562 +
29563 +#ifdef CONFIG_USB_DWC_OTG_LPM
29564 +/**
29565 + * Inform the HCD about LPM sleep.
29566 + * Helper function for using the HCD callbacks.
29567 + *
29568 + * @param core_if Programming view of DWC_otg controller.
29569 + */
29570 +static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)
29571 +{
29572 +       if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
29573 +               core_if->hcd_cb->sleep(core_if->hcd_cb->p);
29574 +       }
29575 +}
29576 +#endif
29577 +
29578 +/** Resume the HCD.  Helper function for using the HCD callbacks.
29579 + *
29580 + * @param core_if Programming view of DWC_otg controller.
29581 + */
29582 +static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)
29583 +{
29584 +       if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
29585 +               core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
29586 +       }
29587 +}
29588 +
29589 +/** Start the PCD.  Helper function for using the PCD callbacks.
29590 + *
29591 + * @param core_if Programming view of DWC_otg controller.
29592 + */
29593 +static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)
29594 +{
29595 +       if (core_if->pcd_cb && core_if->pcd_cb->start) {
29596 +               core_if->pcd_cb->start(core_if->pcd_cb->p);
29597 +       }
29598 +}
29599 +
29600 +/** Stop the PCD.  Helper function for using the PCD callbacks.
29601 + *
29602 + * @param core_if Programming view of DWC_otg controller.
29603 + */
29604 +static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)
29605 +{
29606 +       if (core_if->pcd_cb && core_if->pcd_cb->stop) {
29607 +               core_if->pcd_cb->stop(core_if->pcd_cb->p);
29608 +       }
29609 +}
29610 +
29611 +/** Suspend the PCD.  Helper function for using the PCD callbacks.
29612 + *
29613 + * @param core_if Programming view of DWC_otg controller.
29614 + */
29615 +static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)
29616 +{
29617 +       if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
29618 +               core_if->pcd_cb->suspend(core_if->pcd_cb->p);
29619 +       }
29620 +}
29621 +
29622 +/** Resume the PCD.  Helper function for using the PCD callbacks.
29623 + *
29624 + * @param core_if Programming view of DWC_otg controller.
29625 + */
29626 +static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)
29627 +{
29628 +       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
29629 +               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
29630 +       }
29631 +}
29632 +
29633 +//////////////////////////////////////////////////////////////////////
29634 +
29635 +#endif
29636 --- /dev/null
29637 +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
29638 @@ -0,0 +1,1563 @@
29639 +/* ==========================================================================
29640 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
29641 + * $Revision: #32 $
29642 + * $Date: 2012/08/10 $
29643 + * $Change: 2047372 $
29644 + *
29645 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
29646 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
29647 + * otherwise expressly agreed to in writing between Synopsys and you.
29648 + *
29649 + * The Software IS NOT an item of Licensed Software or Licensed Product under
29650 + * any End User Software License Agreement or Agreement for Licensed Product
29651 + * with Synopsys or any supplement thereto. You are permitted to use and
29652 + * redistribute this Software in source and binary forms, with or without
29653 + * modification, provided that redistributions of source code must retain this
29654 + * notice. You may not view, use, disclose, copy or distribute this file or
29655 + * any information contained herein except pursuant to this license grant from
29656 + * Synopsys. If you do not agree with this notice, including the disclaimer
29657 + * below, then you are not authorized to use the Software.
29658 + *
29659 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
29660 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29661 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29662 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
29663 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29664 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29665 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29666 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29667 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29668 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29669 + * DAMAGE.
29670 + * ========================================================================== */
29671 +
29672 +/** @file
29673 + *
29674 + * The Core Interface Layer provides basic services for accessing and
29675 + * managing the DWC_otg hardware. These services are used by both the
29676 + * Host Controller Driver and the Peripheral Controller Driver.
29677 + *
29678 + * This file contains the Common Interrupt handlers.
29679 + */
29680 +#include "dwc_os.h"
29681 +#include "dwc_otg_regs.h"
29682 +#include "dwc_otg_cil.h"
29683 +#include "dwc_otg_driver.h"
29684 +#include "dwc_otg_pcd.h"
29685 +#include "dwc_otg_hcd.h"
29686 +
29687 +#ifdef DEBUG
29688 +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
29689 +{
29690 +       return (core_if->op_state == A_HOST ? "a_host" :
29691 +               (core_if->op_state == A_SUSPEND ? "a_suspend" :
29692 +                (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
29693 +                 (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
29694 +                  (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
29695 +}
29696 +#endif
29697 +
29698 +/** This function will log a debug message
29699 + *
29700 + * @param core_if Programming view of DWC_otg controller.
29701 + */
29702 +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
29703 +{
29704 +       gintsts_data_t gintsts;
29705 +       DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
29706 +                dwc_otg_mode(core_if) ? "Host" : "Device");
29707 +
29708 +       /* Clear interrupt */
29709 +       gintsts.d32 = 0;
29710 +       gintsts.b.modemismatch = 1;
29711 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29712 +       return 1;
29713 +}
29714 +
29715 +/**
29716 + * This function handles the OTG Interrupts. It reads the OTG
29717 + * Interrupt Register (GOTGINT) to determine what interrupt has
29718 + * occurred.
29719 + *
29720 + * @param core_if Programming view of DWC_otg controller.
29721 + */
29722 +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
29723 +{
29724 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
29725 +       gotgint_data_t gotgint;
29726 +       gotgctl_data_t gotgctl;
29727 +       gintmsk_data_t gintmsk;
29728 +       gpwrdn_data_t gpwrdn;
29729 +
29730 +       gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
29731 +       gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29732 +       DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
29733 +                   op_state_str(core_if));
29734 +
29735 +       if (gotgint.b.sesenddet) {
29736 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29737 +                           "Session End Detected++ (%s)\n",
29738 +                           op_state_str(core_if));
29739 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29740 +
29741 +               if (core_if->op_state == B_HOST) {
29742 +                       cil_pcd_start(core_if);
29743 +                       core_if->op_state = B_PERIPHERAL;
29744 +               } else {
29745 +                       /* If not B_HOST and Device HNP still set. HNP
29746 +                        * Did not succeed!*/
29747 +                       if (gotgctl.b.devhnpen) {
29748 +                               DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
29749 +                               __DWC_ERROR("Device Not Connected/Responding!\n");
29750 +                       }
29751 +
29752 +                       /* If Session End Detected the B-Cable has
29753 +                        * been disconnected. */
29754 +                       /* Reset PCD and Gadget driver to a
29755 +                        * clean state. */
29756 +                       core_if->lx_state = DWC_OTG_L0;
29757 +                       DWC_SPINUNLOCK(core_if->lock);
29758 +                       cil_pcd_stop(core_if);
29759 +                       DWC_SPINLOCK(core_if->lock);
29760 +
29761 +                       if (core_if->adp_enable) {
29762 +                               if (core_if->power_down == 2) {
29763 +                                       gpwrdn.d32 = 0;
29764 +                                       gpwrdn.b.pwrdnswtch = 1;
29765 +                                       DWC_MODIFY_REG32(&core_if->
29766 +                                                        core_global_regs->
29767 +                                                        gpwrdn, gpwrdn.d32, 0);
29768 +                               }
29769 +
29770 +                               gpwrdn.d32 = 0;
29771 +                               gpwrdn.b.pmuintsel = 1;
29772 +                               gpwrdn.b.pmuactv = 1;
29773 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
29774 +                                                gpwrdn, 0, gpwrdn.d32);
29775 +
29776 +                               dwc_otg_adp_sense_start(core_if);
29777 +                       }
29778 +               }
29779 +
29780 +               gotgctl.d32 = 0;
29781 +               gotgctl.b.devhnpen = 1;
29782 +               DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29783 +       }
29784 +       if (gotgint.b.sesreqsucstschng) {
29785 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29786 +                           "Session Reqeust Success Status Change++\n");
29787 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29788 +               if (gotgctl.b.sesreqscs) {
29789 +
29790 +                       if ((core_if->core_params->phy_type ==
29791 +                            DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
29792 +                               core_if->srp_success = 1;
29793 +                       } else {
29794 +                               DWC_SPINUNLOCK(core_if->lock);
29795 +                               cil_pcd_resume(core_if);
29796 +                               DWC_SPINLOCK(core_if->lock);
29797 +                               /* Clear Session Request */
29798 +                               gotgctl.d32 = 0;
29799 +                               gotgctl.b.sesreq = 1;
29800 +                               DWC_MODIFY_REG32(&global_regs->gotgctl,
29801 +                                                gotgctl.d32, 0);
29802 +                       }
29803 +               }
29804 +       }
29805 +       if (gotgint.b.hstnegsucstschng) {
29806 +               /* Print statements during the HNP interrupt handling
29807 +                * can cause it to fail.*/
29808 +               gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
29809 +               /* WA for 3.00a- HW is not setting cur_mode, even sometimes
29810 +                * this does not help*/
29811 +               if (core_if->snpsid >= OTG_CORE_REV_3_00a)
29812 +                       dwc_udelay(100);
29813 +               if (gotgctl.b.hstnegscs) {
29814 +                       if (dwc_otg_is_host_mode(core_if)) {
29815 +                               core_if->op_state = B_HOST;
29816 +                               /*
29817 +                                * Need to disable SOF interrupt immediately.
29818 +                                * When switching from device to host, the PCD
29819 +                                * interrupt handler won't handle the
29820 +                                * interrupt if host mode is already set. The
29821 +                                * HCD interrupt handler won't get called if
29822 +                                * the HCD state is HALT. This means that the
29823 +                                * interrupt does not get handled and Linux
29824 +                                * complains loudly.
29825 +                                */
29826 +                               gintmsk.d32 = 0;
29827 +                               gintmsk.b.sofintr = 1;
29828 +                               DWC_MODIFY_REG32(&global_regs->gintmsk,
29829 +                                                gintmsk.d32, 0);
29830 +                               /* Call callback function with spin lock released */
29831 +                               DWC_SPINUNLOCK(core_if->lock);
29832 +                               cil_pcd_stop(core_if);
29833 +                               /*
29834 +                                * Initialize the Core for Host mode.
29835 +                                */
29836 +                               cil_hcd_start(core_if);
29837 +                               DWC_SPINLOCK(core_if->lock);
29838 +                               core_if->op_state = B_HOST;
29839 +                       }
29840 +               } else {
29841 +                       gotgctl.d32 = 0;
29842 +                       gotgctl.b.hnpreq = 1;
29843 +                       gotgctl.b.devhnpen = 1;
29844 +                       DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
29845 +                       DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
29846 +                       __DWC_ERROR("Device Not Connected/Responding\n");
29847 +               }
29848 +       }
29849 +       if (gotgint.b.hstnegdet) {
29850 +               /* The disconnect interrupt is set at the same time as
29851 +                * Host Negotiation Detected.  During the mode
29852 +                * switch all interrupts are cleared so the disconnect
29853 +                * interrupt handler will not get executed.
29854 +                */
29855 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29856 +                           "Host Negotiation Detected++ (%s)\n",
29857 +                           (dwc_otg_is_host_mode(core_if) ? "Host" :
29858 +                            "Device"));
29859 +               if (dwc_otg_is_device_mode(core_if)) {
29860 +                       DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
29861 +                                   core_if->op_state);
29862 +                       DWC_SPINUNLOCK(core_if->lock);
29863 +                       cil_hcd_disconnect(core_if);
29864 +                       cil_pcd_start(core_if);
29865 +                       DWC_SPINLOCK(core_if->lock);
29866 +                       core_if->op_state = A_PERIPHERAL;
29867 +               } else {
29868 +                       /*
29869 +                        * Need to disable SOF interrupt immediately. When
29870 +                        * switching from device to host, the PCD interrupt
29871 +                        * handler won't handle the interrupt if host mode is
29872 +                        * already set. The HCD interrupt handler won't get
29873 +                        * called if the HCD state is HALT. This means that
29874 +                        * the interrupt does not get handled and Linux
29875 +                        * complains loudly.
29876 +                        */
29877 +                       gintmsk.d32 = 0;
29878 +                       gintmsk.b.sofintr = 1;
29879 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
29880 +                       DWC_SPINUNLOCK(core_if->lock);
29881 +                       cil_pcd_stop(core_if);
29882 +                       cil_hcd_start(core_if);
29883 +                       DWC_SPINLOCK(core_if->lock);
29884 +                       core_if->op_state = A_HOST;
29885 +               }
29886 +       }
29887 +       if (gotgint.b.adevtoutchng) {
29888 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
29889 +                           "A-Device Timeout Change++\n");
29890 +       }
29891 +       if (gotgint.b.debdone) {
29892 +               DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
29893 +       }
29894 +
29895 +       /* Clear GOTGINT */
29896 +       DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
29897 +
29898 +       return 1;
29899 +}
29900 +
29901 +void w_conn_id_status_change(void *p)
29902 +{
29903 +       dwc_otg_core_if_t *core_if = p;
29904 +       uint32_t count = 0;
29905 +       gotgctl_data_t gotgctl = {.d32 = 0 };
29906 +
29907 +       gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
29908 +       DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
29909 +       DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
29910 +
29911 +       /* B-Device connector (Device Mode) */
29912 +       if (gotgctl.b.conidsts) {
29913 +               /* Wait for switch to device mode. */
29914 +               while (!dwc_otg_is_device_mode(core_if)) {
29915 +                       DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
29916 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
29917 +                                   "Peripheral"));
29918 +                       dwc_mdelay(100);
29919 +                       if (++count > 10000)
29920 +                               break;
29921 +               }
29922 +               DWC_ASSERT(++count < 10000,
29923 +                          "Connection id status change timed out");
29924 +               core_if->op_state = B_PERIPHERAL;
29925 +               dwc_otg_core_init(core_if);
29926 +               dwc_otg_enable_global_interrupts(core_if);
29927 +               cil_pcd_start(core_if);
29928 +       } else {
29929 +               /* A-Device connector (Host Mode) */
29930 +               while (!dwc_otg_is_host_mode(core_if)) {
29931 +                       DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
29932 +                                  (dwc_otg_is_host_mode(core_if) ? "Host" :
29933 +                                   "Peripheral"));
29934 +                       dwc_mdelay(100);
29935 +                       if (++count > 10000)
29936 +                               break;
29937 +               }
29938 +               DWC_ASSERT(++count < 10000,
29939 +                          "Connection id status change timed out");
29940 +               core_if->op_state = A_HOST;
29941 +               /*
29942 +                * Initialize the Core for Host mode.
29943 +                */
29944 +               dwc_otg_core_init(core_if);
29945 +               dwc_otg_enable_global_interrupts(core_if);
29946 +               cil_hcd_start(core_if);
29947 +       }
29948 +}
29949 +
29950 +/**
29951 + * This function handles the Connector ID Status Change Interrupt.  It
29952 + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
29953 + * is a Device to Host Mode transition or a Host Mode to Device
29954 + * Transition.
29955 + *
29956 + * This only occurs when the cable is connected/removed from the PHY
29957 + * connector.
29958 + *
29959 + * @param core_if Programming view of DWC_otg controller.
29960 + */
29961 +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
29962 +{
29963 +
29964 +       /*
29965 +        * Need to disable SOF interrupt immediately. If switching from device
29966 +        * to host, the PCD interrupt handler won't handle the interrupt if
29967 +        * host mode is already set. The HCD interrupt handler won't get
29968 +        * called if the HCD state is HALT. This means that the interrupt does
29969 +        * not get handled and Linux complains loudly.
29970 +        */
29971 +       gintmsk_data_t gintmsk = {.d32 = 0 };
29972 +       gintsts_data_t gintsts = {.d32 = 0 };
29973 +
29974 +       gintmsk.b.sofintr = 1;
29975 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
29976 +
29977 +       DWC_DEBUGPL(DBG_CIL,
29978 +                   " ++Connector ID Status Change Interrupt++  (%s)\n",
29979 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
29980 +
29981 +       DWC_SPINUNLOCK(core_if->lock);
29982 +
29983 +       /*
29984 +        * Need to schedule a work, as there are possible DELAY function calls
29985 +        * Release lock before scheduling workq as it holds spinlock during scheduling
29986 +        */
29987 +
29988 +       DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
29989 +                          core_if, "connection id status change");
29990 +       DWC_SPINLOCK(core_if->lock);
29991 +
29992 +       /* Set flag and clear interrupt */
29993 +       gintsts.b.conidstschng = 1;
29994 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
29995 +
29996 +       return 1;
29997 +}
29998 +
29999 +/**
30000 + * This interrupt indicates that a device is initiating the Session
30001 + * Request Protocol to request the host to turn on bus power so a new
30002 + * session can begin. The handler responds by turning on bus power. If
30003 + * the DWC_otg controller is in low power mode, the handler brings the
30004 + * controller out of low power mode before turning on bus power.
30005 + *
30006 + * @param core_if Programming view of DWC_otg controller.
30007 + */
30008 +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
30009 +{
30010 +       gintsts_data_t gintsts;
30011 +
30012 +#ifndef DWC_HOST_ONLY
30013 +       DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
30014 +
30015 +       if (dwc_otg_is_device_mode(core_if)) {
30016 +               DWC_PRINTF("SRP: Device mode\n");
30017 +       } else {
30018 +               hprt0_data_t hprt0;
30019 +               DWC_PRINTF("SRP: Host mode\n");
30020 +
30021 +               /* Turn on the port power bit. */
30022 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
30023 +               hprt0.b.prtpwr = 1;
30024 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30025 +
30026 +               /* Start the Connection timer. So a message can be displayed
30027 +                * if connect does not occur within 10 seconds. */
30028 +               cil_hcd_session_start(core_if);
30029 +       }
30030 +#endif
30031 +
30032 +       /* Clear interrupt */
30033 +       gintsts.d32 = 0;
30034 +       gintsts.b.sessreqintr = 1;
30035 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30036 +
30037 +       return 1;
30038 +}
30039 +
30040 +void w_wakeup_detected(void *p)
30041 +{
30042 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
30043 +       /*
30044 +        * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
30045 +        * so that OPT tests pass with all PHYs).
30046 +        */
30047 +       hprt0_data_t hprt0 = {.d32 = 0 };
30048 +#if 0
30049 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30050 +       /* Restart the Phy Clock */
30051 +       pcgcctl.b.stoppclk = 1;
30052 +       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30053 +       dwc_udelay(10);
30054 +#endif //0
30055 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
30056 +       DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
30057 +//      dwc_mdelay(70);
30058 +       hprt0.b.prtres = 0;     /* Resume */
30059 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
30060 +       DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
30061 +                   DWC_READ_REG32(core_if->host_if->hprt0));
30062 +
30063 +       cil_hcd_resume(core_if);
30064 +
30065 +       /** Change to L0 state*/
30066 +       core_if->lx_state = DWC_OTG_L0;
30067 +}
30068 +
30069 +/**
30070 + * This interrupt indicates that the DWC_otg controller has detected a
30071 + * resume or remote wakeup sequence. If the DWC_otg controller is in
30072 + * low power mode, the handler must brings the controller out of low
30073 + * power mode. The controller automatically begins resume
30074 + * signaling. The handler schedules a time to stop resume signaling.
30075 + */
30076 +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30077 +{
30078 +       gintsts_data_t gintsts;
30079 +
30080 +       DWC_DEBUGPL(DBG_ANY,
30081 +                   "++Resume and Remote Wakeup Detected Interrupt++\n");
30082 +
30083 +       DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
30084 +
30085 +       if (dwc_otg_is_device_mode(core_if)) {
30086 +               dctl_data_t dctl = {.d32 = 0 };
30087 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
30088 +                           DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
30089 +                                          dsts));
30090 +               if (core_if->lx_state == DWC_OTG_L2) {
30091 +#ifdef PARTIAL_POWER_DOWN
30092 +                       if (core_if->hwcfg4.b.power_optimiz) {
30093 +                               pcgcctl_data_t power = {.d32 = 0 };
30094 +
30095 +                               power.d32 = DWC_READ_REG32(core_if->pcgcctl);
30096 +                               DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
30097 +                                           power.d32);
30098 +
30099 +                               power.b.stoppclk = 0;
30100 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30101 +
30102 +                               power.b.pwrclmp = 0;
30103 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30104 +
30105 +                               power.b.rstpdwnmodule = 0;
30106 +                               DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30107 +                       }
30108 +#endif
30109 +                       /* Clear the Remote Wakeup Signaling */
30110 +                       dctl.b.rmtwkupsig = 1;
30111 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
30112 +                                        dctl, dctl.d32, 0);
30113 +
30114 +                       DWC_SPINUNLOCK(core_if->lock);
30115 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
30116 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
30117 +                       }
30118 +                       DWC_SPINLOCK(core_if->lock);
30119 +               } else {
30120 +                       glpmcfg_data_t lpmcfg;
30121 +                       lpmcfg.d32 =
30122 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30123 +                       lpmcfg.b.hird_thres &= (~(1 << 4));
30124 +                       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30125 +                                       lpmcfg.d32);
30126 +               }
30127 +               /** Change to L0 state*/
30128 +               core_if->lx_state = DWC_OTG_L0;
30129 +       } else {
30130 +               if (core_if->lx_state != DWC_OTG_L1) {
30131 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30132 +
30133 +                       /* Restart the Phy Clock */
30134 +                       pcgcctl.b.stoppclk = 1;
30135 +                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
30136 +                       DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
30137 +               } else {
30138 +                       /** Change to L0 state*/
30139 +                       core_if->lx_state = DWC_OTG_L0;
30140 +               }
30141 +       }
30142 +
30143 +       /* Clear interrupt */
30144 +       gintsts.d32 = 0;
30145 +       gintsts.b.wkupintr = 1;
30146 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30147 +
30148 +       return 1;
30149 +}
30150 +
30151 +/**
30152 + * This interrupt indicates that the Wakeup Logic has detected a
30153 + * Device disconnect.
30154 + */
30155 +static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
30156 +{
30157 +       gpwrdn_data_t gpwrdn = { .d32 = 0 };
30158 +       gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
30159 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30160 +
30161 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30162 +
30163 +       if (!core_if->hibernation_suspend) {
30164 +               DWC_PRINTF("Already exited from Hibernation\n");
30165 +               return 1;
30166 +       }
30167 +
30168 +       /* Switch on the voltage to the core */
30169 +       gpwrdn.b.pwrdnswtch = 1;
30170 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30171 +       dwc_udelay(10);
30172 +
30173 +       /* Reset the core */
30174 +       gpwrdn.d32 = 0;
30175 +       gpwrdn.b.pwrdnrstn = 1;
30176 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30177 +       dwc_udelay(10);
30178 +
30179 +       /* Disable power clamps*/
30180 +       gpwrdn.d32 = 0;
30181 +       gpwrdn.b.pwrdnclmp = 1;
30182 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30183 +
30184 +       /* Remove reset the core signal */
30185 +       gpwrdn.d32 = 0;
30186 +       gpwrdn.b.pwrdnrstn = 1;
30187 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30188 +       dwc_udelay(10);
30189 +
30190 +       /* Disable PMU interrupt */
30191 +       gpwrdn.d32 = 0;
30192 +       gpwrdn.b.pmuintsel = 1;
30193 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30194 +
30195 +       core_if->hibernation_suspend = 0;
30196 +
30197 +       /* Disable PMU */
30198 +       gpwrdn.d32 = 0;
30199 +       gpwrdn.b.pmuactv = 1;
30200 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30201 +       dwc_udelay(10);
30202 +
30203 +       if (gpwrdn_temp.b.idsts) {
30204 +               core_if->op_state = B_PERIPHERAL;
30205 +               dwc_otg_core_init(core_if);
30206 +               dwc_otg_enable_global_interrupts(core_if);
30207 +               cil_pcd_start(core_if);
30208 +       } else {
30209 +               core_if->op_state = A_HOST;
30210 +               dwc_otg_core_init(core_if);
30211 +               dwc_otg_enable_global_interrupts(core_if);
30212 +               cil_hcd_start(core_if);
30213 +       }
30214 +
30215 +       return 1;
30216 +}
30217 +
30218 +/**
30219 + * This interrupt indicates that the Wakeup Logic has detected a
30220 + * remote wakeup sequence.
30221 + */
30222 +static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
30223 +{
30224 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30225 +       DWC_DEBUGPL(DBG_ANY,
30226 +                   "++Powerdown Remote Wakeup Detected Interrupt++\n");
30227 +
30228 +       if (!core_if->hibernation_suspend) {
30229 +               DWC_PRINTF("Already exited from Hibernation\n");
30230 +               return 1;
30231 +       }
30232 +
30233 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30234 +       if (gpwrdn.b.idsts) {   // Device Mode
30235 +               if ((core_if->power_down == 2)
30236 +                   && (core_if->hibernation_suspend == 1)) {
30237 +                       dwc_otg_device_hibernation_restore(core_if, 0, 0);
30238 +               }
30239 +       } else {
30240 +               if ((core_if->power_down == 2)
30241 +                   && (core_if->hibernation_suspend == 1)) {
30242 +                       dwc_otg_host_hibernation_restore(core_if, 1, 0);
30243 +               }
30244 +       }
30245 +       return 1;
30246 +}
30247 +
30248 +static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
30249 +{
30250 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30251 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30252 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30253 +
30254 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30255 +       gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30256 +       if (core_if->power_down == 2) {
30257 +               if (!core_if->hibernation_suspend) {
30258 +                       DWC_PRINTF("Already exited from Hibernation\n");
30259 +                       return 1;
30260 +               }
30261 +               DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
30262 +               /* Switch on the voltage to the core */
30263 +               gpwrdn.b.pwrdnswtch = 1;
30264 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30265 +               dwc_udelay(10);
30266 +
30267 +               /* Reset the core */
30268 +               gpwrdn.d32 = 0;
30269 +               gpwrdn.b.pwrdnrstn = 1;
30270 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30271 +               dwc_udelay(10);
30272 +
30273 +               /* Disable power clamps */
30274 +               gpwrdn.d32 = 0;
30275 +               gpwrdn.b.pwrdnclmp = 1;
30276 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30277 +
30278 +               /* Remove reset the core signal */
30279 +               gpwrdn.d32 = 0;
30280 +               gpwrdn.b.pwrdnrstn = 1;
30281 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30282 +               dwc_udelay(10);
30283 +
30284 +               /* Disable PMU interrupt */
30285 +               gpwrdn.d32 = 0;
30286 +               gpwrdn.b.pmuintsel = 1;
30287 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30288 +
30289 +               /*Indicates that we are exiting from hibernation */
30290 +               core_if->hibernation_suspend = 0;
30291 +
30292 +               /* Disable PMU */
30293 +               gpwrdn.d32 = 0;
30294 +               gpwrdn.b.pmuactv = 1;
30295 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30296 +               dwc_udelay(10);
30297 +
30298 +               gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
30299 +               if (gpwrdn.b.dis_vbus == 1) {
30300 +                       gpwrdn.d32 = 0;
30301 +                       gpwrdn.b.dis_vbus = 1;
30302 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30303 +               }
30304 +
30305 +               if (gpwrdn_temp.b.idsts) {
30306 +                       core_if->op_state = B_PERIPHERAL;
30307 +                       dwc_otg_core_init(core_if);
30308 +                       dwc_otg_enable_global_interrupts(core_if);
30309 +                       cil_pcd_start(core_if);
30310 +               } else {
30311 +                       core_if->op_state = A_HOST;
30312 +                       dwc_otg_core_init(core_if);
30313 +                       dwc_otg_enable_global_interrupts(core_if);
30314 +                       cil_hcd_start(core_if);
30315 +               }
30316 +       }
30317 +
30318 +       if (core_if->adp_enable) {
30319 +               uint8_t is_host = 0;
30320 +               DWC_SPINUNLOCK(core_if->lock);
30321 +               /* Change the core_if's lock to hcd/pcd lock depend on mode? */
30322 +#ifndef DWC_HOST_ONLY
30323 +               if (gpwrdn_temp.b.idsts)
30324 +                       core_if->lock = otg_dev->pcd->lock;
30325 +#endif
30326 +#ifndef DWC_DEVICE_ONLY
30327 +               if (!gpwrdn_temp.b.idsts) {
30328 +                               core_if->lock = otg_dev->hcd->lock;
30329 +                               is_host = 1;
30330 +               }
30331 +#endif
30332 +               DWC_PRINTF("RESTART ADP\n");
30333 +               if (core_if->adp.probe_enabled)
30334 +                       dwc_otg_adp_probe_stop(core_if);
30335 +               if (core_if->adp.sense_enabled)
30336 +                       dwc_otg_adp_sense_stop(core_if);
30337 +               if (core_if->adp.sense_timer_started)
30338 +                       DWC_TIMER_CANCEL(core_if->adp.sense_timer);
30339 +               if (core_if->adp.vbuson_timer_started)
30340 +                       DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
30341 +               core_if->adp.probe_timer_values[0] = -1;
30342 +               core_if->adp.probe_timer_values[1] = -1;
30343 +               core_if->adp.sense_timer_started = 0;
30344 +               core_if->adp.vbuson_timer_started = 0;
30345 +               core_if->adp.probe_counter = 0;
30346 +               core_if->adp.gpwrdn = 0;
30347 +
30348 +               /* Disable PMU and restart ADP */
30349 +               gpwrdn_temp.d32 = 0;
30350 +               gpwrdn_temp.b.pmuactv = 1;
30351 +               gpwrdn_temp.b.pmuintsel = 1;
30352 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30353 +               DWC_PRINTF("Check point 1\n");
30354 +               dwc_mdelay(110);
30355 +               dwc_otg_adp_start(core_if, is_host);
30356 +               DWC_SPINLOCK(core_if->lock);
30357 +       }
30358 +
30359 +
30360 +       return 1;
30361 +}
30362 +
30363 +static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
30364 +{
30365 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30366 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
30367 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30368 +
30369 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30370 +       if (core_if->power_down == 2) {
30371 +               if (!core_if->hibernation_suspend) {
30372 +                       DWC_PRINTF("Already exited from Hibernation\n");
30373 +                       return 1;
30374 +               }
30375 +
30376 +               if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30377 +                        otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
30378 +                       gpwrdn.b.bsessvld == 0) {
30379 +                       /* Save gpwrdn register for further usage if stschng interrupt */
30380 +                       core_if->gr_backup->gpwrdn_local =
30381 +                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30382 +                       /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
30383 +                       return 1;
30384 +               }
30385 +
30386 +               /* Switch on the voltage to the core */
30387 +               gpwrdn.d32 = 0;
30388 +               gpwrdn.b.pwrdnswtch = 1;
30389 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30390 +               dwc_udelay(10);
30391 +
30392 +               /* Reset the core */
30393 +               gpwrdn.d32 = 0;
30394 +               gpwrdn.b.pwrdnrstn = 1;
30395 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30396 +               dwc_udelay(10);
30397 +
30398 +               /* Disable power clamps */
30399 +               gpwrdn.d32 = 0;
30400 +               gpwrdn.b.pwrdnclmp = 1;
30401 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30402 +
30403 +               /* Remove reset the core signal */
30404 +               gpwrdn.d32 = 0;
30405 +               gpwrdn.b.pwrdnrstn = 1;
30406 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30407 +               dwc_udelay(10);
30408 +
30409 +               /* Disable PMU interrupt */
30410 +               gpwrdn.d32 = 0;
30411 +               gpwrdn.b.pmuintsel = 1;
30412 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30413 +               dwc_udelay(10);
30414 +
30415 +               /*Indicates that we are exiting from hibernation */
30416 +               core_if->hibernation_suspend = 0;
30417 +
30418 +               /* Disable PMU */
30419 +               gpwrdn.d32 = 0;
30420 +               gpwrdn.b.pmuactv = 1;
30421 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30422 +               dwc_udelay(10);
30423 +
30424 +               core_if->op_state = B_PERIPHERAL;
30425 +               dwc_otg_core_init(core_if);
30426 +               dwc_otg_enable_global_interrupts(core_if);
30427 +               cil_pcd_start(core_if);
30428 +
30429 +               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
30430 +                       otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
30431 +                       /*
30432 +                        * Initiate SRP after initial ADP probe.
30433 +                        */
30434 +                       dwc_otg_initiate_srp(core_if);
30435 +               }
30436 +       }
30437 +
30438 +       return 1;
30439 +}
30440 +/**
30441 + * This interrupt indicates that the Wakeup Logic has detected a
30442 + * status change either on IDDIG or BSessVld.
30443 + */
30444 +static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
30445 +{
30446 +       int retval;
30447 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30448 +       gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
30449 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
30450 +
30451 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30452 +
30453 +       if (core_if->power_down == 2) {
30454 +               if (core_if->hibernation_suspend <= 0) {
30455 +                       DWC_PRINTF("Already exited from Hibernation\n");
30456 +                       return 1;
30457 +               } else
30458 +                       gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
30459 +
30460 +       } else {
30461 +               gpwrdn_temp.d32 = core_if->adp.gpwrdn;
30462 +       }
30463 +
30464 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30465 +
30466 +       if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
30467 +               retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
30468 +       } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
30469 +               retval = dwc_otg_handle_pwrdn_session_change(core_if);
30470 +       }
30471 +
30472 +       return retval;
30473 +}
30474 +
30475 +/**
30476 + * This interrupt indicates that the Wakeup Logic has detected a
30477 + * SRP.
30478 + */
30479 +static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
30480 +{
30481 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30482 +
30483 +       DWC_PRINTF("%s called\n", __FUNCTION__);
30484 +
30485 +       if (!core_if->hibernation_suspend) {
30486 +               DWC_PRINTF("Already exited from Hibernation\n");
30487 +               return 1;
30488 +       }
30489 +#ifdef DWC_DEV_SRPCAP
30490 +       if (core_if->pwron_timer_started) {
30491 +               core_if->pwron_timer_started = 0;
30492 +               DWC_TIMER_CANCEL(core_if->pwron_timer);
30493 +       }
30494 +#endif
30495 +
30496 +       /* Switch on the voltage to the core */
30497 +       gpwrdn.b.pwrdnswtch = 1;
30498 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30499 +       dwc_udelay(10);
30500 +
30501 +       /* Reset the core */
30502 +       gpwrdn.d32 = 0;
30503 +       gpwrdn.b.pwrdnrstn = 1;
30504 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30505 +       dwc_udelay(10);
30506 +
30507 +       /* Disable power clamps */
30508 +       gpwrdn.d32 = 0;
30509 +       gpwrdn.b.pwrdnclmp = 1;
30510 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30511 +
30512 +       /* Remove reset the core signal */
30513 +       gpwrdn.d32 = 0;
30514 +       gpwrdn.b.pwrdnrstn = 1;
30515 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
30516 +       dwc_udelay(10);
30517 +
30518 +       /* Disable PMU interrupt */
30519 +       gpwrdn.d32 = 0;
30520 +       gpwrdn.b.pmuintsel = 1;
30521 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30522 +
30523 +       /* Indicates that we are exiting from hibernation */
30524 +       core_if->hibernation_suspend = 0;
30525 +
30526 +       /* Disable PMU */
30527 +       gpwrdn.d32 = 0;
30528 +       gpwrdn.b.pmuactv = 1;
30529 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30530 +       dwc_udelay(10);
30531 +
30532 +       /* Programm Disable VBUS to 0 */
30533 +       gpwrdn.d32 = 0;
30534 +       gpwrdn.b.dis_vbus = 1;
30535 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
30536 +
30537 +       /*Initialize the core as Host */
30538 +       core_if->op_state = A_HOST;
30539 +       dwc_otg_core_init(core_if);
30540 +       dwc_otg_enable_global_interrupts(core_if);
30541 +       cil_hcd_start(core_if);
30542 +
30543 +       return 1;
30544 +}
30545 +
30546 +/** This interrupt indicates that restore command after Hibernation
30547 + * was completed by the core. */
30548 +int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
30549 +{
30550 +       pcgcctl_data_t pcgcctl;
30551 +       DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
30552 +
30553 +       //TODO De-assert restore signal. 8.a
30554 +       pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
30555 +       if (pcgcctl.b.restoremode == 1) {
30556 +               gintmsk_data_t gintmsk = {.d32 = 0 };
30557 +               /*
30558 +                * If restore mode is Remote Wakeup,
30559 +                * unmask Remote Wakeup interrupt.
30560 +                */
30561 +               gintmsk.b.wkupintr = 1;
30562 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
30563 +                                0, gintmsk.d32);
30564 +       }
30565 +
30566 +       return 1;
30567 +}
30568 +
30569 +/**
30570 + * This interrupt indicates that a device has been disconnected from
30571 + * the root port.
30572 + */
30573 +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
30574 +{
30575 +       gintsts_data_t gintsts;
30576 +
30577 +       DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
30578 +                   (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
30579 +                   op_state_str(core_if));
30580 +
30581 +/** @todo Consolidate this if statement. */
30582 +#ifndef DWC_HOST_ONLY
30583 +       if (core_if->op_state == B_HOST) {
30584 +               /* If in device mode Disconnect and stop the HCD, then
30585 +                * start the PCD. */
30586 +               DWC_SPINUNLOCK(core_if->lock);
30587 +               cil_hcd_disconnect(core_if);
30588 +               cil_pcd_start(core_if);
30589 +               DWC_SPINLOCK(core_if->lock);
30590 +               core_if->op_state = B_PERIPHERAL;
30591 +       } else if (dwc_otg_is_device_mode(core_if)) {
30592 +               gotgctl_data_t gotgctl = {.d32 = 0 };
30593 +               gotgctl.d32 =
30594 +                   DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
30595 +               if (gotgctl.b.hstsethnpen == 1) {
30596 +                       /* Do nothing, if HNP in process the OTG
30597 +                        * interrupt "Host Negotiation Detected"
30598 +                        * interrupt will do the mode switch.
30599 +                        */
30600 +               } else if (gotgctl.b.devhnpen == 0) {
30601 +                       /* If in device mode Disconnect and stop the HCD, then
30602 +                        * start the PCD. */
30603 +                       DWC_SPINUNLOCK(core_if->lock);
30604 +                       cil_hcd_disconnect(core_if);
30605 +                       cil_pcd_start(core_if);
30606 +                       DWC_SPINLOCK(core_if->lock);
30607 +                       core_if->op_state = B_PERIPHERAL;
30608 +               } else {
30609 +                       DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
30610 +               }
30611 +       } else {
30612 +               if (core_if->op_state == A_HOST) {
30613 +                       /* A-Cable still connected but device disconnected. */
30614 +                       cil_hcd_disconnect(core_if);
30615 +                       if (core_if->adp_enable) {
30616 +                               gpwrdn_data_t gpwrdn = { .d32 = 0 };
30617 +                               cil_hcd_stop(core_if);
30618 +                               /* Enable Power Down Logic */
30619 +                               gpwrdn.b.pmuintsel = 1;
30620 +                               gpwrdn.b.pmuactv = 1;
30621 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30622 +                                                gpwrdn, 0, gpwrdn.d32);
30623 +                               dwc_otg_adp_probe_start(core_if);
30624 +
30625 +                               /* Power off the core */
30626 +                               if (core_if->power_down == 2) {
30627 +                                       gpwrdn.d32 = 0;
30628 +                                       gpwrdn.b.pwrdnswtch = 1;
30629 +                                       DWC_MODIFY_REG32
30630 +                                           (&core_if->core_global_regs->gpwrdn,
30631 +                                            gpwrdn.d32, 0);
30632 +                               }
30633 +                       }
30634 +               }
30635 +       }
30636 +#endif
30637 +       /* Change to L3(OFF) state */
30638 +       core_if->lx_state = DWC_OTG_L3;
30639 +
30640 +       gintsts.d32 = 0;
30641 +       gintsts.b.disconnect = 1;
30642 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30643 +       return 1;
30644 +}
30645 +
30646 +/**
30647 + * This interrupt indicates that SUSPEND state has been detected on
30648 + * the USB.
30649 + *
30650 + * For HNP the USB Suspend interrupt signals the change from
30651 + * "a_peripheral" to "a_host".
30652 + *
30653 + * When power management is enabled the core will be put in low power
30654 + * mode.
30655 + */
30656 +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
30657 +{
30658 +       dsts_data_t dsts;
30659 +       gintsts_data_t gintsts;
30660 +       dcfg_data_t dcfg;
30661 +
30662 +       DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
30663 +
30664 +       if (dwc_otg_is_device_mode(core_if)) {
30665 +               /* Check the Device status register to determine if the Suspend
30666 +                * state is active. */
30667 +               dsts.d32 =
30668 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
30669 +               DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
30670 +               DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
30671 +                           "HWCFG4.power Optimize=%d\n",
30672 +                           dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
30673 +
30674 +#ifdef PARTIAL_POWER_DOWN
30675 +/** @todo Add a module parameter for power management. */
30676 +
30677 +               if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
30678 +                       pcgcctl_data_t power = {.d32 = 0 };
30679 +                       DWC_DEBUGPL(DBG_CIL, "suspend\n");
30680 +
30681 +                       power.b.pwrclmp = 1;
30682 +                       DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
30683 +
30684 +                       power.b.rstpdwnmodule = 1;
30685 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30686 +
30687 +                       power.b.stoppclk = 1;
30688 +                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
30689 +
30690 +               } else {
30691 +                       DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
30692 +               }
30693 +#endif
30694 +               /* PCD callback for suspend. Release the lock inside of callback function */
30695 +               cil_pcd_suspend(core_if);
30696 +               if (core_if->power_down == 2)
30697 +               {
30698 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30699 +                       DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
30700 +                       DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
30701 +
30702 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30703 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
30704 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
30705 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
30706 +
30707 +                               /* Change to L2(suspend) state */
30708 +                               core_if->lx_state = DWC_OTG_L2;
30709 +
30710 +                               /* Clear interrupt in gintsts */
30711 +                               gintsts.d32 = 0;
30712 +                               gintsts.b.usbsuspend = 1;
30713 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30714 +                                               gintsts, gintsts.d32);
30715 +                               DWC_PRINTF("Start of hibernation completed\n");
30716 +                               dwc_otg_save_global_regs(core_if);
30717 +                               dwc_otg_save_dev_regs(core_if);
30718 +
30719 +                               gusbcfg.d32 =
30720 +                                   DWC_READ_REG32(&core_if->core_global_regs->
30721 +                                                  gusbcfg);
30722 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
30723 +                                       /* ULPI interface */
30724 +                                       /* Suspend the Phy Clock */
30725 +                                       pcgcctl.d32 = 0;
30726 +                                       pcgcctl.b.stoppclk = 1;
30727 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30728 +                                                        pcgcctl.d32);
30729 +                                       dwc_udelay(10);
30730 +                                       gpwrdn.b.pmuactv = 1;
30731 +                                       DWC_MODIFY_REG32(&core_if->
30732 +                                                        core_global_regs->
30733 +                                                        gpwrdn, 0, gpwrdn.d32);
30734 +                               } else {
30735 +                                       /* UTMI+ Interface */
30736 +                                       gpwrdn.b.pmuactv = 1;
30737 +                                       DWC_MODIFY_REG32(&core_if->
30738 +                                                        core_global_regs->
30739 +                                                        gpwrdn, 0, gpwrdn.d32);
30740 +                                       dwc_udelay(10);
30741 +                                       pcgcctl.b.stoppclk = 1;
30742 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
30743 +                                                        pcgcctl.d32);
30744 +                                       dwc_udelay(10);
30745 +                               }
30746 +
30747 +                               /* Set flag to indicate that we are in hibernation */
30748 +                               core_if->hibernation_suspend = 1;
30749 +                               /* Enable interrupts from wake up logic */
30750 +                               gpwrdn.d32 = 0;
30751 +                               gpwrdn.b.pmuintsel = 1;
30752 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30753 +                                                gpwrdn, 0, gpwrdn.d32);
30754 +                               dwc_udelay(10);
30755 +
30756 +                               /* Unmask device mode interrupts in GPWRDN */
30757 +                               gpwrdn.d32 = 0;
30758 +                               gpwrdn.b.rst_det_msk = 1;
30759 +                               gpwrdn.b.lnstchng_msk = 1;
30760 +                               gpwrdn.b.sts_chngint_msk = 1;
30761 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30762 +                                                gpwrdn, 0, gpwrdn.d32);
30763 +                               dwc_udelay(10);
30764 +
30765 +                               /* Enable Power Down Clamp */
30766 +                               gpwrdn.d32 = 0;
30767 +                               gpwrdn.b.pwrdnclmp = 1;
30768 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30769 +                                                gpwrdn, 0, gpwrdn.d32);
30770 +                               dwc_udelay(10);
30771 +
30772 +                               /* Switch off VDD */
30773 +                               gpwrdn.d32 = 0;
30774 +                               gpwrdn.b.pwrdnswtch = 1;
30775 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
30776 +                                                gpwrdn, 0, gpwrdn.d32);
30777 +
30778 +                               /* Save gpwrdn register for further usage if stschng interrupt */
30779 +                               core_if->gr_backup->gpwrdn_local =
30780 +                                                       DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30781 +                               DWC_PRINTF("Hibernation completed\n");
30782 +
30783 +                               return 1;
30784 +                       }
30785 +               } else if (core_if->power_down == 3) {
30786 +                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30787 +                       dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
30788 +                       DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);
30789 +                       DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);
30790 +
30791 +                       if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
30792 +                               DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");
30793 +                               core_if->xhib = 1;
30794 +
30795 +                               /* Clear interrupt in gintsts */
30796 +                               gintsts.d32 = 0;
30797 +                               gintsts.b.usbsuspend = 1;
30798 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
30799 +                                       gintsts, gintsts.d32);
30800 +
30801 +                               dwc_otg_save_global_regs(core_if);
30802 +                               dwc_otg_save_dev_regs(core_if);
30803 +
30804 +                               /* Wait for 10 PHY clocks */
30805 +                               dwc_udelay(10);
30806 +
30807 +                               /* Program GPIO register while entering to xHib */
30808 +                               DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);
30809 +
30810 +                               pcgcctl.b.enbl_extnd_hiber = 1;
30811 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30812 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30813 +
30814 +                               pcgcctl.d32 = 0;
30815 +                               pcgcctl.b.extnd_hiber_pwrclmp = 1;
30816 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30817 +
30818 +                               pcgcctl.d32 = 0;
30819 +                               pcgcctl.b.extnd_hiber_switch = 1;
30820 +                               core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
30821 +                               core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;
30822 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
30823 +
30824 +                               DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");
30825 +
30826 +                               return 1;
30827 +                       }
30828 +               }
30829 +       } else {
30830 +               if (core_if->op_state == A_PERIPHERAL) {
30831 +                       DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
30832 +                       /* Clear the a_peripheral flag, back to a_host. */
30833 +                       DWC_SPINUNLOCK(core_if->lock);
30834 +                       cil_pcd_stop(core_if);
30835 +                       cil_hcd_start(core_if);
30836 +                       DWC_SPINLOCK(core_if->lock);
30837 +                       core_if->op_state = A_HOST;
30838 +               }
30839 +       }
30840 +
30841 +       /* Change to L2(suspend) state */
30842 +       core_if->lx_state = DWC_OTG_L2;
30843 +
30844 +       /* Clear interrupt */
30845 +       gintsts.d32 = 0;
30846 +       gintsts.b.usbsuspend = 1;
30847 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30848 +
30849 +       return 1;
30850 +}
30851 +
30852 +static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)
30853 +{
30854 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
30855 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
30856 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
30857 +
30858 +       dwc_udelay(10);
30859 +
30860 +       /* Program GPIO register while entering to xHib */
30861 +       DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
30862 +
30863 +       pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
30864 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30865 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30866 +       dwc_udelay(10);
30867 +
30868 +       gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
30869 +       gpwrdn.b.restore = 1;
30870 +       DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
30871 +       dwc_udelay(10);
30872 +
30873 +       restore_lpm_i2c_regs(core_if);
30874 +
30875 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30876 +       pcgcctl.b.max_xcvrselect = 1;
30877 +       pcgcctl.b.ess_reg_restored = 0;
30878 +       pcgcctl.b.extnd_hiber_switch = 0;
30879 +       pcgcctl.b.extnd_hiber_pwrclmp = 0;
30880 +       pcgcctl.b.enbl_extnd_hiber = 1;
30881 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30882 +
30883 +       gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
30884 +       gahbcfg.b.glblintrmsk = 1;
30885 +       DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
30886 +
30887 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
30888 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
30889 +
30890 +       DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
30891 +                       core_if->gr_backup->gusbcfg_local);
30892 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
30893 +                       core_if->dr_backup->dcfg);
30894 +
30895 +       pcgcctl.d32 = 0;
30896 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30897 +       pcgcctl.b.max_xcvrselect = 1;
30898 +       pcgcctl.d32 |= 0x608;
30899 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30900 +       dwc_udelay(10);
30901 +
30902 +       pcgcctl.d32 = 0;
30903 +       pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
30904 +       pcgcctl.b.max_xcvrselect = 1;
30905 +       pcgcctl.b.ess_reg_restored = 1;
30906 +       pcgcctl.b.enbl_extnd_hiber = 1;
30907 +       pcgcctl.b.rstpdwnmodule = 1;
30908 +       pcgcctl.b.restoremode = 1;
30909 +       DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
30910 +
30911 +       DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
30912 +
30913 +       return 1;
30914 +}
30915 +
30916 +#ifdef CONFIG_USB_DWC_OTG_LPM
30917 +/**
30918 + * This function hadles LPM transaction received interrupt.
30919 + */
30920 +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
30921 +{
30922 +       glpmcfg_data_t lpmcfg;
30923 +       gintsts_data_t gintsts;
30924 +
30925 +       if (!core_if->core_params->lpm_enable) {
30926 +               DWC_PRINTF("Unexpected LPM interrupt\n");
30927 +       }
30928 +
30929 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30930 +       DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
30931 +
30932 +       if (dwc_otg_is_host_mode(core_if)) {
30933 +               cil_hcd_sleep(core_if);
30934 +       } else {
30935 +               lpmcfg.b.hird_thres |= (1 << 4);
30936 +               DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
30937 +                               lpmcfg.d32);
30938 +       }
30939 +
30940 +       /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
30941 +       dwc_udelay(10);
30942 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
30943 +       if (lpmcfg.b.prt_sleep_sts) {
30944 +               /* Save the current state */
30945 +               core_if->lx_state = DWC_OTG_L1;
30946 +       }
30947 +
30948 +       /* Clear interrupt  */
30949 +       gintsts.d32 = 0;
30950 +       gintsts.b.lpmtranrcvd = 1;
30951 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
30952 +       return 1;
30953 +}
30954 +#endif /* CONFIG_USB_DWC_OTG_LPM */
30955 +
30956 +/**
30957 + * This function returns the Core Interrupt register.
30958 + */
30959 +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
30960 +{
30961 +       gahbcfg_data_t gahbcfg = {.d32 = 0 };
30962 +       gintsts_data_t gintsts;
30963 +       gintmsk_data_t gintmsk;
30964 +       gintmsk_data_t gintmsk_common = {.d32 = 0 };
30965 +       gintmsk_common.b.wkupintr = 1;
30966 +       gintmsk_common.b.sessreqintr = 1;
30967 +       gintmsk_common.b.conidstschng = 1;
30968 +       gintmsk_common.b.otgintr = 1;
30969 +       gintmsk_common.b.modemismatch = 1;
30970 +       gintmsk_common.b.disconnect = 1;
30971 +       gintmsk_common.b.usbsuspend = 1;
30972 +#ifdef CONFIG_USB_DWC_OTG_LPM
30973 +       gintmsk_common.b.lpmtranrcvd = 1;
30974 +#endif
30975 +       gintmsk_common.b.restoredone = 1;
30976 +       /** @todo: The port interrupt occurs while in device
30977 +         * mode. Added code to CIL to clear the interrupt for now!
30978 +         */
30979 +       gintmsk_common.b.portintr = 1;
30980 +
30981 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
30982 +       gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
30983 +       gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
30984 +
30985 +#ifdef DEBUG
30986 +       /* if any common interrupts set */
30987 +       if (gintsts.d32 & gintmsk_common.d32) {
30988 +               DWC_DEBUGPL(DBG_ANY, "gintsts=%08x  gintmsk=%08x\n",
30989 +                           gintsts.d32, gintmsk.d32);
30990 +       }
30991 +#endif
30992 +       if (gahbcfg.b.glblintrmsk)
30993 +               return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
30994 +       else
30995 +               return 0;
30996 +
30997 +}
30998 +
30999 +/* MACRO for clearing interupt bits in GPWRDN register */
31000 +#define CLEAR_GPWRDN_INTR(__core_if,__intr) \
31001 +do { \
31002 +               gpwrdn_data_t gpwrdn = {.d32=0}; \
31003 +               gpwrdn.b.__intr = 1; \
31004 +               DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
31005 +               0, gpwrdn.d32); \
31006 +} while (0)
31007 +
31008 +/**
31009 + * Common interrupt handler.
31010 + *
31011 + * The common interrupts are those that occur in both Host and Device mode.
31012 + * This handler handles the following interrupts:
31013 + * - Mode Mismatch Interrupt
31014 + * - Disconnect Interrupt
31015 + * - OTG Interrupt
31016 + * - Connector ID Status Change Interrupt
31017 + * - Session Request Interrupt.
31018 + * - Resume / Remote Wakeup Detected Interrupt.
31019 + * - LPM Transaction Received Interrupt
31020 + * - ADP Transaction Received Interrupt
31021 + *
31022 + */
31023 +int32_t dwc_otg_handle_common_intr(void *dev)
31024 +{
31025 +       int retval = 0;
31026 +       gintsts_data_t gintsts;
31027 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
31028 +       dwc_otg_device_t *otg_dev = dev;
31029 +       dwc_otg_core_if_t *core_if = otg_dev->core_if;
31030 +       gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
31031 +       if (dwc_otg_is_device_mode(core_if))
31032 +               core_if->frame_num = dwc_otg_get_frame_number(core_if);
31033 +
31034 +       if (core_if->lock)
31035 +               DWC_SPINLOCK(core_if->lock);
31036 +
31037 +       if (core_if->power_down == 3 && core_if->xhib == 1) {
31038 +               DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
31039 +               retval |= dwc_otg_handle_xhib_exit_intr(core_if);
31040 +               core_if->xhib = 2;
31041 +               if (core_if->lock)
31042 +                       DWC_SPINUNLOCK(core_if->lock);
31043 +
31044 +               return retval;
31045 +       }
31046 +
31047 +       if (core_if->hibernation_suspend <= 0) {
31048 +               gintsts.d32 = dwc_otg_read_common_intr(core_if);
31049 +
31050 +               if (gintsts.b.modemismatch) {
31051 +                       retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
31052 +               }
31053 +               if (gintsts.b.otgintr) {
31054 +                       retval |= dwc_otg_handle_otg_intr(core_if);
31055 +               }
31056 +               if (gintsts.b.conidstschng) {
31057 +                       retval |=
31058 +                           dwc_otg_handle_conn_id_status_change_intr(core_if);
31059 +               }
31060 +               if (gintsts.b.disconnect) {
31061 +                       retval |= dwc_otg_handle_disconnect_intr(core_if);
31062 +               }
31063 +               if (gintsts.b.sessreqintr) {
31064 +                       retval |= dwc_otg_handle_session_req_intr(core_if);
31065 +               }
31066 +               if (gintsts.b.wkupintr) {
31067 +                       retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
31068 +               }
31069 +               if (gintsts.b.usbsuspend) {
31070 +                       retval |= dwc_otg_handle_usb_suspend_intr(core_if);
31071 +               }
31072 +#ifdef CONFIG_USB_DWC_OTG_LPM
31073 +               if (gintsts.b.lpmtranrcvd) {
31074 +                       retval |= dwc_otg_handle_lpm_intr(core_if);
31075 +               }
31076 +#endif
31077 +               if (gintsts.b.restoredone) {
31078 +                       gintsts.d32 = 0;
31079 +                       if (core_if->power_down == 2)
31080 +                               core_if->hibernation_suspend = -1;
31081 +                       else if (core_if->power_down == 3 && core_if->xhib == 2) {
31082 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
31083 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
31084 +                               dctl_data_t dctl = {.d32 = 0 };
31085 +
31086 +                               DWC_WRITE_REG32(&core_if->core_global_regs->
31087 +                                               gintsts, 0xFFFFFFFF);
31088 +
31089 +                               DWC_DEBUGPL(DBG_ANY,
31090 +                                           "RESTORE DONE generated\n");
31091 +
31092 +                               gpwrdn.b.restore = 1;
31093 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
31094 +                               dwc_udelay(10);
31095 +
31096 +                               pcgcctl.b.rstpdwnmodule = 1;
31097 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31098 +
31099 +                               DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);
31100 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);
31101 +                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);
31102 +                               dwc_udelay(50);
31103 +
31104 +                               dctl.b.pwronprgdone = 1;
31105 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
31106 +                               dwc_udelay(10);
31107 +
31108 +                               dwc_otg_restore_global_regs(core_if);
31109 +                               dwc_otg_restore_dev_regs(core_if, 0);
31110 +
31111 +                               dctl.d32 = 0;
31112 +                               dctl.b.pwronprgdone = 1;
31113 +                               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
31114 +                               dwc_udelay(10);
31115 +
31116 +                               pcgcctl.d32 = 0;
31117 +                               pcgcctl.b.enbl_extnd_hiber = 1;
31118 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
31119 +
31120 +                               /* The core will be in ON STATE */
31121 +                               core_if->lx_state = DWC_OTG_L0;
31122 +                               core_if->xhib = 0;
31123 +
31124 +                               DWC_SPINUNLOCK(core_if->lock);
31125 +                               if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
31126 +                                       core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
31127 +                               }
31128 +                               DWC_SPINLOCK(core_if->lock);
31129 +
31130 +                       }
31131 +
31132 +                       gintsts.b.restoredone = 1;
31133 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31134 +                       DWC_PRINTF(" --Restore done interrupt received-- \n");
31135 +                       retval |= 1;
31136 +               }
31137 +               if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
31138 +                       /* The port interrupt occurs while in device mode with HPRT0
31139 +                        * Port Enable/Disable.
31140 +                        */
31141 +                       gintsts.d32 = 0;
31142 +                       gintsts.b.portintr = 1;
31143 +                       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
31144 +                       retval |= 1;
31145 +
31146 +               }
31147 +       } else {
31148 +               DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
31149 +
31150 +               if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
31151 +                       CLEAR_GPWRDN_INTR(core_if, disconn_det);
31152 +                       if (gpwrdn.b.linestate == 0) {
31153 +                               dwc_otg_handle_pwrdn_disconnect_intr(core_if);
31154 +                       } else {
31155 +                               DWC_PRINTF("Disconnect detected while linestate is not 0\n");
31156 +                       }
31157 +
31158 +                       retval |= 1;
31159 +               }
31160 +               if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
31161 +                       CLEAR_GPWRDN_INTR(core_if, lnstschng);
31162 +                       /* remote wakeup from hibernation */
31163 +                       if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
31164 +                               dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
31165 +                       } else {
31166 +                               DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
31167 +                       }
31168 +                       retval |= 1;
31169 +               }
31170 +               if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
31171 +                       CLEAR_GPWRDN_INTR(core_if, rst_det);
31172 +                       if (gpwrdn.b.linestate == 0) {
31173 +                               DWC_PRINTF("Reset detected\n");
31174 +                               retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
31175 +                       }
31176 +               }
31177 +               if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
31178 +                       CLEAR_GPWRDN_INTR(core_if, srp_det);
31179 +                       dwc_otg_handle_pwrdn_srp_intr(core_if);
31180 +                       retval |= 1;
31181 +               }
31182 +       }
31183 +       /* Handle ADP interrupt here */
31184 +       if (gpwrdn.b.adp_int) {
31185 +               DWC_PRINTF("ADP interrupt\n");
31186 +               CLEAR_GPWRDN_INTR(core_if, adp_int);
31187 +               dwc_otg_adp_handle_intr(core_if);
31188 +               retval |= 1;
31189 +       }
31190 +       if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
31191 +               DWC_PRINTF("STS CHNG interrupt asserted\n");
31192 +               CLEAR_GPWRDN_INTR(core_if, sts_chngint);
31193 +               dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
31194 +
31195 +               retval |= 1;
31196 +       }
31197 +       if (core_if->lock)
31198 +               DWC_SPINUNLOCK(core_if->lock);
31199 +
31200 +       return retval;
31201 +}
31202 --- /dev/null
31203 +++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
31204 @@ -0,0 +1,705 @@
31205 +/* ==========================================================================
31206 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
31207 + * $Revision: #13 $
31208 + * $Date: 2012/08/10 $
31209 + * $Change: 2047372 $
31210 + *
31211 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31212 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31213 + * otherwise expressly agreed to in writing between Synopsys and you.
31214 + *
31215 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31216 + * any End User Software License Agreement or Agreement for Licensed Product
31217 + * with Synopsys or any supplement thereto. You are permitted to use and
31218 + * redistribute this Software in source and binary forms, with or without
31219 + * modification, provided that redistributions of source code must retain this
31220 + * notice. You may not view, use, disclose, copy or distribute this file or
31221 + * any information contained herein except pursuant to this license grant from
31222 + * Synopsys. If you do not agree with this notice, including the disclaimer
31223 + * below, then you are not authorized to use the Software.
31224 + *
31225 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31226 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31227 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31228 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31229 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31230 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31231 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31232 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31233 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31234 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31235 + * DAMAGE.
31236 + * ========================================================================== */
31237 +#if !defined(__DWC_CORE_IF_H__)
31238 +#define __DWC_CORE_IF_H__
31239 +
31240 +#include "dwc_os.h"
31241 +
31242 +/** @file
31243 + * This file defines DWC_OTG Core API
31244 + */
31245 +
31246 +struct dwc_otg_core_if;
31247 +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
31248 +
31249 +/** Maximum number of Periodic FIFOs */
31250 +#define MAX_PERIO_FIFOS 15
31251 +/** Maximum number of Periodic FIFOs */
31252 +#define MAX_TX_FIFOS 15
31253 +
31254 +/** Maximum number of Endpoints/HostChannels */
31255 +#define MAX_EPS_CHANNELS 16
31256 +
31257 +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
31258 +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
31259 +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
31260 +
31261 +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
31262 +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
31263 +
31264 +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
31265 +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
31266 +
31267 +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
31268 +
31269 +/** This function should be called on every hardware interrupt. */
31270 +extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
31271 +
31272 +/** @name OTG Core Parameters */
31273 +/** @{ */
31274 +
31275 +/**
31276 + * Specifies the OTG capabilities. The driver will automatically
31277 + * detect the value for this parameter if none is specified.
31278 + * 0 - HNP and SRP capable (default)
31279 + * 1 - SRP Only capable
31280 + * 2 - No HNP/SRP capable
31281 + */
31282 +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
31283 +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
31284 +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
31285 +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
31286 +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
31287 +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
31288 +
31289 +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
31290 +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
31291 +#define dwc_param_opt_default 1
31292 +
31293 +/**
31294 + * Specifies whether to use slave or DMA mode for accessing the data
31295 + * FIFOs. The driver will automatically detect the value for this
31296 + * parameter if none is specified.
31297 + * 0 - Slave
31298 + * 1 - DMA (default, if available)
31299 + */
31300 +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
31301 +                                       int32_t val);
31302 +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
31303 +#define dwc_param_dma_enable_default 1
31304 +
31305 +/**
31306 + * When DMA mode is enabled specifies whether to use
31307 + * address DMA or DMA Descritor mode for accessing the data
31308 + * FIFOs in device mode. The driver will automatically detect
31309 + * the value for this parameter if none is specified.
31310 + * 0 - address DMA
31311 + * 1 - DMA Descriptor(default, if available)
31312 + */
31313 +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
31314 +                                            int32_t val);
31315 +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
31316 +//#define dwc_param_dma_desc_enable_default 1
31317 +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
31318 +
31319 +/** The DMA Burst size (applicable only for External DMA
31320 + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
31321 + */
31322 +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
31323 +                                           int32_t val);
31324 +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
31325 +#define dwc_param_dma_burst_size_default 32
31326 +
31327 +/**
31328 + * Specifies the maximum speed of operation in host and device mode.
31329 + * The actual speed depends on the speed of the attached device and
31330 + * the value of phy_type. The actual speed depends on the speed of the
31331 + * attached device.
31332 + * 0 - High Speed (default)
31333 + * 1 - Full Speed
31334 + */
31335 +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
31336 +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
31337 +#define dwc_param_speed_default 0
31338 +#define DWC_SPEED_PARAM_HIGH 0
31339 +#define DWC_SPEED_PARAM_FULL 1
31340 +
31341 +/** Specifies whether low power mode is supported when attached
31342 + *     to a Full Speed or Low Speed device in host mode.
31343 + * 0 - Don't support low power mode (default)
31344 + * 1 - Support low power mode
31345 + */
31346 +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
31347 +                                                         core_if, int32_t val);
31348 +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
31349 +                                                             * core_if);
31350 +#define dwc_param_host_support_fs_ls_low_power_default 0
31351 +
31352 +/** Specifies the PHY clock rate in low power mode when connected to a
31353 + * Low Speed device in host mode. This parameter is applicable only if
31354 + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
31355 + * then defaults to 6 MHZ otherwise 48 MHZ.
31356 + *
31357 + * 0 - 48 MHz
31358 + * 1 - 6 MHz
31359 + */
31360 +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31361 +                                                      core_if, int32_t val);
31362 +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
31363 +                                                          core_if);
31364 +#define dwc_param_host_ls_low_power_phy_clk_default 0
31365 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
31366 +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
31367 +
31368 +/**
31369 + * 0 - Use cC FIFO size parameters
31370 + * 1 - Allow dynamic FIFO sizing (default)
31371 + */
31372 +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
31373 +                                                int32_t val);
31374 +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
31375 +                                                    core_if);
31376 +#define dwc_param_enable_dynamic_fifo_default 1
31377 +
31378 +/** Total number of 4-byte words in the data FIFO memory. This
31379 + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
31380 + * Tx FIFOs.
31381 + * 32 to 32768 (default 8192)
31382 + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
31383 + */
31384 +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
31385 +                                           int32_t val);
31386 +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
31387 +//#define dwc_param_data_fifo_size_default 8192
31388 +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
31389 +
31390 +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
31391 + * FIFO sizing is enabled.
31392 + * 16 to 32768 (default 1064)
31393 + */
31394 +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
31395 +                                             int32_t val);
31396 +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
31397 +#define dwc_param_dev_rx_fifo_size_default 1064
31398 +
31399 +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
31400 + * when dynamic FIFO sizing is enabled.
31401 + * 16 to 32768 (default 1024)
31402 + */
31403 +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31404 +                                                    core_if, int32_t val);
31405 +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
31406 +                                                        core_if);
31407 +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
31408 +
31409 +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
31410 + * mode when dynamic FIFO sizing is enabled.
31411 + * 4 to 768 (default 256)
31412 + */
31413 +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
31414 +                                                   int32_t val, int fifo_num);
31415 +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
31416 +                                                       core_if, int fifo_num);
31417 +#define dwc_param_dev_perio_tx_fifo_size_default 256
31418 +
31419 +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
31420 + * FIFO sizing is enabled.
31421 + * 16 to 32768 (default 1024)
31422 + */
31423 +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
31424 +                                              int32_t val);
31425 +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
31426 +//#define dwc_param_host_rx_fifo_size_default 1024
31427 +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
31428 +
31429 +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
31430 + * when Dynamic FIFO sizing is enabled in the core.
31431 + * 16 to 32768 (default 1024)
31432 + */
31433 +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31434 +                                                     core_if, int32_t val);
31435 +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
31436 +                                                         core_if);
31437 +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
31438 +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
31439 +
31440 +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
31441 + * FIFO sizing is enabled.
31442 + * 16 to 32768 (default 1024)
31443 + */
31444 +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31445 +                                                    core_if, int32_t val);
31446 +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
31447 +                                                        core_if);
31448 +//#define dwc_param_host_perio_tx_fifo_size_default 1024
31449 +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
31450 +
31451 +/** The maximum transfer size supported in bytes.
31452 + * 2047 to 65,535  (default 65,535)
31453 + */
31454 +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
31455 +                                              int32_t val);
31456 +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
31457 +#define dwc_param_max_transfer_size_default 65535
31458 +
31459 +/** The maximum number of packets in a transfer.
31460 + * 15 to 511  (default 511)
31461 + */
31462 +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
31463 +                                             int32_t val);
31464 +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
31465 +#define dwc_param_max_packet_count_default 511
31466 +
31467 +/** The number of host channel registers to use.
31468 + * 1 to 16 (default 12)
31469 + * Note: The FPGA configuration supports a maximum of 12 host channels.
31470 + */
31471 +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
31472 +                                          int32_t val);
31473 +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
31474 +//#define dwc_param_host_channels_default 12
31475 +#define dwc_param_host_channels_default 8 // Broadcom BCM2708
31476 +
31477 +/** The number of endpoints in addition to EP0 available for device
31478 + * mode operations.
31479 + * 1 to 15 (default 6 IN and OUT)
31480 + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
31481 + * endpoints in addition to EP0.
31482 + */
31483 +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
31484 +                                          int32_t val);
31485 +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
31486 +#define dwc_param_dev_endpoints_default 6
31487 +
31488 +/**
31489 + * Specifies the type of PHY interface to use. By default, the driver
31490 + * will automatically detect the phy_type.
31491 + *
31492 + * 0 - Full Speed PHY
31493 + * 1 - UTMI+ (default)
31494 + * 2 - ULPI
31495 + */
31496 +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
31497 +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
31498 +#define DWC_PHY_TYPE_PARAM_FS 0
31499 +#define DWC_PHY_TYPE_PARAM_UTMI 1
31500 +#define DWC_PHY_TYPE_PARAM_ULPI 2
31501 +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
31502 +
31503 +/**
31504 + * Specifies the UTMI+ Data Width. This parameter is
31505 + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
31506 + * PHY_TYPE, this parameter indicates the data width between
31507 + * the MAC and the ULPI Wrapper.) Also, this parameter is
31508 + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
31509 + * to "8 and 16 bits", meaning that the core has been
31510 + * configured to work at either data path width.
31511 + *
31512 + * 8 or 16 bits (default 16)
31513 + */
31514 +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
31515 +                                           int32_t val);
31516 +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
31517 +//#define dwc_param_phy_utmi_width_default 16
31518 +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708
31519 +
31520 +/**
31521 + * Specifies whether the ULPI operates at double or single
31522 + * data rate. This parameter is only applicable if PHY_TYPE is
31523 + * ULPI.
31524 + *
31525 + * 0 - single data rate ULPI interface with 8 bit wide data
31526 + * bus (default)
31527 + * 1 - double data rate ULPI interface with 4 bit wide data
31528 + * bus
31529 + */
31530 +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
31531 +                                         int32_t val);
31532 +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
31533 +#define dwc_param_phy_ulpi_ddr_default 0
31534 +
31535 +/**
31536 + * Specifies whether to use the internal or external supply to
31537 + * drive the vbus with a ULPI phy.
31538 + */
31539 +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
31540 +                                              int32_t val);
31541 +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
31542 +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
31543 +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
31544 +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
31545 +
31546 +/**
31547 + * Specifies whether to use the I2Cinterface for full speed PHY. This
31548 + * parameter is only applicable if PHY_TYPE is FS.
31549 + * 0 - No (default)
31550 + * 1 - Yes
31551 + */
31552 +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
31553 +                                       int32_t val);
31554 +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
31555 +#define dwc_param_i2c_enable_default 0
31556 +
31557 +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
31558 +                                       int32_t val);
31559 +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
31560 +#define dwc_param_ulpi_fs_ls_default 0
31561 +
31562 +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
31563 +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
31564 +#define dwc_param_ts_dline_default 0
31565 +
31566 +/**
31567 + * Specifies whether dedicated transmit FIFOs are
31568 + * enabled for non periodic IN endpoints in device mode
31569 + * 0 - No
31570 + * 1 - Yes
31571 + */
31572 +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
31573 +                                                int32_t val);
31574 +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
31575 +                                                    core_if);
31576 +#define dwc_param_en_multiple_tx_fifo_default 1
31577 +
31578 +/** Number of 4-byte words in each of the Tx FIFOs in device
31579 + * mode when dynamic FIFO sizing is enabled.
31580 + * 4 to 768 (default 256)
31581 + */
31582 +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31583 +                                             int fifo_num, int32_t val);
31584 +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
31585 +                                                 int fifo_num);
31586 +#define dwc_param_dev_tx_fifo_size_default 768
31587 +
31588 +/** Thresholding enable flag-
31589 + * bit 0 - enable non-ISO Tx thresholding
31590 + * bit 1 - enable ISO Tx thresholding
31591 + * bit 2 - enable Rx thresholding
31592 + */
31593 +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
31594 +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
31595 +#define dwc_param_thr_ctl_default 0
31596 +
31597 +/** Thresholding length for Tx
31598 + * FIFOs in 32 bit DWORDs
31599 + */
31600 +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
31601 +                                          int32_t val);
31602 +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
31603 +#define dwc_param_tx_thr_length_default 64
31604 +
31605 +/** Thresholding length for Rx
31606 + *     FIFOs in 32 bit DWORDs
31607 + */
31608 +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
31609 +                                          int32_t val);
31610 +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
31611 +#define dwc_param_rx_thr_length_default 64
31612 +
31613 +/**
31614 + * Specifies whether LPM (Link Power Management) support is enabled
31615 + */
31616 +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
31617 +                                       int32_t val);
31618 +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
31619 +#define dwc_param_lpm_enable_default 1
31620 +
31621 +/**
31622 + * Specifies whether PTI enhancement is enabled
31623 + */
31624 +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
31625 +                                       int32_t val);
31626 +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
31627 +#define dwc_param_pti_enable_default 0
31628 +
31629 +/**
31630 + * Specifies whether MPI enhancement is enabled
31631 + */
31632 +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
31633 +                                       int32_t val);
31634 +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
31635 +#define dwc_param_mpi_enable_default 0
31636 +
31637 +/**
31638 + * Specifies whether ADP capability is enabled
31639 + */
31640 +extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,
31641 +                                       int32_t val);
31642 +extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);
31643 +#define dwc_param_adp_enable_default 0
31644 +
31645 +/**
31646 + * Specifies whether IC_USB capability is enabled
31647 + */
31648 +
31649 +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
31650 +                                       int32_t val);
31651 +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
31652 +#define dwc_param_ic_usb_cap_default 0
31653 +
31654 +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,
31655 +                                          int32_t val);
31656 +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
31657 +#define dwc_param_ahb_thr_ratio_default 0
31658 +
31659 +extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,
31660 +                                       int32_t val);
31661 +extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);
31662 +#define dwc_param_power_down_default 0
31663 +
31664 +extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,
31665 +                                       int32_t val);
31666 +extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);
31667 +#define dwc_param_reload_ctl_default 0
31668 +
31669 +extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,
31670 +                                                                               int32_t val);
31671 +extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
31672 +#define dwc_param_dev_out_nak_default 0
31673 +
31674 +extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
31675 +                                                                                int32_t val);
31676 +extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
31677 +#define dwc_param_cont_on_bna_default 0
31678 +
31679 +extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
31680 +                                                                                int32_t val);
31681 +extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
31682 +#define dwc_param_ahb_single_default 0
31683 +
31684 +extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
31685 +extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
31686 +#define dwc_param_otg_ver_default 0
31687 +
31688 +/** @} */
31689 +
31690 +/** @name Access to registers and bit-fields */
31691 +
31692 +/**
31693 + * Dump core registers and SPRAM
31694 + */
31695 +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
31696 +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
31697 +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
31698 +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
31699 +
31700 +/**
31701 + * Get host negotiation status.
31702 + */
31703 +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
31704 +
31705 +/**
31706 + * Get srp status
31707 + */
31708 +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
31709 +
31710 +/**
31711 + * Set hnpreq bit in the GOTGCTL register.
31712 + */
31713 +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
31714 +
31715 +/**
31716 + * Get Content of SNPSID register.
31717 + */
31718 +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
31719 +
31720 +/**
31721 + * Get current mode.
31722 + * Returns 0 if in device mode, and 1 if in host mode.
31723 + */
31724 +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
31725 +
31726 +/**
31727 + * Get value of hnpcapable field in the GUSBCFG register
31728 + */
31729 +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
31730 +/**
31731 + * Set value of hnpcapable field in the GUSBCFG register
31732 + */
31733 +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31734 +
31735 +/**
31736 + * Get value of srpcapable field in the GUSBCFG register
31737 + */
31738 +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
31739 +/**
31740 + * Set value of srpcapable field in the GUSBCFG register
31741 + */
31742 +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
31743 +
31744 +/**
31745 + * Get value of devspeed field in the DCFG register
31746 + */
31747 +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
31748 +/**
31749 + * Set value of devspeed field in the DCFG register
31750 + */
31751 +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
31752 +
31753 +/**
31754 + * Get the value of busconnected field from the HPRT0 register
31755 + */
31756 +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
31757 +
31758 +/**
31759 + * Gets the device enumeration Speed.
31760 + */
31761 +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
31762 +
31763 +/**
31764 + * Get value of prtpwr field from the HPRT0 register
31765 + */
31766 +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
31767 +
31768 +/**
31769 + * Get value of flag indicating core state - hibernated or not
31770 + */
31771 +extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);
31772 +
31773 +/**
31774 + * Set value of prtpwr field from the HPRT0 register
31775 + */
31776 +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
31777 +
31778 +/**
31779 + * Get value of prtsusp field from the HPRT0 regsiter
31780 + */
31781 +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
31782 +/**
31783 + * Set value of prtpwr field from the HPRT0 register
31784 + */
31785 +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
31786 +
31787 +/**
31788 + * Get value of ModeChTimEn field from the HCFG regsiter
31789 + */
31790 +extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);
31791 +/**
31792 + * Set value of ModeChTimEn field from the HCFG regsiter
31793 + */
31794 +extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);
31795 +
31796 +/**
31797 + * Get value of Fram Interval field from the HFIR regsiter
31798 + */
31799 +extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);
31800 +/**
31801 + * Set value of Frame Interval field from the HFIR regsiter
31802 + */
31803 +extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);
31804 +
31805 +/**
31806 + * Set value of prtres field from the HPRT0 register
31807 + *FIXME Remove?
31808 + */
31809 +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
31810 +
31811 +/**
31812 + * Get value of rmtwkupsig bit in DCTL register
31813 + */
31814 +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
31815 +
31816 +/**
31817 + * Get value of prt_sleep_sts field from the GLPMCFG register
31818 + */
31819 +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
31820 +
31821 +/**
31822 + * Get value of rem_wkup_en field from the GLPMCFG register
31823 + */
31824 +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
31825 +
31826 +/**
31827 + * Get value of appl_resp field from the GLPMCFG register
31828 + */
31829 +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
31830 +/**
31831 + * Set value of appl_resp field from the GLPMCFG register
31832 + */
31833 +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
31834 +
31835 +/**
31836 + * Get value of hsic_connect field from the GLPMCFG register
31837 + */
31838 +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
31839 +/**
31840 + * Set value of hsic_connect field from the GLPMCFG register
31841 + */
31842 +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
31843 +
31844 +/**
31845 + * Get value of inv_sel_hsic field from the GLPMCFG register.
31846 + */
31847 +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
31848 +/**
31849 + * Set value of inv_sel_hsic field from the GLPMFG register.
31850 + */
31851 +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
31852 +
31853 +/*
31854 + * Some functions for accessing registers
31855 + */
31856 +
31857 +/**
31858 + *  GOTGCTL register
31859 + */
31860 +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
31861 +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
31862 +
31863 +/**
31864 + * GUSBCFG register
31865 + */
31866 +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
31867 +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
31868 +
31869 +/**
31870 + * GRXFSIZ register
31871 + */
31872 +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
31873 +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31874 +
31875 +/**
31876 + * GNPTXFSIZ register
31877 + */
31878 +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
31879 +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
31880 +
31881 +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
31882 +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
31883 +
31884 +/**
31885 + * GGPIO register
31886 + */
31887 +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
31888 +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
31889 +
31890 +/**
31891 + * GUID register
31892 + */
31893 +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
31894 +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
31895 +
31896 +/**
31897 + * HPRT0 register
31898 + */
31899 +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
31900 +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
31901 +
31902 +/**
31903 + * GHPTXFSIZE
31904 + */
31905 +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
31906 +
31907 +/** @} */
31908 +
31909 +#endif                         /* __DWC_CORE_IF_H__ */
31910 --- /dev/null
31911 +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
31912 @@ -0,0 +1,116 @@
31913 +/* ==========================================================================
31914 + *
31915 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
31916 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
31917 + * otherwise expressly agreed to in writing between Synopsys and you.
31918 + *
31919 + * The Software IS NOT an item of Licensed Software or Licensed Product under
31920 + * any End User Software License Agreement or Agreement for Licensed Product
31921 + * with Synopsys or any supplement thereto. You are permitted to use and
31922 + * redistribute this Software in source and binary forms, with or without
31923 + * modification, provided that redistributions of source code must retain this
31924 + * notice. You may not view, use, disclose, copy or distribute this file or
31925 + * any information contained herein except pursuant to this license grant from
31926 + * Synopsys. If you do not agree with this notice, including the disclaimer
31927 + * below, then you are not authorized to use the Software.
31928 + *
31929 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
31930 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31931 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31932 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
31933 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31934 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31935 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31936 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31937 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31938 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31939 + * DAMAGE.
31940 + * ========================================================================== */
31941 +
31942 +#ifndef __DWC_OTG_DBG_H__
31943 +#define __DWC_OTG_DBG_H__
31944 +
31945 +/** @file
31946 + * This file defines debug levels.
31947 + * Debugging support vanishes in non-debug builds.
31948 + */
31949 +
31950 +/**
31951 + * The Debug Level bit-mask variable.
31952 + */
31953 +extern uint32_t g_dbg_lvl;
31954 +/**
31955 + * Set the Debug Level variable.
31956 + */
31957 +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
31958 +{
31959 +       uint32_t old = g_dbg_lvl;
31960 +       g_dbg_lvl = new;
31961 +       return old;
31962 +}
31963 +
31964 +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
31965 +#define DBG_CIL                (0x2)
31966 +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
31967 + * messages */
31968 +#define DBG_CILV       (0x20)
31969 +/**  When debug level has the DBG_PCD bit set, display PCD (Device) debug
31970 + *  messages */
31971 +#define DBG_PCD                (0x4)
31972 +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
31973 + * messages */
31974 +#define DBG_PCDV       (0x40)
31975 +/** When debug level has the DBG_HCD bit set, display Host debug messages */
31976 +#define DBG_HCD                (0x8)
31977 +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
31978 + * messages */
31979 +#define DBG_HCDV       (0x80)
31980 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
31981 + *  mode. */
31982 +#define DBG_HCD_URB    (0x800)
31983 +/** When debug level has the DBG_HCDI bit set, display host interrupt
31984 + *  messages. */
31985 +#define DBG_HCDI       (0x1000)
31986 +
31987 +/** When debug level has any bit set, display debug messages */
31988 +#define DBG_ANY                (0xFF)
31989 +
31990 +/** All debug messages off */
31991 +#define DBG_OFF                0
31992 +
31993 +/** Prefix string for DWC_DEBUG print macros. */
31994 +#define USB_DWC "DWC_otg: "
31995 +
31996 +/**
31997 + * Print a debug message when the Global debug level variable contains
31998 + * the bit defined in <code>lvl</code>.
31999 + *
32000 + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
32001 + * @param[in] x - like printf
32002 + *
32003 + *    Example:<p>
32004 + * <code>
32005 + *      DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
32006 + * </code>
32007 + * <br>
32008 + * results in:<br>
32009 + * <code>
32010 + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
32011 + * </code>
32012 + */
32013 +#ifdef DEBUG
32014 +
32015 +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
32016 +# define DWC_DEBUGP(x...)      DWC_DEBUGPL(DBG_ANY, x )
32017 +
32018 +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
32019 +
32020 +#else
32021 +
32022 +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
32023 +# define DWC_DEBUGP(x...)
32024 +
32025 +# define CHK_DEBUG_LEVEL(level) (0)
32026 +
32027 +#endif /*DEBUG*/
32028 +#endif
32029 --- /dev/null
32030 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
32031 @@ -0,0 +1,1700 @@
32032 +/* ==========================================================================
32033 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
32034 + * $Revision: #92 $
32035 + * $Date: 2012/08/10 $
32036 + * $Change: 2047372 $
32037 + *
32038 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
32039 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
32040 + * otherwise expressly agreed to in writing between Synopsys and you.
32041 + *
32042 + * The Software IS NOT an item of Licensed Software or Licensed Product under
32043 + * any End User Software License Agreement or Agreement for Licensed Product
32044 + * with Synopsys or any supplement thereto. You are permitted to use and
32045 + * redistribute this Software in source and binary forms, with or without
32046 + * modification, provided that redistributions of source code must retain this
32047 + * notice. You may not view, use, disclose, copy or distribute this file or
32048 + * any information contained herein except pursuant to this license grant from
32049 + * Synopsys. If you do not agree with this notice, including the disclaimer
32050 + * below, then you are not authorized to use the Software.
32051 + *
32052 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
32053 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32054 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32055 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
32056 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32057 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32058 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32059 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32060 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32061 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32062 + * DAMAGE.
32063 + * ========================================================================== */
32064 +
32065 +/** @file
32066 + * The dwc_otg_driver module provides the initialization and cleanup entry
32067 + * points for the DWC_otg driver. This module will be dynamically installed
32068 + * after Linux is booted using the insmod command. When the module is
32069 + * installed, the dwc_otg_driver_init function is called. When the module is
32070 + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
32071 + *
32072 + * This module also defines a data structure for the dwc_otg_driver, which is
32073 + * used in conjunction with the standard ARM lm_device structure. These
32074 + * structures allow the OTG driver to comply with the standard Linux driver
32075 + * model in which devices and drivers are registered with a bus driver. This
32076 + * has the benefit that Linux can expose attributes of the driver and device
32077 + * in its special sysfs file system. Users can then read or write files in
32078 + * this file system to perform diagnostics on the driver components or the
32079 + * device.
32080 + */
32081 +
32082 +#include "dwc_otg_os_dep.h"
32083 +#include "dwc_os.h"
32084 +#include "dwc_otg_dbg.h"
32085 +#include "dwc_otg_driver.h"
32086 +#include "dwc_otg_attr.h"
32087 +#include "dwc_otg_core_if.h"
32088 +#include "dwc_otg_pcd_if.h"
32089 +#include "dwc_otg_hcd_if.h"
32090 +
32091 +#define DWC_DRIVER_VERSION     "3.00a 10-AUG-2012"
32092 +#define DWC_DRIVER_DESC                "HS OTG USB Controller driver"
32093 +
32094 +bool microframe_schedule=true;
32095 +
32096 +static const char dwc_driver_name[] = "dwc_otg";
32097 +
32098 +extern int pcd_init(
32099 +#ifdef LM_INTERFACE
32100 +                          struct lm_device *_dev
32101 +#elif  defined(PCI_INTERFACE)
32102 +                          struct pci_dev *_dev
32103 +#elif  defined(PLATFORM_INTERFACE)
32104 +       struct platform_device *dev
32105 +#endif
32106 +    );
32107 +extern int hcd_init(
32108 +#ifdef LM_INTERFACE
32109 +                          struct lm_device *_dev
32110 +#elif  defined(PCI_INTERFACE)
32111 +                          struct pci_dev *_dev
32112 +#elif  defined(PLATFORM_INTERFACE)
32113 +       struct platform_device *dev
32114 +#endif
32115 +    );
32116 +
32117 +extern int pcd_remove(
32118 +#ifdef LM_INTERFACE
32119 +                            struct lm_device *_dev
32120 +#elif  defined(PCI_INTERFACE)
32121 +                            struct pci_dev *_dev
32122 +#elif  defined(PLATFORM_INTERFACE)
32123 +       struct platform_device *_dev
32124 +#endif
32125 +    );
32126 +
32127 +extern void hcd_remove(
32128 +#ifdef LM_INTERFACE
32129 +                             struct lm_device *_dev
32130 +#elif  defined(PCI_INTERFACE)
32131 +                             struct pci_dev *_dev
32132 +#elif  defined(PLATFORM_INTERFACE)
32133 +       struct platform_device *_dev
32134 +#endif
32135 +    );
32136 +
32137 +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
32138 +
32139 +/*-------------------------------------------------------------------------*/
32140 +/* Encapsulate the module parameter settings */
32141 +
32142 +struct dwc_otg_driver_module_params {
32143 +       int32_t opt;
32144 +       int32_t otg_cap;
32145 +       int32_t dma_enable;
32146 +       int32_t dma_desc_enable;
32147 +       int32_t dma_burst_size;
32148 +       int32_t speed;
32149 +       int32_t host_support_fs_ls_low_power;
32150 +       int32_t host_ls_low_power_phy_clk;
32151 +       int32_t enable_dynamic_fifo;
32152 +       int32_t data_fifo_size;
32153 +       int32_t dev_rx_fifo_size;
32154 +       int32_t dev_nperio_tx_fifo_size;
32155 +       uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
32156 +       int32_t host_rx_fifo_size;
32157 +       int32_t host_nperio_tx_fifo_size;
32158 +       int32_t host_perio_tx_fifo_size;
32159 +       int32_t max_transfer_size;
32160 +       int32_t max_packet_count;
32161 +       int32_t host_channels;
32162 +       int32_t dev_endpoints;
32163 +       int32_t phy_type;
32164 +       int32_t phy_utmi_width;
32165 +       int32_t phy_ulpi_ddr;
32166 +       int32_t phy_ulpi_ext_vbus;
32167 +       int32_t i2c_enable;
32168 +       int32_t ulpi_fs_ls;
32169 +       int32_t ts_dline;
32170 +       int32_t en_multiple_tx_fifo;
32171 +       uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
32172 +       uint32_t thr_ctl;
32173 +       uint32_t tx_thr_length;
32174 +       uint32_t rx_thr_length;
32175 +       int32_t pti_enable;
32176 +       int32_t mpi_enable;
32177 +       int32_t lpm_enable;
32178 +       int32_t ic_usb_cap;
32179 +       int32_t ahb_thr_ratio;
32180 +       int32_t power_down;
32181 +       int32_t reload_ctl;
32182 +       int32_t dev_out_nak;
32183 +       int32_t cont_on_bna;
32184 +       int32_t ahb_single;
32185 +       int32_t otg_ver;
32186 +       int32_t adp_enable;
32187 +};
32188 +
32189 +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
32190 +       .opt = -1,
32191 +       .otg_cap = -1,
32192 +       .dma_enable = -1,
32193 +       .dma_desc_enable = -1,
32194 +       .dma_burst_size = -1,
32195 +       .speed = -1,
32196 +       .host_support_fs_ls_low_power = -1,
32197 +       .host_ls_low_power_phy_clk = -1,
32198 +       .enable_dynamic_fifo = -1,
32199 +       .data_fifo_size = -1,
32200 +       .dev_rx_fifo_size = -1,
32201 +       .dev_nperio_tx_fifo_size = -1,
32202 +       .dev_perio_tx_fifo_size = {
32203 +                                  /* dev_perio_tx_fifo_size_1 */
32204 +                                  -1,
32205 +                                  -1,
32206 +                                  -1,
32207 +                                  -1,
32208 +                                  -1,
32209 +                                  -1,
32210 +                                  -1,
32211 +                                  -1,
32212 +                                  -1,
32213 +                                  -1,
32214 +                                  -1,
32215 +                                  -1,
32216 +                                  -1,
32217 +                                  -1,
32218 +                                  -1
32219 +                                  /* 15 */
32220 +                                  },
32221 +       .host_rx_fifo_size = -1,
32222 +       .host_nperio_tx_fifo_size = -1,
32223 +       .host_perio_tx_fifo_size = -1,
32224 +       .max_transfer_size = -1,
32225 +       .max_packet_count = -1,
32226 +       .host_channels = -1,
32227 +       .dev_endpoints = -1,
32228 +       .phy_type = -1,
32229 +       .phy_utmi_width = -1,
32230 +       .phy_ulpi_ddr = -1,
32231 +       .phy_ulpi_ext_vbus = -1,
32232 +       .i2c_enable = -1,
32233 +       .ulpi_fs_ls = -1,
32234 +       .ts_dline = -1,
32235 +       .en_multiple_tx_fifo = -1,
32236 +       .dev_tx_fifo_size = {
32237 +                            /* dev_tx_fifo_size */
32238 +                            -1,
32239 +                            -1,
32240 +                            -1,
32241 +                            -1,
32242 +                            -1,
32243 +                            -1,
32244 +                            -1,
32245 +                            -1,
32246 +                            -1,
32247 +                            -1,
32248 +                            -1,
32249 +                            -1,
32250 +                            -1,
32251 +                            -1,
32252 +                            -1
32253 +                            /* 15 */
32254 +                            },
32255 +       .thr_ctl = -1,
32256 +       .tx_thr_length = -1,
32257 +       .rx_thr_length = -1,
32258 +       .pti_enable = -1,
32259 +       .mpi_enable = -1,
32260 +       .lpm_enable = 0,
32261 +       .ic_usb_cap = -1,
32262 +       .ahb_thr_ratio = -1,
32263 +       .power_down = -1,
32264 +       .reload_ctl = -1,
32265 +       .dev_out_nak = -1,
32266 +       .cont_on_bna = -1,
32267 +       .ahb_single = -1,
32268 +       .otg_ver = -1,
32269 +       .adp_enable = -1,
32270 +};
32271 +
32272 +/**
32273 + * This function shows the Driver Version.
32274 + */
32275 +static ssize_t version_show(struct device_driver *dev, char *buf)
32276 +{
32277 +       return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
32278 +                       DWC_DRIVER_VERSION);
32279 +}
32280 +
32281 +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
32282 +
32283 +/**
32284 + * Global Debug Level Mask.
32285 + */
32286 +uint32_t g_dbg_lvl = 0;                /* OFF */
32287 +
32288 +/**
32289 + * This function shows the driver Debug Level.
32290 + */
32291 +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
32292 +{
32293 +       return sprintf(buf, "0x%0x\n", g_dbg_lvl);
32294 +}
32295 +
32296 +/**
32297 + * This function stores the driver Debug Level.
32298 + */
32299 +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
32300 +                              size_t count)
32301 +{
32302 +       g_dbg_lvl = simple_strtoul(buf, NULL, 16);
32303 +       return count;
32304 +}
32305 +
32306 +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
32307 +                  dbg_level_store);
32308 +
32309 +/**
32310 + * This function is called during module intialization
32311 + * to pass module parameters to the DWC_OTG CORE.
32312 + */
32313 +static int set_parameters(dwc_otg_core_if_t * core_if)
32314 +{
32315 +       int retval = 0;
32316 +       int i;
32317 +
32318 +       if (dwc_otg_module_params.otg_cap != -1) {
32319 +               retval +=
32320 +                   dwc_otg_set_param_otg_cap(core_if,
32321 +                                             dwc_otg_module_params.otg_cap);
32322 +       }
32323 +       if (dwc_otg_module_params.dma_enable != -1) {
32324 +               retval +=
32325 +                   dwc_otg_set_param_dma_enable(core_if,
32326 +                                                dwc_otg_module_params.
32327 +                                                dma_enable);
32328 +       }
32329 +       if (dwc_otg_module_params.dma_desc_enable != -1) {
32330 +               retval +=
32331 +                   dwc_otg_set_param_dma_desc_enable(core_if,
32332 +                                                     dwc_otg_module_params.
32333 +                                                     dma_desc_enable);
32334 +       }
32335 +       if (dwc_otg_module_params.opt != -1) {
32336 +               retval +=
32337 +                   dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
32338 +       }
32339 +       if (dwc_otg_module_params.dma_burst_size != -1) {
32340 +               retval +=
32341 +                   dwc_otg_set_param_dma_burst_size(core_if,
32342 +                                                    dwc_otg_module_params.
32343 +                                                    dma_burst_size);
32344 +       }
32345 +       if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
32346 +               retval +=
32347 +                   dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
32348 +                                                                  dwc_otg_module_params.
32349 +                                                                  host_support_fs_ls_low_power);
32350 +       }
32351 +       if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
32352 +               retval +=
32353 +                   dwc_otg_set_param_enable_dynamic_fifo(core_if,
32354 +                                                         dwc_otg_module_params.
32355 +                                                         enable_dynamic_fifo);
32356 +       }
32357 +       if (dwc_otg_module_params.data_fifo_size != -1) {
32358 +               retval +=
32359 +                   dwc_otg_set_param_data_fifo_size(core_if,
32360 +                                                    dwc_otg_module_params.
32361 +                                                    data_fifo_size);
32362 +       }
32363 +       if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
32364 +               retval +=
32365 +                   dwc_otg_set_param_dev_rx_fifo_size(core_if,
32366 +                                                      dwc_otg_module_params.
32367 +                                                      dev_rx_fifo_size);
32368 +       }
32369 +       if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
32370 +               retval +=
32371 +                   dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
32372 +                                                             dwc_otg_module_params.
32373 +                                                             dev_nperio_tx_fifo_size);
32374 +       }
32375 +       if (dwc_otg_module_params.host_rx_fifo_size != -1) {
32376 +               retval +=
32377 +                   dwc_otg_set_param_host_rx_fifo_size(core_if,
32378 +                                                       dwc_otg_module_params.host_rx_fifo_size);
32379 +       }
32380 +       if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
32381 +               retval +=
32382 +                   dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
32383 +                                                              dwc_otg_module_params.
32384 +                                                              host_nperio_tx_fifo_size);
32385 +       }
32386 +       if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
32387 +               retval +=
32388 +                   dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
32389 +                                                             dwc_otg_module_params.
32390 +                                                             host_perio_tx_fifo_size);
32391 +       }
32392 +       if (dwc_otg_module_params.max_transfer_size != -1) {
32393 +               retval +=
32394 +                   dwc_otg_set_param_max_transfer_size(core_if,
32395 +                                                       dwc_otg_module_params.
32396 +                                                       max_transfer_size);
32397 +       }
32398 +       if (dwc_otg_module_params.max_packet_count != -1) {
32399 +               retval +=
32400 +                   dwc_otg_set_param_max_packet_count(core_if,
32401 +                                                      dwc_otg_module_params.
32402 +                                                      max_packet_count);
32403 +       }
32404 +       if (dwc_otg_module_params.host_channels != -1) {
32405 +               retval +=
32406 +                   dwc_otg_set_param_host_channels(core_if,
32407 +                                                   dwc_otg_module_params.
32408 +                                                   host_channels);
32409 +       }
32410 +       if (dwc_otg_module_params.dev_endpoints != -1) {
32411 +               retval +=
32412 +                   dwc_otg_set_param_dev_endpoints(core_if,
32413 +                                                   dwc_otg_module_params.
32414 +                                                   dev_endpoints);
32415 +       }
32416 +       if (dwc_otg_module_params.phy_type != -1) {
32417 +               retval +=
32418 +                   dwc_otg_set_param_phy_type(core_if,
32419 +                                              dwc_otg_module_params.phy_type);
32420 +       }
32421 +       if (dwc_otg_module_params.speed != -1) {
32422 +               retval +=
32423 +                   dwc_otg_set_param_speed(core_if,
32424 +                                           dwc_otg_module_params.speed);
32425 +       }
32426 +       if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
32427 +               retval +=
32428 +                   dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
32429 +                                                               dwc_otg_module_params.
32430 +                                                               host_ls_low_power_phy_clk);
32431 +       }
32432 +       if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
32433 +               retval +=
32434 +                   dwc_otg_set_param_phy_ulpi_ddr(core_if,
32435 +                                                  dwc_otg_module_params.
32436 +                                                  phy_ulpi_ddr);
32437 +       }
32438 +       if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
32439 +               retval +=
32440 +                   dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
32441 +                                                       dwc_otg_module_params.
32442 +                                                       phy_ulpi_ext_vbus);
32443 +       }
32444 +       if (dwc_otg_module_params.phy_utmi_width != -1) {
32445 +               retval +=
32446 +                   dwc_otg_set_param_phy_utmi_width(core_if,
32447 +                                                    dwc_otg_module_params.
32448 +                                                    phy_utmi_width);
32449 +       }
32450 +       if (dwc_otg_module_params.ulpi_fs_ls != -1) {
32451 +               retval +=
32452 +                   dwc_otg_set_param_ulpi_fs_ls(core_if,
32453 +                                                dwc_otg_module_params.ulpi_fs_ls);
32454 +       }
32455 +       if (dwc_otg_module_params.ts_dline != -1) {
32456 +               retval +=
32457 +                   dwc_otg_set_param_ts_dline(core_if,
32458 +                                              dwc_otg_module_params.ts_dline);
32459 +       }
32460 +       if (dwc_otg_module_params.i2c_enable != -1) {
32461 +               retval +=
32462 +                   dwc_otg_set_param_i2c_enable(core_if,
32463 +                                                dwc_otg_module_params.
32464 +                                                i2c_enable);
32465 +       }
32466 +       if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
32467 +               retval +=
32468 +                   dwc_otg_set_param_en_multiple_tx_fifo(core_if,
32469 +                                                         dwc_otg_module_params.
32470 +                                                         en_multiple_tx_fifo);
32471 +       }
32472 +       for (i = 0; i < 15; i++) {
32473 +               if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
32474 +                       retval +=
32475 +                           dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
32476 +                                                                    dwc_otg_module_params.
32477 +                                                                    dev_perio_tx_fifo_size
32478 +                                                                    [i], i);
32479 +               }
32480 +       }
32481 +
32482 +       for (i = 0; i < 15; i++) {
32483 +               if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
32484 +                       retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
32485 +                                                                    dwc_otg_module_params.
32486 +                                                                    dev_tx_fifo_size
32487 +                                                                    [i], i);
32488 +               }
32489 +       }
32490 +       if (dwc_otg_module_params.thr_ctl != -1) {
32491 +               retval +=
32492 +                   dwc_otg_set_param_thr_ctl(core_if,
32493 +                                             dwc_otg_module_params.thr_ctl);
32494 +       }
32495 +       if (dwc_otg_module_params.mpi_enable != -1) {
32496 +               retval +=
32497 +                   dwc_otg_set_param_mpi_enable(core_if,
32498 +                                                dwc_otg_module_params.
32499 +                                                mpi_enable);
32500 +       }
32501 +       if (dwc_otg_module_params.pti_enable != -1) {
32502 +               retval +=
32503 +                   dwc_otg_set_param_pti_enable(core_if,
32504 +                                                dwc_otg_module_params.
32505 +                                                pti_enable);
32506 +       }
32507 +       if (dwc_otg_module_params.lpm_enable != -1) {
32508 +               retval +=
32509 +                   dwc_otg_set_param_lpm_enable(core_if,
32510 +                                                dwc_otg_module_params.
32511 +                                                lpm_enable);
32512 +       }
32513 +       if (dwc_otg_module_params.ic_usb_cap != -1) {
32514 +               retval +=
32515 +                   dwc_otg_set_param_ic_usb_cap(core_if,
32516 +                                                dwc_otg_module_params.
32517 +                                                ic_usb_cap);
32518 +       }
32519 +       if (dwc_otg_module_params.tx_thr_length != -1) {
32520 +               retval +=
32521 +                   dwc_otg_set_param_tx_thr_length(core_if,
32522 +                                                   dwc_otg_module_params.tx_thr_length);
32523 +       }
32524 +       if (dwc_otg_module_params.rx_thr_length != -1) {
32525 +               retval +=
32526 +                   dwc_otg_set_param_rx_thr_length(core_if,
32527 +                                                   dwc_otg_module_params.
32528 +                                                   rx_thr_length);
32529 +       }
32530 +       if (dwc_otg_module_params.ahb_thr_ratio != -1) {
32531 +               retval +=
32532 +                   dwc_otg_set_param_ahb_thr_ratio(core_if,
32533 +                                                   dwc_otg_module_params.ahb_thr_ratio);
32534 +       }
32535 +       if (dwc_otg_module_params.power_down != -1) {
32536 +               retval +=
32537 +                   dwc_otg_set_param_power_down(core_if,
32538 +                                                dwc_otg_module_params.power_down);
32539 +       }
32540 +       if (dwc_otg_module_params.reload_ctl != -1) {
32541 +               retval +=
32542 +                   dwc_otg_set_param_reload_ctl(core_if,
32543 +                                                dwc_otg_module_params.reload_ctl);
32544 +       }
32545 +
32546 +       if (dwc_otg_module_params.dev_out_nak != -1) {
32547 +               retval +=
32548 +                       dwc_otg_set_param_dev_out_nak(core_if,
32549 +                       dwc_otg_module_params.dev_out_nak);
32550 +       }
32551 +
32552 +       if (dwc_otg_module_params.cont_on_bna != -1) {
32553 +               retval +=
32554 +                       dwc_otg_set_param_cont_on_bna(core_if,
32555 +                       dwc_otg_module_params.cont_on_bna);
32556 +       }
32557 +
32558 +       if (dwc_otg_module_params.ahb_single != -1) {
32559 +               retval +=
32560 +                       dwc_otg_set_param_ahb_single(core_if,
32561 +                       dwc_otg_module_params.ahb_single);
32562 +       }
32563 +
32564 +       if (dwc_otg_module_params.otg_ver != -1) {
32565 +               retval +=
32566 +                   dwc_otg_set_param_otg_ver(core_if,
32567 +                                             dwc_otg_module_params.otg_ver);
32568 +       }
32569 +       if (dwc_otg_module_params.adp_enable != -1) {
32570 +               retval +=
32571 +                   dwc_otg_set_param_adp_enable(core_if,
32572 +                                                dwc_otg_module_params.
32573 +                                                adp_enable);
32574 +       }
32575 +       return retval;
32576 +}
32577 +
32578 +/**
32579 + * This function is the top level interrupt handler for the Common
32580 + * (Device and host modes) interrupts.
32581 + */
32582 +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
32583 +{
32584 +       int32_t retval = IRQ_NONE;
32585 +
32586 +       retval = dwc_otg_handle_common_intr(dev);
32587 +       if (retval != 0) {
32588 +               S3C2410X_CLEAR_EINTPEND();
32589 +       }
32590 +       return IRQ_RETVAL(retval);
32591 +}
32592 +
32593 +/**
32594 + * This function is called when a lm_device is unregistered with the
32595 + * dwc_otg_driver. This happens, for example, when the rmmod command is
32596 + * executed. The device may or may not be electrically present. If it is
32597 + * present, the driver stops device processing. Any resources used on behalf
32598 + * of this device are freed.
32599 + *
32600 + * @param _dev
32601 + */
32602 +#ifdef LM_INTERFACE
32603 +#define REM_RETVAL(n)
32604 +static void dwc_otg_driver_remove(      struct lm_device *_dev )
32605 +{       dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
32606 +#elif  defined(PCI_INTERFACE)
32607 +#define REM_RETVAL(n)
32608 +static void dwc_otg_driver_remove(      struct pci_dev *_dev )
32609 +{      dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
32610 +#elif  defined(PLATFORM_INTERFACE)
32611 +#define REM_RETVAL(n) n
32612 +static int dwc_otg_driver_remove(        struct platform_device *_dev )
32613 +{       dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
32614 +#endif
32615 +
32616 +       DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
32617 +
32618 +       if (!otg_dev) {
32619 +               /* Memory allocation for the dwc_otg_device failed. */
32620 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
32621 +                return REM_RETVAL(-ENOMEM);
32622 +       }
32623 +#ifndef DWC_DEVICE_ONLY
32624 +       if (otg_dev->hcd) {
32625 +               hcd_remove(_dev);
32626 +       } else {
32627 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
32628 +                return REM_RETVAL(-EINVAL);
32629 +       }
32630 +#endif
32631 +
32632 +#ifndef DWC_HOST_ONLY
32633 +       if (otg_dev->pcd) {
32634 +               pcd_remove(_dev);
32635 +       } else {
32636 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);
32637 +                return REM_RETVAL(-EINVAL);
32638 +       }
32639 +#endif
32640 +       /*
32641 +        * Free the IRQ
32642 +        */
32643 +       if (otg_dev->common_irq_installed) {
32644 +#ifdef PLATFORM_INTERFACE
32645 +               free_irq(platform_get_irq(_dev, 0), otg_dev);
32646 +#else
32647 +               free_irq(_dev->irq, otg_dev);
32648 +#endif
32649 +        } else {
32650 +               DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
32651 +               return REM_RETVAL(-ENXIO);
32652 +       }
32653 +
32654 +       if (otg_dev->core_if) {
32655 +               dwc_otg_cil_remove(otg_dev->core_if);
32656 +       } else {
32657 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);
32658 +               return REM_RETVAL(-ENXIO);
32659 +       }
32660 +
32661 +       /*
32662 +        * Remove the device attributes
32663 +        */
32664 +       dwc_otg_attr_remove(_dev);
32665 +
32666 +       /*
32667 +        * Return the memory.
32668 +        */
32669 +       if (otg_dev->os_dep.base) {
32670 +               iounmap(otg_dev->os_dep.base);
32671 +       }
32672 +       DWC_FREE(otg_dev);
32673 +
32674 +       /*
32675 +        * Clear the drvdata pointer.
32676 +        */
32677 +#ifdef LM_INTERFACE
32678 +       lm_set_drvdata(_dev, 0);
32679 +#elif defined(PCI_INTERFACE)
32680 +        release_mem_region(otg_dev->os_dep.rsrc_start,
32681 +                           otg_dev->os_dep.rsrc_len);
32682 +       pci_set_drvdata(_dev, 0);
32683 +#elif  defined(PLATFORM_INTERFACE)
32684 +        platform_set_drvdata(_dev, 0);
32685 +#endif
32686 +        return REM_RETVAL(0);
32687 +}
32688 +
32689 +/**
32690 + * This function is called when an lm_device is bound to a
32691 + * dwc_otg_driver. It creates the driver components required to
32692 + * control the device (CIL, HCD, and PCD) and it initializes the
32693 + * device. The driver components are stored in a dwc_otg_device
32694 + * structure. A reference to the dwc_otg_device is saved in the
32695 + * lm_device. This allows the driver to access the dwc_otg_device
32696 + * structure on subsequent calls to driver methods for this device.
32697 + *
32698 + * @param _dev Bus device
32699 + */
32700 +static int dwc_otg_driver_probe(
32701 +#ifdef LM_INTERFACE
32702 +                                      struct lm_device *_dev
32703 +#elif defined(PCI_INTERFACE)
32704 +                                      struct pci_dev *_dev,
32705 +                                      const struct pci_device_id *id
32706 +#elif  defined(PLATFORM_INTERFACE)
32707 +                                       struct platform_device *_dev
32708 +#endif
32709 +    )
32710 +{
32711 +       int retval = 0;
32712 +       dwc_otg_device_t *dwc_otg_device;
32713 +        int devirq;
32714 +
32715 +       dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
32716 +#ifdef LM_INTERFACE
32717 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
32718 +#elif defined(PCI_INTERFACE)
32719 +       if (!id) {
32720 +               DWC_ERROR("Invalid pci_device_id %p", id);
32721 +               return -EINVAL;
32722 +       }
32723 +
32724 +       if (!_dev || (pci_enable_device(_dev) < 0)) {
32725 +               DWC_ERROR("Invalid pci_device %p", _dev);
32726 +               return -ENODEV;
32727 +       }
32728 +       dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
32729 +       /* other stuff needed as well? */
32730 +
32731 +#elif  defined(PLATFORM_INTERFACE)
32732 +       dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
32733 +                (unsigned)_dev->resource->start,
32734 +                (unsigned)(_dev->resource->end - _dev->resource->start));
32735 +#endif
32736 +
32737 +       dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
32738 +
32739 +       if (!dwc_otg_device) {
32740 +               dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
32741 +               return -ENOMEM;
32742 +       }
32743 +
32744 +       memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
32745 +       dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
32746 +
32747 +       /*
32748 +        * Map the DWC_otg Core memory into virtual address space.
32749 +        */
32750 +#ifdef LM_INTERFACE
32751 +       dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);
32752 +
32753 +       if (!dwc_otg_device->os_dep.base) {
32754 +               dev_err(&_dev->dev, "ioremap() failed\n");
32755 +               DWC_FREE(dwc_otg_device);
32756 +               return -ENOMEM;
32757 +       }
32758 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32759 +               (unsigned)dwc_otg_device->os_dep.base);
32760 +#elif defined(PCI_INTERFACE)
32761 +       _dev->current_state = PCI_D0;
32762 +       _dev->dev.power.power_state = PMSG_ON;
32763 +
32764 +       if (!_dev->irq) {
32765 +               DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",
32766 +                         pci_name(_dev));
32767 +               iounmap(dwc_otg_device->os_dep.base);
32768 +               DWC_FREE(dwc_otg_device);
32769 +               return -ENODEV;
32770 +       }
32771 +
32772 +       dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);
32773 +       dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);
32774 +       DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",
32775 +                   (unsigned)dwc_otg_device->os_dep.rsrc_start,
32776 +                   (unsigned)dwc_otg_device->os_dep.rsrc_len);
32777 +       if (!request_mem_region
32778 +           (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,
32779 +            "dwc_otg")) {
32780 +               dev_dbg(&_dev->dev, "error requesting memory\n");
32781 +               iounmap(dwc_otg_device->os_dep.base);
32782 +               DWC_FREE(dwc_otg_device);
32783 +               return -EFAULT;
32784 +       }
32785 +
32786 +       dwc_otg_device->os_dep.base =
32787 +           ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,
32788 +                           dwc_otg_device->os_dep.rsrc_len);
32789 +       if (dwc_otg_device->os_dep.base == NULL) {
32790 +               dev_dbg(&_dev->dev, "error mapping memory\n");
32791 +               release_mem_region(dwc_otg_device->os_dep.rsrc_start,
32792 +                                  dwc_otg_device->os_dep.rsrc_len);
32793 +               iounmap(dwc_otg_device->os_dep.base);
32794 +               DWC_FREE(dwc_otg_device);
32795 +               return -EFAULT;
32796 +       }
32797 +       dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",
32798 +               dwc_otg_device->os_dep.base);
32799 +       dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;
32800 +       dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",
32801 +               dwc_otg_device->os_dep.base);
32802 +       dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
32803 +               (unsigned)dwc_otg_device->os_dep.rsrc_start,
32804 +               dwc_otg_device->os_dep.base);
32805 +
32806 +       pci_set_master(_dev);
32807 +       pci_set_drvdata(_dev, dwc_otg_device);
32808 +#elif defined(PLATFORM_INTERFACE)
32809 +        DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
32810 +                    _dev->resource->start,
32811 +                    _dev->resource->end - _dev->resource->start + 1);
32812 +#if 1
32813 +        if (!request_mem_region(_dev->resource->start,
32814 +                                _dev->resource->end - _dev->resource->start + 1,
32815 +                                "dwc_otg")) {
32816 +          dev_dbg(&_dev->dev, "error reserving mapped memory\n");
32817 +          retval = -EFAULT;
32818 +          goto fail;
32819 +        }
32820 +
32821 +       dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
32822 +                                                      _dev->resource->end -
32823 +                                                      _dev->resource->start+1);
32824 +#else
32825 +        {
32826 +                struct map_desc desc = {
32827 +                    .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
32828 +                    .pfn     = __phys_to_pfn((unsigned)_dev->resource->start),
32829 +                    .length  = SZ_128K,
32830 +                    .type    = MT_DEVICE
32831 +                };
32832 +                iotable_init(&desc, 1);
32833 +                dwc_otg_device->os_dep.base = (void *)desc.virtual;
32834 +        }
32835 +#endif
32836 +       if (!dwc_otg_device->os_dep.base) {
32837 +               dev_err(&_dev->dev, "ioremap() failed\n");
32838 +               retval = -ENOMEM;
32839 +               goto fail;
32840 +       }
32841 +       dev_dbg(&_dev->dev, "base=0x%08x\n",
32842 +                (unsigned)dwc_otg_device->os_dep.base);
32843 +#endif
32844 +
32845 +       /*
32846 +        * Initialize driver data to point to the global DWC_otg
32847 +        * Device structure.
32848 +        */
32849 +#ifdef LM_INTERFACE
32850 +       lm_set_drvdata(_dev, dwc_otg_device);
32851 +#elif defined(PLATFORM_INTERFACE)
32852 +       platform_set_drvdata(_dev, dwc_otg_device);
32853 +#endif
32854 +       dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
32855 +
32856 +       dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
32857 +        DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
32858 +                    dwc_otg_device, dwc_otg_device->core_if);//GRAYG
32859 +
32860 +       if (!dwc_otg_device->core_if) {
32861 +               dev_err(&_dev->dev, "CIL initialization failed!\n");
32862 +               retval = -ENOMEM;
32863 +               goto fail;
32864 +       }
32865 +
32866 +       dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
32867 +       /*
32868 +        * Attempt to ensure this device is really a DWC_otg Controller.
32869 +        * Read and verify the SNPSID register contents. The value should be
32870 +        * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",
32871 +        * as in "OTG version 2.XX" or "OTG version 3.XX".
32872 +        */
32873 +
32874 +       if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) !=     0x4F542000) &&
32875 +               ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
32876 +               dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
32877 +                       dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
32878 +               retval = -EINVAL;
32879 +               goto fail;
32880 +       }
32881 +
32882 +       /*
32883 +        * Validate parameter values.
32884 +        */
32885 +       dev_dbg(&_dev->dev, "Calling set_parameters\n");
32886 +       if (set_parameters(dwc_otg_device->core_if)) {
32887 +               retval = -EINVAL;
32888 +               goto fail;
32889 +       }
32890 +
32891 +       /*
32892 +        * Create Device Attributes in sysfs
32893 +        */
32894 +       dev_dbg(&_dev->dev, "Calling attr_create\n");
32895 +       dwc_otg_attr_create(_dev);
32896 +
32897 +       /*
32898 +        * Disable the global interrupt until all the interrupt
32899 +        * handlers are installed.
32900 +        */
32901 +       dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
32902 +       dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
32903 +
32904 +       /*
32905 +        * Install the interrupt handler for the common interrupts before
32906 +        * enabling common interrupts in core_init below.
32907 +        */
32908 +
32909 +#if defined(PLATFORM_INTERFACE)
32910 +        devirq = platform_get_irq(_dev, 0);
32911 +#else
32912 +        devirq = _dev->irq;
32913 +#endif
32914 +       DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
32915 +                   devirq);
32916 +       dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
32917 +       retval = request_irq(devirq, dwc_otg_common_irq,
32918 +                             IRQF_SHARED,
32919 +                             "dwc_otg", dwc_otg_device);
32920 +       if (retval) {
32921 +               DWC_ERROR("request of irq%d failed\n", devirq);
32922 +               retval = -EBUSY;
32923 +               goto fail;
32924 +       } else {
32925 +               dwc_otg_device->common_irq_installed = 1;
32926 +       }
32927 +
32928 +#ifndef IRQF_TRIGGER_LOW
32929 +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
32930 +       dev_dbg(&_dev->dev, "Calling set_irq_type\n");
32931 +       set_irq_type(devirq,
32932 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
32933 +                     IRQT_LOW
32934 +#else
32935 +                     IRQ_TYPE_LEVEL_LOW
32936 +#endif
32937 +                    );
32938 +#endif
32939 +#endif /*IRQF_TRIGGER_LOW*/
32940 +
32941 +       /*
32942 +        * Initialize the DWC_otg core.
32943 +        */
32944 +       dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
32945 +       dwc_otg_core_init(dwc_otg_device->core_if);
32946 +
32947 +#ifndef DWC_HOST_ONLY
32948 +       /*
32949 +        * Initialize the PCD
32950 +        */
32951 +       dev_dbg(&_dev->dev, "Calling pcd_init\n");
32952 +       retval = pcd_init(_dev);
32953 +       if (retval != 0) {
32954 +               DWC_ERROR("pcd_init failed\n");
32955 +               dwc_otg_device->pcd = NULL;
32956 +               goto fail;
32957 +       }
32958 +#endif
32959 +#ifndef DWC_DEVICE_ONLY
32960 +       /*
32961 +        * Initialize the HCD
32962 +        */
32963 +       dev_dbg(&_dev->dev, "Calling hcd_init\n");
32964 +       retval = hcd_init(_dev);
32965 +       if (retval != 0) {
32966 +               DWC_ERROR("hcd_init failed\n");
32967 +               dwc_otg_device->hcd = NULL;
32968 +               goto fail;
32969 +       }
32970 +#endif
32971 +        /* Recover from drvdata having been overwritten by hcd_init() */
32972 +#ifdef LM_INTERFACE
32973 +       lm_set_drvdata(_dev, dwc_otg_device);
32974 +#elif defined(PLATFORM_INTERFACE)
32975 +       platform_set_drvdata(_dev, dwc_otg_device);
32976 +#elif defined(PCI_INTERFACE)
32977 +       pci_set_drvdata(_dev, dwc_otg_device);
32978 +       dwc_otg_device->os_dep.pcidev = _dev;
32979 +#endif
32980 +
32981 +       /*
32982 +        * Enable the global interrupt after all the interrupt
32983 +        * handlers are installed if there is no ADP support else
32984 +        * perform initial actions required for Internal ADP logic.
32985 +        */
32986 +       if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
32987 +               dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
32988 +               dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
32989 +               dev_dbg(&_dev->dev, "Done\n");
32990 +       } else
32991 +               dwc_otg_adp_start(dwc_otg_device->core_if,
32992 +                                                       dwc_otg_is_host_mode(dwc_otg_device->core_if));
32993 +
32994 +       return 0;
32995 +
32996 +fail:
32997 +       dwc_otg_driver_remove(_dev);
32998 +       return retval;
32999 +}
33000 +
33001 +/**
33002 + * This structure defines the methods to be called by a bus driver
33003 + * during the lifecycle of a device on that bus. Both drivers and
33004 + * devices are registered with a bus driver. The bus driver matches
33005 + * devices to drivers based on information in the device and driver
33006 + * structures.
33007 + *
33008 + * The probe function is called when the bus driver matches a device
33009 + * to this driver. The remove function is called when a device is
33010 + * unregistered with the bus driver.
33011 + */
33012 +#ifdef LM_INTERFACE
33013 +static struct lm_driver dwc_otg_driver = {
33014 +       .drv = {.name = (char *)dwc_driver_name,},
33015 +       .probe = dwc_otg_driver_probe,
33016 +       .remove = dwc_otg_driver_remove,
33017 +        // 'suspend' and 'resume' absent
33018 +};
33019 +#elif defined(PCI_INTERFACE)
33020 +static const struct pci_device_id pci_ids[] = { {
33021 +                                                PCI_DEVICE(0x16c3, 0xabcd),
33022 +                                                .driver_data =
33023 +                                                (unsigned long)0xdeadbeef,
33024 +                                                }, { /* end: all zeroes */ }
33025 +};
33026 +
33027 +MODULE_DEVICE_TABLE(pci, pci_ids);
33028 +
33029 +/* pci driver glue; this is a "new style" PCI driver module */
33030 +static struct pci_driver dwc_otg_driver = {
33031 +       .name = "dwc_otg",
33032 +       .id_table = pci_ids,
33033 +
33034 +       .probe = dwc_otg_driver_probe,
33035 +       .remove = dwc_otg_driver_remove,
33036 +
33037 +       .driver = {
33038 +                  .name = (char *)dwc_driver_name,
33039 +                  },
33040 +};
33041 +#elif defined(PLATFORM_INTERFACE)
33042 +static struct platform_device_id platform_ids[] = {
33043 +        {
33044 +              .name = "bcm2708_usb",
33045 +              .driver_data = (kernel_ulong_t) 0xdeadbeef,
33046 +        },
33047 +        { /* end: all zeroes */ }
33048 +};
33049 +MODULE_DEVICE_TABLE(platform, platform_ids);
33050 +
33051 +static struct platform_driver dwc_otg_driver = {
33052 +       .driver = {
33053 +               .name = (char *)dwc_driver_name,
33054 +               },
33055 +        .id_table = platform_ids,
33056 +
33057 +       .probe = dwc_otg_driver_probe,
33058 +       .remove = dwc_otg_driver_remove,
33059 +        // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early'
33060 +};
33061 +#endif
33062 +
33063 +/**
33064 + * This function is called when the dwc_otg_driver is installed with the
33065 + * insmod command. It registers the dwc_otg_driver structure with the
33066 + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
33067 + * to be called. In addition, the bus driver will automatically expose
33068 + * attributes defined for the device and driver in the special sysfs file
33069 + * system.
33070 + *
33071 + * @return
33072 + */
33073 +static int __init dwc_otg_driver_init(void)
33074 +{
33075 +       int retval = 0;
33076 +       int error;
33077 +        struct device_driver *drv;
33078 +       printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
33079 +              DWC_DRIVER_VERSION,
33080 +#ifdef LM_INTERFACE
33081 +               "logicmodule");
33082 +       retval = lm_driver_register(&dwc_otg_driver);
33083 +        drv = &dwc_otg_driver.drv;
33084 +#elif defined(PCI_INTERFACE)
33085 +               "pci");
33086 +       retval = pci_register_driver(&dwc_otg_driver);
33087 +        drv = &dwc_otg_driver.driver;
33088 +#elif defined(PLATFORM_INTERFACE)
33089 +               "platform");
33090 +       retval = platform_driver_register(&dwc_otg_driver);
33091 +        drv = &dwc_otg_driver.driver;
33092 +#endif
33093 +       if (retval < 0) {
33094 +               printk(KERN_ERR "%s retval=%d\n", __func__, retval);
33095 +               return retval;
33096 +       }
33097 +
33098 +       error = driver_create_file(drv, &driver_attr_version);
33099 +#ifdef DEBUG
33100 +       error = driver_create_file(drv, &driver_attr_debuglevel);
33101 +#endif
33102 +       return retval;
33103 +}
33104 +
33105 +module_init(dwc_otg_driver_init);
33106 +
33107 +/**
33108 + * This function is called when the driver is removed from the kernel
33109 + * with the rmmod command. The driver unregisters itself with its bus
33110 + * driver.
33111 + *
33112 + */
33113 +static void __exit dwc_otg_driver_cleanup(void)
33114 +{
33115 +       printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
33116 +
33117 +#ifdef LM_INTERFACE
33118 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
33119 +       driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
33120 +       lm_driver_unregister(&dwc_otg_driver);
33121 +#elif defined(PCI_INTERFACE)
33122 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33123 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33124 +       pci_unregister_driver(&dwc_otg_driver);
33125 +#elif defined(PLATFORM_INTERFACE)
33126 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
33127 +       driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
33128 +       platform_driver_unregister(&dwc_otg_driver);
33129 +#endif
33130 +
33131 +       printk(KERN_INFO "%s module removed\n", dwc_driver_name);
33132 +}
33133 +
33134 +module_exit(dwc_otg_driver_cleanup);
33135 +
33136 +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
33137 +MODULE_AUTHOR("Synopsys Inc.");
33138 +MODULE_LICENSE("GPL");
33139 +
33140 +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
33141 +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
33142 +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
33143 +MODULE_PARM_DESC(opt, "OPT Mode");
33144 +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
33145 +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
33146 +
33147 +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
33148 +                  0444);
33149 +MODULE_PARM_DESC(dma_desc_enable,
33150 +                "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
33151 +
33152 +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
33153 +                  0444);
33154 +MODULE_PARM_DESC(dma_burst_size,
33155 +                "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
33156 +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
33157 +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
33158 +module_param_named(host_support_fs_ls_low_power,
33159 +                  dwc_otg_module_params.host_support_fs_ls_low_power, int,
33160 +                  0444);
33161 +MODULE_PARM_DESC(host_support_fs_ls_low_power,
33162 +                "Support Low Power w/FS or LS 0=Support 1=Don't Support");
33163 +module_param_named(host_ls_low_power_phy_clk,
33164 +                  dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
33165 +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
33166 +                "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
33167 +module_param_named(enable_dynamic_fifo,
33168 +                  dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
33169 +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
33170 +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
33171 +                  0444);
33172 +MODULE_PARM_DESC(data_fifo_size,
33173 +                "Total number of words in the data FIFO memory 32-32768");
33174 +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
33175 +                  int, 0444);
33176 +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33177 +module_param_named(dev_nperio_tx_fifo_size,
33178 +                  dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
33179 +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
33180 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33181 +module_param_named(dev_perio_tx_fifo_size_1,
33182 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
33183 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
33184 +                "Number of words in the periodic Tx FIFO 4-768");
33185 +module_param_named(dev_perio_tx_fifo_size_2,
33186 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
33187 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
33188 +                "Number of words in the periodic Tx FIFO 4-768");
33189 +module_param_named(dev_perio_tx_fifo_size_3,
33190 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
33191 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
33192 +                "Number of words in the periodic Tx FIFO 4-768");
33193 +module_param_named(dev_perio_tx_fifo_size_4,
33194 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
33195 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
33196 +                "Number of words in the periodic Tx FIFO 4-768");
33197 +module_param_named(dev_perio_tx_fifo_size_5,
33198 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
33199 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
33200 +                "Number of words in the periodic Tx FIFO 4-768");
33201 +module_param_named(dev_perio_tx_fifo_size_6,
33202 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
33203 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
33204 +                "Number of words in the periodic Tx FIFO 4-768");
33205 +module_param_named(dev_perio_tx_fifo_size_7,
33206 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
33207 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
33208 +                "Number of words in the periodic Tx FIFO 4-768");
33209 +module_param_named(dev_perio_tx_fifo_size_8,
33210 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
33211 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
33212 +                "Number of words in the periodic Tx FIFO 4-768");
33213 +module_param_named(dev_perio_tx_fifo_size_9,
33214 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
33215 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
33216 +                "Number of words in the periodic Tx FIFO 4-768");
33217 +module_param_named(dev_perio_tx_fifo_size_10,
33218 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
33219 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
33220 +                "Number of words in the periodic Tx FIFO 4-768");
33221 +module_param_named(dev_perio_tx_fifo_size_11,
33222 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
33223 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
33224 +                "Number of words in the periodic Tx FIFO 4-768");
33225 +module_param_named(dev_perio_tx_fifo_size_12,
33226 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
33227 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
33228 +                "Number of words in the periodic Tx FIFO 4-768");
33229 +module_param_named(dev_perio_tx_fifo_size_13,
33230 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
33231 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
33232 +                "Number of words in the periodic Tx FIFO 4-768");
33233 +module_param_named(dev_perio_tx_fifo_size_14,
33234 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
33235 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
33236 +                "Number of words in the periodic Tx FIFO 4-768");
33237 +module_param_named(dev_perio_tx_fifo_size_15,
33238 +                  dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
33239 +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
33240 +                "Number of words in the periodic Tx FIFO 4-768");
33241 +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
33242 +                  int, 0444);
33243 +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
33244 +module_param_named(host_nperio_tx_fifo_size,
33245 +                  dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
33246 +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
33247 +                "Number of words in the non-periodic Tx FIFO 16-32768");
33248 +module_param_named(host_perio_tx_fifo_size,
33249 +                  dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
33250 +MODULE_PARM_DESC(host_perio_tx_fifo_size,
33251 +                "Number of words in the host periodic Tx FIFO 16-32768");
33252 +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
33253 +                  int, 0444);
33254 +/** @todo Set the max to 512K, modify checks */
33255 +MODULE_PARM_DESC(max_transfer_size,
33256 +                "The maximum transfer size supported in bytes 2047-65535");
33257 +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
33258 +                  int, 0444);
33259 +MODULE_PARM_DESC(max_packet_count,
33260 +                "The maximum number of packets in a transfer 15-511");
33261 +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
33262 +                  0444);
33263 +MODULE_PARM_DESC(host_channels,
33264 +                "The number of host channel registers to use 1-16");
33265 +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
33266 +                  0444);
33267 +MODULE_PARM_DESC(dev_endpoints,
33268 +                "The number of endpoints in addition to EP0 available for device mode 1-15");
33269 +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
33270 +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
33271 +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
33272 +                  0444);
33273 +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
33274 +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
33275 +MODULE_PARM_DESC(phy_ulpi_ddr,
33276 +                "ULPI at double or single data rate 0=Single 1=Double");
33277 +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
33278 +                  int, 0444);
33279 +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
33280 +                "ULPI PHY using internal or external vbus 0=Internal");
33281 +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
33282 +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
33283 +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
33284 +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
33285 +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
33286 +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
33287 +module_param_named(debug, g_dbg_lvl, int, 0444);
33288 +MODULE_PARM_DESC(debug, "");
33289 +
33290 +module_param_named(en_multiple_tx_fifo,
33291 +                  dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
33292 +MODULE_PARM_DESC(en_multiple_tx_fifo,
33293 +                "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
33294 +module_param_named(dev_tx_fifo_size_1,
33295 +                  dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
33296 +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
33297 +module_param_named(dev_tx_fifo_size_2,
33298 +                  dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
33299 +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
33300 +module_param_named(dev_tx_fifo_size_3,
33301 +                  dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
33302 +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
33303 +module_param_named(dev_tx_fifo_size_4,
33304 +                  dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
33305 +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
33306 +module_param_named(dev_tx_fifo_size_5,
33307 +                  dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
33308 +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
33309 +module_param_named(dev_tx_fifo_size_6,
33310 +                  dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
33311 +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
33312 +module_param_named(dev_tx_fifo_size_7,
33313 +                  dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
33314 +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
33315 +module_param_named(dev_tx_fifo_size_8,
33316 +                  dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
33317 +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
33318 +module_param_named(dev_tx_fifo_size_9,
33319 +                  dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
33320 +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
33321 +module_param_named(dev_tx_fifo_size_10,
33322 +                  dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
33323 +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
33324 +module_param_named(dev_tx_fifo_size_11,
33325 +                  dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
33326 +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
33327 +module_param_named(dev_tx_fifo_size_12,
33328 +                  dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
33329 +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
33330 +module_param_named(dev_tx_fifo_size_13,
33331 +                  dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
33332 +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
33333 +module_param_named(dev_tx_fifo_size_14,
33334 +                  dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
33335 +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
33336 +module_param_named(dev_tx_fifo_size_15,
33337 +                  dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
33338 +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
33339 +
33340 +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
33341 +MODULE_PARM_DESC(thr_ctl,
33342 +                "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
33343 +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
33344 +                  0444);
33345 +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
33346 +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
33347 +                  0444);
33348 +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
33349 +
33350 +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
33351 +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
33352 +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
33353 +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
33354 +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
33355 +MODULE_PARM_DESC(ic_usb_cap,
33356 +                "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
33357 +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,
33358 +                  0444);
33359 +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
33360 +module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);
33361 +MODULE_PARM_DESC(power_down, "Power Down Mode");
33362 +module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);
33363 +MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
33364 +module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
33365 +MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
33366 +module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
33367 +MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
33368 +module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
33369 +MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
33370 +module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
33371 +MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
33372 +module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
33373 +MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
33374 +module_param(microframe_schedule, bool, 0444);
33375 +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
33376 +
33377 +/** @page "Module Parameters"
33378 + *
33379 + * The following parameters may be specified when starting the module.
33380 + * These parameters define how the DWC_otg controller should be
33381 + * configured. Parameter values are passed to the CIL initialization
33382 + * function dwc_otg_cil_init
33383 + *
33384 + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
33385 + *
33386 +
33387 + <table>
33388 + <tr><td>Parameter Name</td><td>Meaning</td></tr>
33389 +
33390 + <tr>
33391 + <td>otg_cap</td>
33392 + <td>Specifies the OTG capabilities. The driver will automatically detect the
33393 + value for this parameter if none is specified.
33394 + - 0: HNP and SRP capable (default, if available)
33395 + - 1: SRP Only capable
33396 + - 2: No HNP/SRP capable
33397 + </td></tr>
33398 +
33399 + <tr>
33400 + <td>dma_enable</td>
33401 + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
33402 + The driver will automatically detect the value for this parameter if none is
33403 + specified.
33404 + - 0: Slave
33405 + - 1: DMA (default, if available)
33406 + </td></tr>
33407 +
33408 + <tr>
33409 + <td>dma_burst_size</td>
33410 + <td>The DMA Burst size (applicable only for External DMA Mode).
33411 + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
33412 + </td></tr>
33413 +
33414 + <tr>
33415 + <td>speed</td>
33416 + <td>Specifies the maximum speed of operation in host and device mode. The
33417 + actual speed depends on the speed of the attached device and the value of
33418 + phy_type.
33419 + - 0: High Speed (default)
33420 + - 1: Full Speed
33421 + </td></tr>
33422 +
33423 + <tr>
33424 + <td>host_support_fs_ls_low_power</td>
33425 + <td>Specifies whether low power mode is supported when attached to a Full
33426 + Speed or Low Speed device in host mode.
33427 + - 0: Don't support low power mode (default)
33428 + - 1: Support low power mode
33429 + </td></tr>
33430 +
33431 + <tr>
33432 + <td>host_ls_low_power_phy_clk</td>
33433 + <td>Specifies the PHY clock rate in low power mode when connected to a Low
33434 + Speed device in host mode. This parameter is applicable only if
33435 + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
33436 + - 0: 48 MHz (default)
33437 + - 1: 6 MHz
33438 + </td></tr>
33439 +
33440 + <tr>
33441 + <td>enable_dynamic_fifo</td>
33442 + <td> Specifies whether FIFOs may be resized by the driver software.
33443 + - 0: Use cC FIFO size parameters
33444 + - 1: Allow dynamic FIFO sizing (default)
33445 + </td></tr>
33446 +
33447 + <tr>
33448 + <td>data_fifo_size</td>
33449 + <td>Total number of 4-byte words in the data FIFO memory. This memory
33450 + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
33451 + - Values: 32 to 32768 (default 8192)
33452 +
33453 + Note: The total FIFO memory depth in the FPGA configuration is 8192.
33454 + </td></tr>
33455 +
33456 + <tr>
33457 + <td>dev_rx_fifo_size</td>
33458 + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
33459 + FIFO sizing is enabled.
33460 + - Values: 16 to 32768 (default 1064)
33461 + </td></tr>
33462 +
33463 + <tr>
33464 + <td>dev_nperio_tx_fifo_size</td>
33465 + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
33466 + dynamic FIFO sizing is enabled.
33467 + - Values: 16 to 32768 (default 1024)
33468 + </td></tr>
33469 +
33470 + <tr>
33471 + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
33472 + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
33473 + when dynamic FIFO sizing is enabled.
33474 + - Values: 4 to 768 (default 256)
33475 + </td></tr>
33476 +
33477 + <tr>
33478 + <td>host_rx_fifo_size</td>
33479 + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
33480 + sizing is enabled.
33481 + - Values: 16 to 32768 (default 1024)
33482 + </td></tr>
33483 +
33484 + <tr>
33485 + <td>host_nperio_tx_fifo_size</td>
33486 + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
33487 + dynamic FIFO sizing is enabled in the core.
33488 + - Values: 16 to 32768 (default 1024)
33489 + </td></tr>
33490 +
33491 + <tr>
33492 + <td>host_perio_tx_fifo_size</td>
33493 + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
33494 + sizing is enabled.
33495 + - Values: 16 to 32768 (default 1024)
33496 + </td></tr>
33497 +
33498 + <tr>
33499 + <td>max_transfer_size</td>
33500 + <td>The maximum transfer size supported in bytes.
33501 + - Values: 2047 to 65,535 (default 65,535)
33502 + </td></tr>
33503 +
33504 + <tr>
33505 + <td>max_packet_count</td>
33506 + <td>The maximum number of packets in a transfer.
33507 + - Values: 15 to 511 (default 511)
33508 + </td></tr>
33509 +
33510 + <tr>
33511 + <td>host_channels</td>
33512 + <td>The number of host channel registers to use.
33513 + - Values: 1 to 16 (default 12)
33514 +
33515 + Note: The FPGA configuration supports a maximum of 12 host channels.
33516 + </td></tr>
33517 +
33518 + <tr>
33519 + <td>dev_endpoints</td>
33520 + <td>The number of endpoints in addition to EP0 available for device mode
33521 + operations.
33522 + - Values: 1 to 15 (default 6 IN and OUT)
33523 +
33524 + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
33525 + addition to EP0.
33526 + </td></tr>
33527 +
33528 + <tr>
33529 + <td>phy_type</td>
33530 + <td>Specifies the type of PHY interface to use. By default, the driver will
33531 + automatically detect the phy_type.
33532 + - 0: Full Speed
33533 + - 1: UTMI+ (default, if available)
33534 + - 2: ULPI
33535 + </td></tr>
33536 +
33537 + <tr>
33538 + <td>phy_utmi_width</td>
33539 + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
33540 + phy_type of UTMI+. Also, this parameter is applicable only if the
33541 + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
33542 + core has been configured to work at either data path width.
33543 + - Values: 8 or 16 bits (default 16)
33544 + </td></tr>
33545 +
33546 + <tr>
33547 + <td>phy_ulpi_ddr</td>
33548 + <td>Specifies whether the ULPI operates at double or single data rate. This
33549 + parameter is only applicable if phy_type is ULPI.
33550 + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
33551 + - 1: double data rate ULPI interface with 4 bit wide data bus
33552 + </td></tr>
33553 +
33554 + <tr>
33555 + <td>i2c_enable</td>
33556 + <td>Specifies whether to use the I2C interface for full speed PHY. This
33557 + parameter is only applicable if PHY_TYPE is FS.
33558 + - 0: Disabled (default)
33559 + - 1: Enabled
33560 + </td></tr>
33561 +
33562 + <tr>
33563 + <td>ulpi_fs_ls</td>
33564 + <td>Specifies whether to use ULPI FS/LS mode only.
33565 + - 0: Disabled (default)
33566 + - 1: Enabled
33567 + </td></tr>
33568 +
33569 + <tr>
33570 + <td>ts_dline</td>
33571 + <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.
33572 + - 0: Disabled (default)
33573 + - 1: Enabled
33574 + </td></tr>
33575 +
33576 + <tr>
33577 + <td>en_multiple_tx_fifo</td>
33578 + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
33579 + The driver will automatically detect the value for this parameter if none is
33580 + specified.
33581 + - 0: Disabled
33582 + - 1: Enabled (default, if available)
33583 + </td></tr>
33584 +
33585 + <tr>
33586 + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
33587 + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
33588 + when dynamic FIFO sizing is enabled.
33589 + - Values: 4 to 768 (default 256)
33590 + </td></tr>
33591 +
33592 + <tr>
33593 + <td>tx_thr_length</td>
33594 + <td>Transmit Threshold length in 32 bit double words
33595 + - Values: 8 to 128 (default 64)
33596 + </td></tr>
33597 +
33598 + <tr>
33599 + <td>rx_thr_length</td>
33600 + <td>Receive Threshold length in 32 bit double words
33601 + - Values: 8 to 128 (default 64)
33602 + </td></tr>
33603 +
33604 +<tr>
33605 + <td>thr_ctl</td>
33606 + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
33607 + this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
33608 + Rx transfers accordingly.
33609 + The driver will automatically detect the value for this parameter if none is
33610 + specified.
33611 + - Values: 0 to 7 (default 0)
33612 + Bit values indicate:
33613 + - 0: Thresholding disabled
33614 + - 1: Thresholding enabled
33615 + </td></tr>
33616 +
33617 +<tr>
33618 + <td>dma_desc_enable</td>
33619 + <td>Specifies whether to enable Descriptor DMA mode.
33620 + The driver will automatically detect the value for this parameter if none is
33621 + specified.
33622 + - 0: Descriptor DMA disabled
33623 + - 1: Descriptor DMA (default, if available)
33624 + </td></tr>
33625 +
33626 +<tr>
33627 + <td>mpi_enable</td>
33628 + <td>Specifies whether to enable MPI enhancement mode.
33629 + The driver will automatically detect the value for this parameter if none is
33630 + specified.
33631 + - 0: MPI disabled (default)
33632 + - 1: MPI enable
33633 + </td></tr>
33634 +
33635 +<tr>
33636 + <td>pti_enable</td>
33637 + <td>Specifies whether to enable PTI enhancement support.
33638 + The driver will automatically detect the value for this parameter if none is
33639 + specified.
33640 + - 0: PTI disabled (default)
33641 + - 1: PTI enable
33642 + </td></tr>
33643 +
33644 +<tr>
33645 + <td>lpm_enable</td>
33646 + <td>Specifies whether to enable LPM support.
33647 + The driver will automatically detect the value for this parameter if none is
33648 + specified.
33649 + - 0: LPM disabled
33650 + - 1: LPM enable (default, if available)
33651 + </td></tr>
33652 +
33653 +<tr>
33654 + <td>ic_usb_cap</td>
33655 + <td>Specifies whether to enable IC_USB capability.
33656 + The driver will automatically detect the value for this parameter if none is
33657 + specified.
33658 + - 0: IC_USB disabled (default, if available)
33659 + - 1: IC_USB enable
33660 + </td></tr>
33661 +
33662 +<tr>
33663 + <td>ahb_thr_ratio</td>
33664 + <td>Specifies AHB Threshold ratio.
33665 + - Values: 0 to 3 (default 0)
33666 + </td></tr>
33667 +
33668 +<tr>
33669 + <td>power_down</td>
33670 + <td>Specifies Power Down(Hibernation) Mode.
33671 + The driver will automatically detect the value for this parameter if none is
33672 + specified.
33673 + - 0: Power Down disabled (default)
33674 + - 2: Power Down enabled
33675 + </td></tr>
33676 +
33677 + <tr>
33678 + <td>reload_ctl</td>
33679 + <td>Specifies whether dynamic reloading of the HFIR register is allowed during
33680 + run time. The driver will automatically detect the value for this parameter if
33681 + none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0
33682 + the core might misbehave.
33683 + - 0: Reload Control disabled (default)
33684 + - 1: Reload Control enabled
33685 + </td></tr>
33686 +
33687 + <tr>
33688 + <td>dev_out_nak</td>
33689 + <td>Specifies whether  Device OUT NAK enhancement enabled or no.
33690 + The driver will automatically detect the value for this parameter if
33691 + none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33692 + - 0: The core does not set NAK after Bulk OUT transfer complete (default)
33693 + - 1: The core sets NAK after Bulk OUT transfer complete
33694 + </td></tr>
33695 +
33696 + <tr>
33697 + <td>cont_on_bna</td>
33698 + <td>Specifies whether Enable Continue on BNA enabled or no.
33699 + After receiving BNA interrupt the core disables the endpoint,when the
33700 + endpoint is re-enabled by the application the
33701 + - 0: Core starts processing from the DOEPDMA descriptor (default)
33702 + - 1: Core starts processing from the descriptor which received the BNA.
33703 + This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
33704 + </td></tr>
33705 +
33706 + <tr>
33707 + <td>ahb_single</td>
33708 + <td>This bit when programmed supports SINGLE transfers for remainder data
33709 + in a transfer for DMA mode of operation.
33710 + - 0: The remainder data will be sent using INCR burst size (default)
33711 + - 1: The remainder data will be sent using SINGLE burst size.
33712 + </td></tr>
33713 +
33714 +<tr>
33715 + <td>adp_enable</td>
33716 + <td>Specifies whether ADP feature is enabled.
33717 + The driver will automatically detect the value for this parameter if none is
33718 + specified.
33719 + - 0: ADP feature disabled (default)
33720 + - 1: ADP feature enabled
33721 + </td></tr>
33722 +
33723 +  <tr>
33724 + <td>otg_ver</td>
33725 + <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
33726 + USB OTG device.
33727 + - 0: OTG 2.0 support disabled (default)
33728 + - 1: OTG 2.0 support enabled
33729 + </td></tr>
33730 +
33731 +*/
33732 --- /dev/null
33733 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
33734 @@ -0,0 +1,86 @@
33735 +/* ==========================================================================
33736 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
33737 + * $Revision: #19 $
33738 + * $Date: 2010/11/15 $
33739 + * $Change: 1627671 $
33740 + *
33741 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33742 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33743 + * otherwise expressly agreed to in writing between Synopsys and you.
33744 + *
33745 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33746 + * any End User Software License Agreement or Agreement for Licensed Product
33747 + * with Synopsys or any supplement thereto. You are permitted to use and
33748 + * redistribute this Software in source and binary forms, with or without
33749 + * modification, provided that redistributions of source code must retain this
33750 + * notice. You may not view, use, disclose, copy or distribute this file or
33751 + * any information contained herein except pursuant to this license grant from
33752 + * Synopsys. If you do not agree with this notice, including the disclaimer
33753 + * below, then you are not authorized to use the Software.
33754 + *
33755 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33756 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33757 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33758 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33759 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33760 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33761 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33762 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33763 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33764 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33765 + * DAMAGE.
33766 + * ========================================================================== */
33767 +
33768 +#ifndef __DWC_OTG_DRIVER_H__
33769 +#define __DWC_OTG_DRIVER_H__
33770 +
33771 +/** @file
33772 + * This file contains the interface to the Linux driver.
33773 + */
33774 +#include "dwc_otg_os_dep.h"
33775 +#include "dwc_otg_core_if.h"
33776 +
33777 +/* Type declarations */
33778 +struct dwc_otg_pcd;
33779 +struct dwc_otg_hcd;
33780 +
33781 +/**
33782 + * This structure is a wrapper that encapsulates the driver components used to
33783 + * manage a single DWC_otg controller.
33784 + */
33785 +typedef struct dwc_otg_device {
33786 +       /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE
33787 +        * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD
33788 +        * require this. */
33789 +       struct os_dependent os_dep;
33790 +
33791 +       /** Pointer to the core interface structure. */
33792 +       dwc_otg_core_if_t *core_if;
33793 +
33794 +       /** Pointer to the PCD structure. */
33795 +       struct dwc_otg_pcd *pcd;
33796 +
33797 +       /** Pointer to the HCD structure. */
33798 +       struct dwc_otg_hcd *hcd;
33799 +
33800 +       /** Flag to indicate whether the common IRQ handler is installed. */
33801 +       uint8_t common_irq_installed;
33802 +
33803 +} dwc_otg_device_t;
33804 +
33805 +/*We must clear S3C24XX_EINTPEND external interrupt register
33806 + * because after clearing in this register trigerred IRQ from
33807 + * H/W core in kernel interrupt can be occured again before OTG
33808 + * handlers clear all IRQ sources of Core registers because of
33809 + * timing latencies and Low Level IRQ Type.
33810 + */
33811 +#ifdef CONFIG_MACH_IPMATE
33812 +#define  S3C2410X_CLEAR_EINTPEND()   \
33813 +do { \
33814 +       __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
33815 +} while (0)
33816 +#else
33817 +#define  S3C2410X_CLEAR_EINTPEND()   do { } while (0)
33818 +#endif
33819 +
33820 +#endif
33821 --- /dev/null
33822 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
33823 @@ -0,0 +1,3473 @@
33824 +
33825 +/* ==========================================================================
33826 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
33827 + * $Revision: #104 $
33828 + * $Date: 2011/10/24 $
33829 + * $Change: 1871159 $
33830 + *
33831 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
33832 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
33833 + * otherwise expressly agreed to in writing between Synopsys and you.
33834 + *
33835 + * The Software IS NOT an item of Licensed Software or Licensed Product under
33836 + * any End User Software License Agreement or Agreement for Licensed Product
33837 + * with Synopsys or any supplement thereto. You are permitted to use and
33838 + * redistribute this Software in source and binary forms, with or without
33839 + * modification, provided that redistributions of source code must retain this
33840 + * notice. You may not view, use, disclose, copy or distribute this file or
33841 + * any information contained herein except pursuant to this license grant from
33842 + * Synopsys. If you do not agree with this notice, including the disclaimer
33843 + * below, then you are not authorized to use the Software.
33844 + *
33845 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
33846 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33847 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33848 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
33849 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33850 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33851 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33852 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33853 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33854 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33855 + * DAMAGE.
33856 + * ========================================================================== */
33857 +#ifndef DWC_DEVICE_ONLY
33858 +
33859 +/** @file
33860 + * This file implements HCD Core. All code in this file is portable and doesn't
33861 + * use any OS specific functions.
33862 + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
33863 + * header file.
33864 + */
33865 +
33866 +#include "dwc_otg_hcd.h"
33867 +#include "dwc_otg_regs.h"
33868 +
33869 +extern bool microframe_schedule;
33870 +
33871 +//#define DEBUG_HOST_CHANNELS
33872 +#ifdef DEBUG_HOST_CHANNELS
33873 +static int last_sel_trans_num_per_scheduled = 0;
33874 +static int last_sel_trans_num_nonper_scheduled = 0;
33875 +static int last_sel_trans_num_avail_hc_at_start = 0;
33876 +static int last_sel_trans_num_avail_hc_at_end = 0;
33877 +#endif /* DEBUG_HOST_CHANNELS */
33878 +
33879 +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
33880 +{
33881 +       return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
33882 +}
33883 +
33884 +/**
33885 + * Connection timeout function.  An OTG host is required to display a
33886 + * message if the device does not connect within 10 seconds.
33887 + */
33888 +void dwc_otg_hcd_connect_timeout(void *ptr)
33889 +{
33890 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
33891 +       DWC_PRINTF("Connect Timeout\n");
33892 +       __DWC_ERROR("Device Not Connected/Responding\n");
33893 +}
33894 +
33895 +#if defined(DEBUG)
33896 +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
33897 +{
33898 +       if (qh->channel != NULL) {
33899 +               dwc_hc_t *hc = qh->channel;
33900 +               dwc_list_link_t *item;
33901 +               dwc_otg_qh_t *qh_item;
33902 +               int num_channels = hcd->core_if->core_params->host_channels;
33903 +               int i;
33904 +
33905 +               dwc_otg_hc_regs_t *hc_regs;
33906 +               hcchar_data_t hcchar;
33907 +               hcsplt_data_t hcsplt;
33908 +               hctsiz_data_t hctsiz;
33909 +               uint32_t hcdma;
33910 +
33911 +               hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
33912 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
33913 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
33914 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
33915 +               hcdma = DWC_READ_REG32(&hc_regs->hcdma);
33916 +
33917 +               DWC_PRINTF("  Assigned to channel %p:\n", hc);
33918 +               DWC_PRINTF("    hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
33919 +                          hcsplt.d32);
33920 +               DWC_PRINTF("    hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
33921 +                          hcdma);
33922 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
33923 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
33924 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
33925 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
33926 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
33927 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
33928 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
33929 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
33930 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
33931 +               DWC_PRINTF("    qh: %p\n", hc->qh);
33932 +               DWC_PRINTF("  NP inactive sched:\n");
33933 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
33934 +                       qh_item =
33935 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
33936 +                       DWC_PRINTF("    %p\n", qh_item);
33937 +               }
33938 +               DWC_PRINTF("  NP active sched:\n");
33939 +               DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
33940 +                       qh_item =
33941 +                           DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
33942 +                       DWC_PRINTF("    %p\n", qh_item);
33943 +               }
33944 +               DWC_PRINTF("  Channels: \n");
33945 +               for (i = 0; i < num_channels; i++) {
33946 +                       dwc_hc_t *hc = hcd->hc_ptr_array[i];
33947 +                       DWC_PRINTF("    %2d: %p\n", i, hc);
33948 +               }
33949 +       }
33950 +}
33951 +#else
33952 +#define dump_channel_info(hcd, qh)
33953 +#endif /* DEBUG */
33954 +
33955 +/**
33956 + * Work queue function for starting the HCD when A-Cable is connected.
33957 + * The hcd_start() must be called in a process context.
33958 + */
33959 +static void hcd_start_func(void *_vp)
33960 +{
33961 +       dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
33962 +
33963 +       DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
33964 +       if (hcd) {
33965 +               hcd->fops->start(hcd);
33966 +       }
33967 +}
33968 +
33969 +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
33970 +{
33971 +#ifdef DEBUG
33972 +       int i;
33973 +       int num_channels = hcd->core_if->core_params->host_channels;
33974 +       for (i = 0; i < num_channels; i++) {
33975 +               DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
33976 +       }
33977 +#endif
33978 +}
33979 +
33980 +static void del_timers(dwc_otg_hcd_t * hcd)
33981 +{
33982 +       del_xfer_timers(hcd);
33983 +       DWC_TIMER_CANCEL(hcd->conn_timer);
33984 +}
33985 +
33986 +/**
33987 + * Processes all the URBs in a single list of QHs. Completes them with
33988 + * -ETIMEDOUT and frees the QTD.
33989 + */
33990 +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
33991 +{
33992 +       dwc_list_link_t *qh_item;
33993 +       dwc_otg_qh_t *qh;
33994 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
33995 +
33996 +       DWC_LIST_FOREACH(qh_item, qh_list) {
33997 +               qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
33998 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
33999 +                                        &qh->qtd_list, qtd_list_entry) {
34000 +                       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34001 +                       if (qtd->urb != NULL) {
34002 +                               hcd->fops->complete(hcd, qtd->urb->priv,
34003 +                                                   qtd->urb, -DWC_E_TIMEOUT);
34004 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
34005 +                       }
34006 +
34007 +               }
34008 +       }
34009 +}
34010 +
34011 +/**
34012 + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
34013 + * and periodic schedules. The QTD associated with each URB is removed from
34014 + * the schedule and freed. This function may be called when a disconnect is
34015 + * detected or when the HCD is being stopped.
34016 + */
34017 +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
34018 +{
34019 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
34020 +       kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
34021 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
34022 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
34023 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
34024 +       kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
34025 +}
34026 +
34027 +/**
34028 + * Start the connection timer.  An OTG host is required to display a
34029 + * message if the device does not connect within 10 seconds.  The
34030 + * timer is deleted if a port connect interrupt occurs before the
34031 + * timer expires.
34032 + */
34033 +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
34034 +{
34035 +       DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
34036 +}
34037 +
34038 +/**
34039 + * HCD Callback function for disconnect of the HCD.
34040 + *
34041 + * @param p void pointer to the <code>struct usb_hcd</code>
34042 + */
34043 +static int32_t dwc_otg_hcd_session_start_cb(void *p)
34044 +{
34045 +       dwc_otg_hcd_t *dwc_otg_hcd;
34046 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34047 +       dwc_otg_hcd = p;
34048 +       dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
34049 +       return 1;
34050 +}
34051 +
34052 +/**
34053 + * HCD Callback function for starting the HCD when A-Cable is
34054 + * connected.
34055 + *
34056 + * @param p void pointer to the <code>struct usb_hcd</code>
34057 + */
34058 +static int32_t dwc_otg_hcd_start_cb(void *p)
34059 +{
34060 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34061 +       dwc_otg_core_if_t *core_if;
34062 +       hprt0_data_t hprt0;
34063 +
34064 +       core_if = dwc_otg_hcd->core_if;
34065 +
34066 +       if (core_if->op_state == B_HOST) {
34067 +               /*
34068 +                * Reset the port.  During a HNP mode switch the reset
34069 +                * needs to occur within 1ms and have a duration of at
34070 +                * least 50ms.
34071 +                */
34072 +               hprt0.d32 = dwc_otg_read_hprt0(core_if);
34073 +               hprt0.b.prtrst = 1;
34074 +               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34075 +       }
34076 +       DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
34077 +                                  hcd_start_func, dwc_otg_hcd, 50,
34078 +                                  "start hcd");
34079 +
34080 +       return 1;
34081 +}
34082 +
34083 +/**
34084 + * HCD Callback function for disconnect of the HCD.
34085 + *
34086 + * @param p void pointer to the <code>struct usb_hcd</code>
34087 + */
34088 +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
34089 +{
34090 +       gintsts_data_t intr;
34091 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34092 +
34093 +       /*
34094 +        * Set status flags for the hub driver.
34095 +        */
34096 +       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
34097 +       dwc_otg_hcd->flags.b.port_connect_status = 0;
34098 +
34099 +       /*
34100 +        * Shutdown any transfers in process by clearing the Tx FIFO Empty
34101 +        * interrupt mask and status bits and disabling subsequent host
34102 +        * channel interrupts.
34103 +        */
34104 +       intr.d32 = 0;
34105 +       intr.b.nptxfempty = 1;
34106 +       intr.b.ptxfempty = 1;
34107 +       intr.b.hcintr = 1;
34108 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
34109 +                        intr.d32, 0);
34110 +       DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
34111 +                        intr.d32, 0);
34112 +
34113 +       del_timers(dwc_otg_hcd);
34114 +
34115 +       /*
34116 +        * Turn off the vbus power only if the core has transitioned to device
34117 +        * mode. If still in host mode, need to keep power on to detect a
34118 +        * reconnection.
34119 +        */
34120 +       if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
34121 +               if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
34122 +                       hprt0_data_t hprt0 = {.d32 = 0 };
34123 +                       DWC_PRINTF("Disconnect: PortPower off\n");
34124 +                       hprt0.b.prtpwr = 0;
34125 +                       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
34126 +                                       hprt0.d32);
34127 +               }
34128 +
34129 +               dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
34130 +       }
34131 +
34132 +       /* Respond with an error status to all URBs in the schedule. */
34133 +       kill_all_urbs(dwc_otg_hcd);
34134 +
34135 +       if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
34136 +               /* Clean up any host channels that were in use. */
34137 +               int num_channels;
34138 +               int i;
34139 +               dwc_hc_t *channel;
34140 +               dwc_otg_hc_regs_t *hc_regs;
34141 +               hcchar_data_t hcchar;
34142 +
34143 +               num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
34144 +
34145 +               if (!dwc_otg_hcd->core_if->dma_enable) {
34146 +                       /* Flush out any channel requests in slave mode. */
34147 +                       for (i = 0; i < num_channels; i++) {
34148 +                               channel = dwc_otg_hcd->hc_ptr_array[i];
34149 +                               if (DWC_CIRCLEQ_EMPTY_ENTRY
34150 +                                   (channel, hc_list_entry)) {
34151 +                                       hc_regs =
34152 +                                           dwc_otg_hcd->core_if->
34153 +                                           host_if->hc_regs[i];
34154 +                                       hcchar.d32 =
34155 +                                           DWC_READ_REG32(&hc_regs->hcchar);
34156 +                                       if (hcchar.b.chen) {
34157 +                                               hcchar.b.chen = 0;
34158 +                                               hcchar.b.chdis = 1;
34159 +                                               hcchar.b.epdir = 0;
34160 +                                               DWC_WRITE_REG32
34161 +                                                   (&hc_regs->hcchar,
34162 +                                                    hcchar.d32);
34163 +                                       }
34164 +                               }
34165 +                       }
34166 +               }
34167 +
34168 +               for (i = 0; i < num_channels; i++) {
34169 +                       channel = dwc_otg_hcd->hc_ptr_array[i];
34170 +                       if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
34171 +                               hc_regs =
34172 +                                   dwc_otg_hcd->core_if->host_if->hc_regs[i];
34173 +                               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
34174 +                               if (hcchar.b.chen) {
34175 +                                       /* Halt the channel. */
34176 +                                       hcchar.b.chdis = 1;
34177 +                                       DWC_WRITE_REG32(&hc_regs->hcchar,
34178 +                                                       hcchar.d32);
34179 +                               }
34180 +
34181 +                               dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
34182 +                                                  channel);
34183 +                               DWC_CIRCLEQ_INSERT_TAIL
34184 +                                   (&dwc_otg_hcd->free_hc_list, channel,
34185 +                                    hc_list_entry);
34186 +                               /*
34187 +                                * Added for Descriptor DMA to prevent channel double cleanup
34188 +                                * in release_channel_ddma(). Which called from ep_disable
34189 +                                * when device disconnect.
34190 +                                */
34191 +                               channel->qh = NULL;
34192 +                       }
34193 +               }
34194 +       }
34195 +
34196 +       if (dwc_otg_hcd->fops->disconnect) {
34197 +               dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
34198 +       }
34199 +
34200 +       return 1;
34201 +}
34202 +
34203 +/**
34204 + * HCD Callback function for stopping the HCD.
34205 + *
34206 + * @param p void pointer to the <code>struct usb_hcd</code>
34207 + */
34208 +static int32_t dwc_otg_hcd_stop_cb(void *p)
34209 +{
34210 +       dwc_otg_hcd_t *dwc_otg_hcd = p;
34211 +
34212 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
34213 +       dwc_otg_hcd_stop(dwc_otg_hcd);
34214 +       return 1;
34215 +}
34216 +
34217 +#ifdef CONFIG_USB_DWC_OTG_LPM
34218 +/**
34219 + * HCD Callback function for sleep of HCD.
34220 + *
34221 + * @param p void pointer to the <code>struct usb_hcd</code>
34222 + */
34223 +static int dwc_otg_hcd_sleep_cb(void *p)
34224 +{
34225 +       dwc_otg_hcd_t *hcd = p;
34226 +
34227 +       dwc_otg_hcd_free_hc_from_lpm(hcd);
34228 +
34229 +       return 0;
34230 +}
34231 +#endif
34232 +
34233 +/**
34234 + * HCD Callback function for Remote Wakeup.
34235 + *
34236 + * @param p void pointer to the <code>struct usb_hcd</code>
34237 + */
34238 +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
34239 +{
34240 +       dwc_otg_hcd_t *hcd = p;
34241 +
34242 +       if (hcd->core_if->lx_state == DWC_OTG_L2) {
34243 +               hcd->flags.b.port_suspend_change = 1;
34244 +       }
34245 +#ifdef CONFIG_USB_DWC_OTG_LPM
34246 +       else {
34247 +               hcd->flags.b.port_l1_change = 1;
34248 +       }
34249 +#endif
34250 +       return 0;
34251 +}
34252 +
34253 +/**
34254 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
34255 + * stopped.
34256 + */
34257 +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
34258 +{
34259 +       hprt0_data_t hprt0 = {.d32 = 0 };
34260 +
34261 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
34262 +
34263 +       /*
34264 +        * The root hub should be disconnected before this function is called.
34265 +        * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
34266 +        * and the QH lists (via ..._hcd_endpoint_disable).
34267 +        */
34268 +
34269 +       /* Turn off all host-specific interrupts. */
34270 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34271 +
34272 +       /* Turn off the vbus power */
34273 +       DWC_PRINTF("PortPower off\n");
34274 +       hprt0.b.prtpwr = 0;
34275 +       DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
34276 +       dwc_mdelay(1);
34277 +}
34278 +
34279 +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
34280 +                           dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
34281 +                           int atomic_alloc)
34282 +{
34283 +       dwc_irqflags_t flags;
34284 +       int retval = 0;
34285 +       dwc_otg_qtd_t *qtd;
34286 +       gintmsk_data_t intr_mask = {.d32 = 0 };
34287 +
34288 +#ifdef DEBUG /* integrity checks (Broadcom) */
34289 +       if (NULL == hcd->core_if) {
34290 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
34291 +               /* No longer connected. */
34292 +               return -DWC_E_INVALID;
34293 +       }
34294 +#endif
34295 +       if (!hcd->flags.b.port_connect_status) {
34296 +               /* No longer connected. */
34297 +               DWC_ERROR("Not connected\n");
34298 +               return -DWC_E_NO_DEVICE;
34299 +       }
34300 +
34301 +       qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
34302 +       if (qtd == NULL) {
34303 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
34304 +               return -DWC_E_NO_MEMORY;
34305 +       }
34306 +#ifdef DEBUG /* integrity checks (Broadcom) */
34307 +       if (qtd->urb == NULL) {
34308 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
34309 +               return -DWC_E_NO_MEMORY;
34310 +       }
34311 +       if (qtd->urb->priv == NULL) {
34312 +               DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
34313 +               return -DWC_E_NO_MEMORY;
34314 +       }
34315 +#endif
34316 +       retval =
34317 +           dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
34318 +            // creates a new queue in ep_handle if it doesn't exist already
34319 +       if (retval < 0) {
34320 +               DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
34321 +                         "Error status %d\n", retval);
34322 +               dwc_otg_hcd_qtd_free(qtd);
34323 +       } else {
34324 +               qtd->qh = *ep_handle;
34325 +       }
34326 +       intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
34327 +       if (!intr_mask.b.sofintr && retval == 0) {
34328 +               dwc_otg_transaction_type_e tr_type;
34329 +               if ((qtd->qh->ep_type == UE_BULK)
34330 +                   && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
34331 +                       /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
34332 +                       return 0;
34333 +               }
34334 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34335 +               tr_type = dwc_otg_hcd_select_transactions(hcd);
34336 +               if (tr_type != DWC_OTG_TRANSACTION_NONE) {
34337 +                       dwc_otg_hcd_queue_transactions(hcd, tr_type);
34338 +               }
34339 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34340 +       }
34341 +
34342 +       return retval;
34343 +}
34344 +
34345 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
34346 +                           dwc_otg_hcd_urb_t * dwc_otg_urb)
34347 +{
34348 +       dwc_otg_qh_t *qh;
34349 +       dwc_otg_qtd_t *urb_qtd;
34350 +
34351 +#ifdef DEBUG /* integrity checks (Broadcom) */
34352 +
34353 +       if (hcd == NULL) {
34354 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
34355 +               return -DWC_E_INVALID;
34356 +       }
34357 +       if (dwc_otg_urb == NULL) {
34358 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
34359 +               return -DWC_E_INVALID;
34360 +       }
34361 +       if (dwc_otg_urb->qtd == NULL) {
34362 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
34363 +               return -DWC_E_INVALID;
34364 +       }
34365 +       urb_qtd = dwc_otg_urb->qtd;
34366 +       if (urb_qtd->qh == NULL) {
34367 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
34368 +               return -DWC_E_INVALID;
34369 +       }
34370 +#else
34371 +       urb_qtd = dwc_otg_urb->qtd;
34372 +#endif
34373 +       qh = urb_qtd->qh;
34374 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
34375 +               if (urb_qtd->in_process) {
34376 +                       dump_channel_info(hcd, qh);
34377 +               }
34378 +       }
34379 +#ifdef DEBUG /* integrity checks (Broadcom) */
34380 +       if (hcd->core_if == NULL) {
34381 +               DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
34382 +               return -DWC_E_INVALID;
34383 +       }
34384 +#endif
34385 +       if (urb_qtd->in_process && qh->channel) {
34386 +               /* The QTD is in process (it has been assigned to a channel). */
34387 +               if (hcd->flags.b.port_connect_status) {
34388 +                       /*
34389 +                        * If still connected (i.e. in host mode), halt the
34390 +                        * channel so it can be used for other transfers. If
34391 +                        * no longer connected, the host registers can't be
34392 +                        * written to halt the channel since the core is in
34393 +                        * device mode.
34394 +                        */
34395 +                       dwc_otg_hc_halt(hcd->core_if, qh->channel,
34396 +                                       DWC_OTG_HC_XFER_URB_DEQUEUE);
34397 +               }
34398 +       }
34399 +
34400 +       /*
34401 +        * Free the QTD and clean up the associated QH. Leave the QH in the
34402 +        * schedule if it has any remaining QTDs.
34403 +        */
34404 +
34405 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
34406 +                    "delete %sQueue handler\n",
34407 +                    hcd->core_if->dma_desc_enable?"DMA ":"");
34408 +       if (!hcd->core_if->dma_desc_enable) {
34409 +               uint8_t b = urb_qtd->in_process;
34410 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34411 +               if (b) {
34412 +                       dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
34413 +                       qh->channel = NULL;
34414 +               } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
34415 +                       dwc_otg_hcd_qh_remove(hcd, qh);
34416 +               }
34417 +       } else {
34418 +               dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
34419 +       }
34420 +       return 0;
34421 +}
34422 +
34423 +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
34424 +                                int retry)
34425 +{
34426 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34427 +       int retval = 0;
34428 +       dwc_irqflags_t flags;
34429 +
34430 +       if (retry < 0) {
34431 +               retval = -DWC_E_INVALID;
34432 +               goto done;
34433 +       }
34434 +
34435 +       if (!qh) {
34436 +               retval = -DWC_E_INVALID;
34437 +               goto done;
34438 +       }
34439 +
34440 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34441 +
34442 +       while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
34443 +               DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34444 +               retry--;
34445 +               dwc_msleep(5);
34446 +               DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34447 +       }
34448 +
34449 +       dwc_otg_hcd_qh_remove(hcd, qh);
34450 +
34451 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34452 +       /*
34453 +        * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
34454 +        * and qh_free to prevent stack dump on DWC_DMA_FREE() with
34455 +        * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
34456 +        * and dwc_otg_hcd_frame_list_alloc().
34457 +        */
34458 +       dwc_otg_hcd_qh_free(hcd, qh);
34459 +
34460 +done:
34461 +       return retval;
34462 +}
34463 +
34464 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
34465 +int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
34466 +{
34467 +       int retval = 0;
34468 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
34469 +       if (!qh)
34470 +               return -DWC_E_INVALID;
34471 +
34472 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
34473 +       return retval;
34474 +}
34475 +#endif
34476 +
34477 +/**
34478 + * HCD Callback structure for handling mode switching.
34479 + */
34480 +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
34481 +       .start = dwc_otg_hcd_start_cb,
34482 +       .stop = dwc_otg_hcd_stop_cb,
34483 +       .disconnect = dwc_otg_hcd_disconnect_cb,
34484 +       .session_start = dwc_otg_hcd_session_start_cb,
34485 +       .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
34486 +#ifdef CONFIG_USB_DWC_OTG_LPM
34487 +       .sleep = dwc_otg_hcd_sleep_cb,
34488 +#endif
34489 +       .p = 0,
34490 +};
34491 +
34492 +/**
34493 + * Reset tasklet function
34494 + */
34495 +static void reset_tasklet_func(void *data)
34496 +{
34497 +       dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
34498 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
34499 +       hprt0_data_t hprt0;
34500 +
34501 +       DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
34502 +
34503 +       hprt0.d32 = dwc_otg_read_hprt0(core_if);
34504 +       hprt0.b.prtrst = 1;
34505 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34506 +       dwc_mdelay(60);
34507 +
34508 +       hprt0.b.prtrst = 0;
34509 +       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
34510 +       dwc_otg_hcd->flags.b.port_reset_change = 1;
34511 +}
34512 +
34513 +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
34514 +{
34515 +       dwc_list_link_t *item;
34516 +       dwc_otg_qh_t *qh;
34517 +       dwc_irqflags_t flags;
34518 +
34519 +       if (!qh_list->next) {
34520 +               /* The list hasn't been initialized yet. */
34521 +               return;
34522 +       }
34523 +       /*
34524 +        * Hold spinlock here. Not needed in that case if bellow
34525 +        * function is being called from ISR
34526 +        */
34527 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
34528 +       /* Ensure there are no QTDs or URBs left. */
34529 +       kill_urbs_in_qh_list(hcd, qh_list);
34530 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
34531 +
34532 +       DWC_LIST_FOREACH(item, qh_list) {
34533 +               qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
34534 +               dwc_otg_hcd_qh_remove_and_free(hcd, qh);
34535 +       }
34536 +}
34537 +
34538 +/**
34539 + * Exit from Hibernation if Host did not detect SRP from connected SRP capable
34540 + * Device during SRP time by host power up.
34541 + */
34542 +void dwc_otg_hcd_power_up(void *ptr)
34543 +{
34544 +       gpwrdn_data_t gpwrdn = {.d32 = 0 };
34545 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
34546 +
34547 +       DWC_PRINTF("%s called\n", __FUNCTION__);
34548 +
34549 +       if (!core_if->hibernation_suspend) {
34550 +               DWC_PRINTF("Already exited from Hibernation\n");
34551 +               return;
34552 +       }
34553 +
34554 +       /* Switch on the voltage to the core */
34555 +       gpwrdn.b.pwrdnswtch = 1;
34556 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34557 +       dwc_udelay(10);
34558 +
34559 +       /* Reset the core */
34560 +       gpwrdn.d32 = 0;
34561 +       gpwrdn.b.pwrdnrstn = 1;
34562 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34563 +       dwc_udelay(10);
34564 +
34565 +       /* Disable power clamps */
34566 +       gpwrdn.d32 = 0;
34567 +       gpwrdn.b.pwrdnclmp = 1;
34568 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34569 +
34570 +       /* Remove reset the core signal */
34571 +       gpwrdn.d32 = 0;
34572 +       gpwrdn.b.pwrdnrstn = 1;
34573 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
34574 +       dwc_udelay(10);
34575 +
34576 +       /* Disable PMU interrupt */
34577 +       gpwrdn.d32 = 0;
34578 +       gpwrdn.b.pmuintsel = 1;
34579 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34580 +
34581 +       core_if->hibernation_suspend = 0;
34582 +
34583 +       /* Disable PMU */
34584 +       gpwrdn.d32 = 0;
34585 +       gpwrdn.b.pmuactv = 1;
34586 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34587 +       dwc_udelay(10);
34588 +
34589 +       /* Enable VBUS */
34590 +       gpwrdn.d32 = 0;
34591 +       gpwrdn.b.dis_vbus = 1;
34592 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
34593 +
34594 +       core_if->op_state = A_HOST;
34595 +       dwc_otg_core_init(core_if);
34596 +       dwc_otg_enable_global_interrupts(core_if);
34597 +       cil_hcd_start(core_if);
34598 +}
34599 +
34600 +/**
34601 + * Frees secondary storage associated with the dwc_otg_hcd structure contained
34602 + * in the struct usb_hcd field.
34603 + */
34604 +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
34605 +{
34606 +       int i;
34607 +
34608 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
34609 +
34610 +       del_timers(dwc_otg_hcd);
34611 +
34612 +       /* Free memory for QH/QTD lists */
34613 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
34614 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
34615 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
34616 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
34617 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
34618 +       qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
34619 +
34620 +       /* Free memory for the host channels. */
34621 +       for (i = 0; i < MAX_EPS_CHANNELS; i++) {
34622 +               dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
34623 +
34624 +#ifdef DEBUG
34625 +               if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
34626 +                       DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
34627 +               }
34628 +#endif
34629 +               if (hc != NULL) {
34630 +                       DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
34631 +                                   i, hc);
34632 +                       DWC_FREE(hc);
34633 +               }
34634 +       }
34635 +
34636 +       if (dwc_otg_hcd->core_if->dma_enable) {
34637 +               if (dwc_otg_hcd->status_buf_dma) {
34638 +                       DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
34639 +                                    dwc_otg_hcd->status_buf,
34640 +                                    dwc_otg_hcd->status_buf_dma);
34641 +               }
34642 +       } else if (dwc_otg_hcd->status_buf != NULL) {
34643 +               DWC_FREE(dwc_otg_hcd->status_buf);
34644 +       }
34645 +       DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
34646 +       /* Set core_if's lock pointer to NULL */
34647 +       dwc_otg_hcd->core_if->lock = NULL;
34648 +
34649 +       DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
34650 +       DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
34651 +
34652 +#ifdef DWC_DEV_SRPCAP
34653 +       if (dwc_otg_hcd->core_if->power_down == 2 &&
34654 +           dwc_otg_hcd->core_if->pwron_timer) {
34655 +               DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
34656 +       }
34657 +#endif
34658 +       DWC_FREE(dwc_otg_hcd);
34659 +}
34660 +
34661 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
34662 +
34663 +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
34664 +{
34665 +       int retval = 0;
34666 +       int num_channels;
34667 +       int i;
34668 +       dwc_hc_t *channel;
34669 +
34670 +       hcd->lock = DWC_SPINLOCK_ALLOC();
34671 +        DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
34672 +                    hcd, core_if);
34673 +       if (!hcd->lock) {
34674 +               DWC_ERROR("Could not allocate lock for pcd");
34675 +               DWC_FREE(hcd);
34676 +               retval = -DWC_E_NO_MEMORY;
34677 +               goto out;
34678 +       }
34679 +       hcd->core_if = core_if;
34680 +
34681 +       /* Register the HCD CIL Callbacks */
34682 +       dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
34683 +                                          &hcd_cil_callbacks, hcd);
34684 +
34685 +       /* Initialize the non-periodic schedule. */
34686 +       DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
34687 +       DWC_LIST_INIT(&hcd->non_periodic_sched_active);
34688 +
34689 +       /* Initialize the periodic schedule. */
34690 +       DWC_LIST_INIT(&hcd->periodic_sched_inactive);
34691 +       DWC_LIST_INIT(&hcd->periodic_sched_ready);
34692 +       DWC_LIST_INIT(&hcd->periodic_sched_assigned);
34693 +       DWC_LIST_INIT(&hcd->periodic_sched_queued);
34694 +
34695 +       /*
34696 +        * Create a host channel descriptor for each host channel implemented
34697 +        * in the controller. Initialize the channel descriptor array.
34698 +        */
34699 +       DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
34700 +       num_channels = hcd->core_if->core_params->host_channels;
34701 +       DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
34702 +       for (i = 0; i < num_channels; i++) {
34703 +               channel = DWC_ALLOC(sizeof(dwc_hc_t));
34704 +               if (channel == NULL) {
34705 +                       retval = -DWC_E_NO_MEMORY;
34706 +                       DWC_ERROR("%s: host channel allocation failed\n",
34707 +                                 __func__);
34708 +                       dwc_otg_hcd_free(hcd);
34709 +                       goto out;
34710 +               }
34711 +               channel->hc_num = i;
34712 +               hcd->hc_ptr_array[i] = channel;
34713 +#ifdef DEBUG
34714 +               hcd->core_if->hc_xfer_timer[i] =
34715 +                   DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
34716 +                                   &hcd->core_if->hc_xfer_info[i]);
34717 +#endif
34718 +               DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
34719 +                           channel);
34720 +       }
34721 +
34722 +       /* Initialize the Connection timeout timer. */
34723 +       hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
34724 +                                         dwc_otg_hcd_connect_timeout, 0);
34725 +
34726 +       printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
34727 +       if (microframe_schedule)
34728 +               init_hcd_usecs(hcd);
34729 +
34730 +       /* Initialize reset tasklet. */
34731 +       hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
34732 +#ifdef DWC_DEV_SRPCAP
34733 +       if (hcd->core_if->power_down == 2) {
34734 +               /* Initialize Power on timer for Host power up in case hibernation */
34735 +               hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
34736 +                                                                       dwc_otg_hcd_power_up, core_if);
34737 +       }
34738 +#endif
34739 +
34740 +       /*
34741 +        * Allocate space for storing data on status transactions. Normally no
34742 +        * data is sent, but this space acts as a bit bucket. This must be
34743 +        * done after usb_add_hcd since that function allocates the DMA buffer
34744 +        * pool.
34745 +        */
34746 +       if (hcd->core_if->dma_enable) {
34747 +               hcd->status_buf =
34748 +                   DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
34749 +                                 &hcd->status_buf_dma);
34750 +       } else {
34751 +               hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
34752 +       }
34753 +       if (!hcd->status_buf) {
34754 +               retval = -DWC_E_NO_MEMORY;
34755 +               DWC_ERROR("%s: status_buf allocation failed\n", __func__);
34756 +               dwc_otg_hcd_free(hcd);
34757 +               goto out;
34758 +       }
34759 +
34760 +       hcd->otg_port = 1;
34761 +       hcd->frame_list = NULL;
34762 +       hcd->frame_list_dma = 0;
34763 +       hcd->periodic_qh_count = 0;
34764 +out:
34765 +       return retval;
34766 +}
34767 +
34768 +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
34769 +{
34770 +       /* Turn off all host-specific interrupts. */
34771 +       dwc_otg_disable_host_interrupts(hcd->core_if);
34772 +
34773 +       dwc_otg_hcd_free(hcd);
34774 +}
34775 +
34776 +/**
34777 + * Initializes dynamic portions of the DWC_otg HCD state.
34778 + */
34779 +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
34780 +{
34781 +       int num_channels;
34782 +       int i;
34783 +       dwc_hc_t *channel;
34784 +       dwc_hc_t *channel_tmp;
34785 +
34786 +       hcd->flags.d32 = 0;
34787 +
34788 +       hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
34789 +       if (!microframe_schedule) {
34790 +               hcd->non_periodic_channels = 0;
34791 +               hcd->periodic_channels = 0;
34792 +       } else {
34793 +               hcd->available_host_channels = hcd->core_if->core_params->host_channels;
34794 +       }
34795 +       /*
34796 +        * Put all channels in the free channel list and clean up channel
34797 +        * states.
34798 +        */
34799 +       DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
34800 +                                &hcd->free_hc_list, hc_list_entry) {
34801 +               DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
34802 +       }
34803 +
34804 +       num_channels = hcd->core_if->core_params->host_channels;
34805 +       for (i = 0; i < num_channels; i++) {
34806 +               channel = hcd->hc_ptr_array[i];
34807 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
34808 +                                       hc_list_entry);
34809 +               dwc_otg_hc_cleanup(hcd->core_if, channel);
34810 +       }
34811 +
34812 +       /* Initialize the DWC core for host mode operation. */
34813 +       dwc_otg_core_host_init(hcd->core_if);
34814 +
34815 +       /* Set core_if's lock pointer to the hcd->lock */
34816 +       hcd->core_if->lock = hcd->lock;
34817 +}
34818 +
34819 +/**
34820 + * Assigns transactions from a QTD to a free host channel and initializes the
34821 + * host channel to perform the transactions. The host channel is removed from
34822 + * the free list.
34823 + *
34824 + * @param hcd The HCD state structure.
34825 + * @param qh Transactions from the first QTD for this QH are selected and
34826 + * assigned to a free host channel.
34827 + */
34828 +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
34829 +{
34830 +       dwc_hc_t *hc;
34831 +       dwc_otg_qtd_t *qtd;
34832 +       dwc_otg_hcd_urb_t *urb;
34833 +       void* ptr = NULL;
34834 +
34835 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
34836 +
34837 +       urb = qtd->urb;
34838 +
34839 +       DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
34840 +
34841 +       if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
34842 +               urb->actual_length = urb->length;
34843 +
34844 +
34845 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
34846 +
34847 +       /* Remove the host channel from the free list. */
34848 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
34849 +
34850 +       qh->channel = hc;
34851 +
34852 +       qtd->in_process = 1;
34853 +
34854 +       /*
34855 +        * Use usb_pipedevice to determine device address. This address is
34856 +        * 0 before the SET_ADDRESS command and the correct address afterward.
34857 +        */
34858 +       hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
34859 +       hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
34860 +       hc->speed = qh->dev_speed;
34861 +       hc->max_packet = dwc_max_packet(qh->maxp);
34862 +
34863 +       hc->xfer_started = 0;
34864 +       hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
34865 +       hc->error_state = (qtd->error_count > 0);
34866 +       hc->halt_on_queue = 0;
34867 +       hc->halt_pending = 0;
34868 +       hc->requests = 0;
34869 +
34870 +       /*
34871 +        * The following values may be modified in the transfer type section
34872 +        * below. The xfer_len value may be reduced when the transfer is
34873 +        * started to accommodate the max widths of the XferSize and PktCnt
34874 +        * fields in the HCTSIZn register.
34875 +        */
34876 +
34877 +       hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
34878 +       if (hc->ep_is_in) {
34879 +               hc->do_ping = 0;
34880 +       } else {
34881 +               hc->do_ping = qh->ping_state;
34882 +       }
34883 +
34884 +       hc->data_pid_start = qh->data_toggle;
34885 +       hc->multi_count = 1;
34886 +
34887 +       if (hcd->core_if->dma_enable) {
34888 +               hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
34889 +
34890 +               /* For non-dword aligned case */
34891 +               if (((unsigned long)hc->xfer_buff & 0x3)
34892 +                   && !hcd->core_if->dma_desc_enable) {
34893 +                       ptr = (uint8_t *) urb->buf + urb->actual_length;
34894 +               }
34895 +       } else {
34896 +               hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
34897 +       }
34898 +       hc->xfer_len = urb->length - urb->actual_length;
34899 +       hc->xfer_count = 0;
34900 +
34901 +       /*
34902 +        * Set the split attributes
34903 +        */
34904 +       hc->do_split = 0;
34905 +       if (qh->do_split) {
34906 +               uint32_t hub_addr, port_addr;
34907 +               hc->do_split = 1;
34908 +               hc->xact_pos = qtd->isoc_split_pos;
34909 +               hc->complete_split = qtd->complete_split;
34910 +               hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
34911 +               hc->hub_addr = (uint8_t) hub_addr;
34912 +               hc->port_addr = (uint8_t) port_addr;
34913 +       }
34914 +
34915 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
34916 +       case UE_CONTROL:
34917 +               hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
34918 +               switch (qtd->control_phase) {
34919 +               case DWC_OTG_CONTROL_SETUP:
34920 +                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction\n");
34921 +                       hc->do_ping = 0;
34922 +                       hc->ep_is_in = 0;
34923 +                       hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
34924 +                       if (hcd->core_if->dma_enable) {
34925 +                               hc->xfer_buff = (uint8_t *) urb->setup_dma;
34926 +                       } else {
34927 +                               hc->xfer_buff = (uint8_t *) urb->setup_packet;
34928 +                       }
34929 +                       hc->xfer_len = 8;
34930 +                       ptr = NULL;
34931 +                       break;
34932 +               case DWC_OTG_CONTROL_DATA:
34933 +                       DWC_DEBUGPL(DBG_HCDV, "  Control data transaction\n");
34934 +                       hc->data_pid_start = qtd->data_toggle;
34935 +                       break;
34936 +               case DWC_OTG_CONTROL_STATUS:
34937 +                       /*
34938 +                        * Direction is opposite of data direction or IN if no
34939 +                        * data.
34940 +                        */
34941 +                       DWC_DEBUGPL(DBG_HCDV, "  Control status transaction\n");
34942 +                       if (urb->length == 0) {
34943 +                               hc->ep_is_in = 1;
34944 +                       } else {
34945 +                               hc->ep_is_in =
34946 +                                   dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
34947 +                       }
34948 +                       if (hc->ep_is_in) {
34949 +                               hc->do_ping = 0;
34950 +                       }
34951 +
34952 +                       hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
34953 +
34954 +                       hc->xfer_len = 0;
34955 +                       if (hcd->core_if->dma_enable) {
34956 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
34957 +                       } else {
34958 +                               hc->xfer_buff = (uint8_t *) hcd->status_buf;
34959 +                       }
34960 +                       ptr = NULL;
34961 +                       break;
34962 +               }
34963 +               break;
34964 +       case UE_BULK:
34965 +               hc->ep_type = DWC_OTG_EP_TYPE_BULK;
34966 +               break;
34967 +       case UE_INTERRUPT:
34968 +               hc->ep_type = DWC_OTG_EP_TYPE_INTR;
34969 +               break;
34970 +       case UE_ISOCHRONOUS:
34971 +               {
34972 +                       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
34973 +
34974 +                       hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
34975 +
34976 +                       if (hcd->core_if->dma_desc_enable)
34977 +                               break;
34978 +
34979 +                       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
34980 +
34981 +                       frame_desc->status = 0;
34982 +
34983 +                       if (hcd->core_if->dma_enable) {
34984 +                               hc->xfer_buff = (uint8_t *) urb->dma;
34985 +                       } else {
34986 +                               hc->xfer_buff = (uint8_t *) urb->buf;
34987 +                       }
34988 +                       hc->xfer_buff +=
34989 +                           frame_desc->offset + qtd->isoc_split_offset;
34990 +                       hc->xfer_len =
34991 +                           frame_desc->length - qtd->isoc_split_offset;
34992 +
34993 +                       /* For non-dword aligned buffers */
34994 +                       if (((unsigned long)hc->xfer_buff & 0x3)
34995 +                           && hcd->core_if->dma_enable) {
34996 +                               ptr =
34997 +                                   (uint8_t *) urb->buf + frame_desc->offset +
34998 +                                   qtd->isoc_split_offset;
34999 +                       } else
35000 +                               ptr = NULL;
35001 +
35002 +                       if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
35003 +                               if (hc->xfer_len <= 188) {
35004 +                                       hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
35005 +                               } else {
35006 +                                       hc->xact_pos =
35007 +                                           DWC_HCSPLIT_XACTPOS_BEGIN;
35008 +                               }
35009 +                       }
35010 +               }
35011 +               break;
35012 +       }
35013 +       /* non DWORD-aligned buffer case */
35014 +       if (ptr) {
35015 +               uint32_t buf_size;
35016 +               if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
35017 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
35018 +               } else {
35019 +                       buf_size = 4096;
35020 +               }
35021 +               if (!qh->dw_align_buf) {
35022 +                       qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
35023 +                                                        &qh->dw_align_buf_dma);
35024 +                       if (!qh->dw_align_buf) {
35025 +                               DWC_ERROR
35026 +                                   ("%s: Failed to allocate memory to handle "
35027 +                                    "non-dword aligned buffer case\n",
35028 +                                    __func__);
35029 +                               return;
35030 +                       }
35031 +               }
35032 +               if (!hc->ep_is_in) {
35033 +                       dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
35034 +               }
35035 +               hc->align_buff = qh->dw_align_buf_dma;
35036 +       } else {
35037 +               hc->align_buff = 0;
35038 +       }
35039 +
35040 +       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
35041 +           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
35042 +               /*
35043 +                * This value may be modified when the transfer is started to
35044 +                * reflect the actual transfer length.
35045 +                */
35046 +               hc->multi_count = dwc_hb_mult(qh->maxp);
35047 +       }
35048 +
35049 +       if (hcd->core_if->dma_desc_enable)
35050 +               hc->desc_list_addr = qh->desc_list_dma;
35051 +
35052 +       dwc_otg_hc_init(hcd->core_if, hc);
35053 +       hc->qh = qh;
35054 +}
35055 +
35056 +/**
35057 + * This function selects transactions from the HCD transfer schedule and
35058 + * assigns them to available host channels. It is called from HCD interrupt
35059 + * handler functions.
35060 + *
35061 + * @param hcd The HCD state structure.
35062 + *
35063 + * @return The types of new transactions that were assigned to host channels.
35064 + */
35065 +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
35066 +{
35067 +       dwc_list_link_t *qh_ptr;
35068 +       dwc_otg_qh_t *qh;
35069 +       int num_channels;
35070 +       dwc_irqflags_t flags;
35071 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
35072 +       dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
35073 +
35074 +#ifdef DEBUG_SOF
35075 +       DWC_DEBUGPL(DBG_HCD, "  Select Transactions\n");
35076 +#endif
35077 +
35078 +#ifdef DEBUG_HOST_CHANNELS
35079 +       last_sel_trans_num_per_scheduled = 0;
35080 +       last_sel_trans_num_nonper_scheduled = 0;
35081 +       last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
35082 +#endif /* DEBUG_HOST_CHANNELS */
35083 +
35084 +       /* Process entries in the periodic ready list. */
35085 +       qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
35086 +
35087 +       while (qh_ptr != &hcd->periodic_sched_ready &&
35088 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35089 +               if (microframe_schedule) {
35090 +                       // Make sure we leave one channel for non periodic transactions.
35091 +                       DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35092 +                       if (hcd->available_host_channels <= 1) {
35093 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35094 +                               break;
35095 +                       }
35096 +                       hcd->available_host_channels--;
35097 +                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35098 +#ifdef DEBUG_HOST_CHANNELS
35099 +                       last_sel_trans_num_per_scheduled++;
35100 +#endif /* DEBUG_HOST_CHANNELS */
35101 +               }
35102 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35103 +               assign_and_init_hc(hcd, qh);
35104 +
35105 +               /*
35106 +                * Move the QH from the periodic ready schedule to the
35107 +                * periodic assigned schedule.
35108 +                */
35109 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35110 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35111 +               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
35112 +                                  &qh->qh_list_entry);
35113 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35114 +
35115 +               ret_val = DWC_OTG_TRANSACTION_PERIODIC;
35116 +       }
35117 +
35118 +       /*
35119 +        * Process entries in the inactive portion of the non-periodic
35120 +        * schedule. Some free host channels may not be used if they are
35121 +        * reserved for periodic transfers.
35122 +        */
35123 +       qh_ptr = hcd->non_periodic_sched_inactive.next;
35124 +       num_channels = hcd->core_if->core_params->host_channels;
35125 +       while (qh_ptr != &hcd->non_periodic_sched_inactive &&
35126 +              (microframe_schedule || hcd->non_periodic_channels <
35127 +               num_channels - hcd->periodic_channels) &&
35128 +              !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
35129 +
35130 +               if (microframe_schedule) {
35131 +                               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35132 +                               if (hcd->available_host_channels < 1) {
35133 +                                       DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35134 +                                       break;
35135 +                               }
35136 +                               hcd->available_host_channels--;
35137 +                               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35138 +#ifdef DEBUG_HOST_CHANNELS
35139 +                               last_sel_trans_num_nonper_scheduled++;
35140 +#endif /* DEBUG_HOST_CHANNELS */
35141 +               }
35142 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35143 +
35144 +               assign_and_init_hc(hcd, qh);
35145 +
35146 +               /*
35147 +                * Move the QH from the non-periodic inactive schedule to the
35148 +                * non-periodic active schedule.
35149 +                */
35150 +               qh_ptr = DWC_LIST_NEXT(qh_ptr);
35151 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
35152 +               DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
35153 +                                  &qh->qh_list_entry);
35154 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
35155 +
35156 +               if (ret_val == DWC_OTG_TRANSACTION_NONE) {
35157 +                       ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
35158 +               } else {
35159 +                       ret_val = DWC_OTG_TRANSACTION_ALL;
35160 +               }
35161 +
35162 +               if (!microframe_schedule)
35163 +                       hcd->non_periodic_channels++;
35164 +       }
35165 +
35166 +#ifdef DEBUG_HOST_CHANNELS
35167 +       last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
35168 +#endif /* DEBUG_HOST_CHANNELS */
35169 +
35170 +       DWC_SPINLOCK_FREE(channel_lock);
35171 +       return ret_val;
35172 +}
35173 +
35174 +/**
35175 + * Attempts to queue a single transaction request for a host channel
35176 + * associated with either a periodic or non-periodic transfer. This function
35177 + * assumes that there is space available in the appropriate request queue. For
35178 + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
35179 + * is available in the appropriate Tx FIFO.
35180 + *
35181 + * @param hcd The HCD state structure.
35182 + * @param hc Host channel descriptor associated with either a periodic or
35183 + * non-periodic transfer.
35184 + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
35185 + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
35186 + * transfers.
35187 + *
35188 + * @return 1 if a request is queued and more requests may be needed to
35189 + * complete the transfer, 0 if no more requests are required for this
35190 + * transfer, -1 if there is insufficient space in the Tx FIFO.
35191 + */
35192 +static int queue_transaction(dwc_otg_hcd_t * hcd,
35193 +                            dwc_hc_t * hc, uint16_t fifo_dwords_avail)
35194 +{
35195 +       int retval;
35196 +
35197 +       if (hcd->core_if->dma_enable) {
35198 +               if (hcd->core_if->dma_desc_enable) {
35199 +                       if (!hc->xfer_started
35200 +                           || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
35201 +                               dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
35202 +                               hc->qh->ping_state = 0;
35203 +                       }
35204 +               } else if (!hc->xfer_started) {
35205 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35206 +                       hc->qh->ping_state = 0;
35207 +               }
35208 +               retval = 0;
35209 +       } else if (hc->halt_pending) {
35210 +               /* Don't queue a request if the channel has been halted. */
35211 +               retval = 0;
35212 +       } else if (hc->halt_on_queue) {
35213 +               dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
35214 +               retval = 0;
35215 +       } else if (hc->do_ping) {
35216 +               if (!hc->xfer_started) {
35217 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35218 +               }
35219 +               retval = 0;
35220 +       } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
35221 +               if ((fifo_dwords_avail * 4) >= hc->max_packet) {
35222 +                       if (!hc->xfer_started) {
35223 +                               dwc_otg_hc_start_transfer(hcd->core_if, hc);
35224 +                               retval = 1;
35225 +                       } else {
35226 +                               retval =
35227 +                                   dwc_otg_hc_continue_transfer(hcd->core_if,
35228 +                                                                hc);
35229 +                       }
35230 +               } else {
35231 +                       retval = -1;
35232 +               }
35233 +       } else {
35234 +               if (!hc->xfer_started) {
35235 +                       dwc_otg_hc_start_transfer(hcd->core_if, hc);
35236 +                       retval = 1;
35237 +               } else {
35238 +                       retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
35239 +               }
35240 +       }
35241 +
35242 +       return retval;
35243 +}
35244 +
35245 +/**
35246 + * Processes periodic channels for the next frame and queues transactions for
35247 + * these channels to the DWC_otg controller. After queueing transactions, the
35248 + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
35249 + * to queue as Periodic Tx FIFO or request queue space becomes available.
35250 + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
35251 + */
35252 +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
35253 +{
35254 +       hptxsts_data_t tx_status;
35255 +       dwc_list_link_t *qh_ptr;
35256 +       dwc_otg_qh_t *qh;
35257 +       int status;
35258 +       int no_queue_space = 0;
35259 +       int no_fifo_space = 0;
35260 +
35261 +       dwc_otg_host_global_regs_t *host_regs;
35262 +       host_regs = hcd->core_if->host_if->host_global_regs;
35263 +
35264 +       DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
35265 +#ifdef DEBUG
35266 +       tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35267 +       DWC_DEBUGPL(DBG_HCDV,
35268 +                   "  P Tx Req Queue Space Avail (before queue): %d\n",
35269 +                   tx_status.b.ptxqspcavail);
35270 +       DWC_DEBUGPL(DBG_HCDV, "  P Tx FIFO Space Avail (before queue): %d\n",
35271 +                   tx_status.b.ptxfspcavail);
35272 +#endif
35273 +
35274 +       qh_ptr = hcd->periodic_sched_assigned.next;
35275 +       while (qh_ptr != &hcd->periodic_sched_assigned) {
35276 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35277 +               if (tx_status.b.ptxqspcavail == 0) {
35278 +                       no_queue_space = 1;
35279 +                       break;
35280 +               }
35281 +
35282 +               qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
35283 +
35284 +               /*
35285 +                * Set a flag if we're queuing high-bandwidth in slave mode.
35286 +                * The flag prevents any halts to get into the request queue in
35287 +                * the middle of multiple high-bandwidth packets getting queued.
35288 +                */
35289 +               if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
35290 +                       hcd->core_if->queuing_high_bandwidth = 1;
35291 +               }
35292 +               status =
35293 +                   queue_transaction(hcd, qh->channel,
35294 +                                     tx_status.b.ptxfspcavail);
35295 +               if (status < 0) {
35296 +                       no_fifo_space = 1;
35297 +                       break;
35298 +               }
35299 +
35300 +               /*
35301 +                * In Slave mode, stay on the current transfer until there is
35302 +                * nothing more to do or the high-bandwidth request count is
35303 +                * reached. In DMA mode, only need to queue one request. The
35304 +                * controller automatically handles multiple packets for
35305 +                * high-bandwidth transfers.
35306 +                */
35307 +               if (hcd->core_if->dma_enable || status == 0 ||
35308 +                   qh->channel->requests == qh->channel->multi_count) {
35309 +                       qh_ptr = qh_ptr->next;
35310 +                       /*
35311 +                        * Move the QH from the periodic assigned schedule to
35312 +                        * the periodic queued schedule.
35313 +                        */
35314 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
35315 +                                          &qh->qh_list_entry);
35316 +
35317 +                       /* done queuing high bandwidth */
35318 +                       hcd->core_if->queuing_high_bandwidth = 0;
35319 +               }
35320 +       }
35321 +
35322 +       if (!hcd->core_if->dma_enable) {
35323 +               dwc_otg_core_global_regs_t *global_regs;
35324 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35325 +
35326 +               global_regs = hcd->core_if->core_global_regs;
35327 +               intr_mask.b.ptxfempty = 1;
35328 +#ifdef DEBUG
35329 +               tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
35330 +               DWC_DEBUGPL(DBG_HCDV,
35331 +                           "  P Tx Req Queue Space Avail (after queue): %d\n",
35332 +                           tx_status.b.ptxqspcavail);
35333 +               DWC_DEBUGPL(DBG_HCDV,
35334 +                           "  P Tx FIFO Space Avail (after queue): %d\n",
35335 +                           tx_status.b.ptxfspcavail);
35336 +#endif
35337 +               if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
35338 +                   no_queue_space || no_fifo_space) {
35339 +                       /*
35340 +                        * May need to queue more transactions as the request
35341 +                        * queue or Tx FIFO empties. Enable the periodic Tx
35342 +                        * FIFO empty interrupt. (Always use the half-empty
35343 +                        * level to ensure that new requests are loaded as
35344 +                        * soon as possible.)
35345 +                        */
35346 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35347 +                                        intr_mask.d32);
35348 +               } else {
35349 +                       /*
35350 +                        * Disable the Tx FIFO empty interrupt since there are
35351 +                        * no more transactions that need to be queued right
35352 +                        * now. This function is called from interrupt
35353 +                        * handlers to queue more transactions as transfer
35354 +                        * states change.
35355 +                        */
35356 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35357 +                                        0);
35358 +               }
35359 +       }
35360 +}
35361 +
35362 +/**
35363 + * Processes active non-periodic channels and queues transactions for these
35364 + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
35365 + * FIFO Empty interrupt is enabled if there are more transactions to queue as
35366 + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
35367 + * FIFO Empty interrupt is disabled.
35368 + */
35369 +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
35370 +{
35371 +       gnptxsts_data_t tx_status;
35372 +       dwc_list_link_t *orig_qh_ptr;
35373 +       dwc_otg_qh_t *qh;
35374 +       int status;
35375 +       int no_queue_space = 0;
35376 +       int no_fifo_space = 0;
35377 +       int more_to_do = 0;
35378 +
35379 +       dwc_otg_core_global_regs_t *global_regs =
35380 +           hcd->core_if->core_global_regs;
35381 +
35382 +       DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
35383 +#ifdef DEBUG
35384 +       tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35385 +       DWC_DEBUGPL(DBG_HCDV,
35386 +                   "  NP Tx Req Queue Space Avail (before queue): %d\n",
35387 +                   tx_status.b.nptxqspcavail);
35388 +       DWC_DEBUGPL(DBG_HCDV, "  NP Tx FIFO Space Avail (before queue): %d\n",
35389 +                   tx_status.b.nptxfspcavail);
35390 +#endif
35391 +       /*
35392 +        * Keep track of the starting point. Skip over the start-of-list
35393 +        * entry.
35394 +        */
35395 +       if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35396 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35397 +       }
35398 +       orig_qh_ptr = hcd->non_periodic_qh_ptr;
35399 +
35400 +       /*
35401 +        * Process once through the active list or until no more space is
35402 +        * available in the request queue or the Tx FIFO.
35403 +        */
35404 +       do {
35405 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35406 +               if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
35407 +                       no_queue_space = 1;
35408 +                       break;
35409 +               }
35410 +
35411 +               qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
35412 +                                   qh_list_entry);
35413 +               status =
35414 +                   queue_transaction(hcd, qh->channel,
35415 +                                     tx_status.b.nptxfspcavail);
35416 +
35417 +               if (status > 0) {
35418 +                       more_to_do = 1;
35419 +               } else if (status < 0) {
35420 +                       no_fifo_space = 1;
35421 +                       break;
35422 +               }
35423 +
35424 +               /* Advance to next QH, skipping start-of-list entry. */
35425 +               hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
35426 +               if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
35427 +                       hcd->non_periodic_qh_ptr =
35428 +                           hcd->non_periodic_qh_ptr->next;
35429 +               }
35430 +
35431 +       } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
35432 +
35433 +       if (!hcd->core_if->dma_enable) {
35434 +               gintmsk_data_t intr_mask = {.d32 = 0 };
35435 +               intr_mask.b.nptxfempty = 1;
35436 +
35437 +#ifdef DEBUG
35438 +               tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
35439 +               DWC_DEBUGPL(DBG_HCDV,
35440 +                           "  NP Tx Req Queue Space Avail (after queue): %d\n",
35441 +                           tx_status.b.nptxqspcavail);
35442 +               DWC_DEBUGPL(DBG_HCDV,
35443 +                           "  NP Tx FIFO Space Avail (after queue): %d\n",
35444 +                           tx_status.b.nptxfspcavail);
35445 +#endif
35446 +               if (more_to_do || no_queue_space || no_fifo_space) {
35447 +                       /*
35448 +                        * May need to queue more transactions as the request
35449 +                        * queue or Tx FIFO empties. Enable the non-periodic
35450 +                        * Tx FIFO empty interrupt. (Always use the half-empty
35451 +                        * level to ensure that new requests are loaded as
35452 +                        * soon as possible.)
35453 +                        */
35454 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
35455 +                                        intr_mask.d32);
35456 +               } else {
35457 +                       /*
35458 +                        * Disable the Tx FIFO empty interrupt since there are
35459 +                        * no more transactions that need to be queued right
35460 +                        * now. This function is called from interrupt
35461 +                        * handlers to queue more transactions as transfer
35462 +                        * states change.
35463 +                        */
35464 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
35465 +                                        0);
35466 +               }
35467 +       }
35468 +}
35469 +
35470 +/**
35471 + * This function processes the currently active host channels and queues
35472 + * transactions for these channels to the DWC_otg controller. It is called
35473 + * from HCD interrupt handler functions.
35474 + *
35475 + * @param hcd The HCD state structure.
35476 + * @param tr_type The type(s) of transactions to queue (non-periodic,
35477 + * periodic, or both).
35478 + */
35479 +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
35480 +                                   dwc_otg_transaction_type_e tr_type)
35481 +{
35482 +#ifdef DEBUG_SOF
35483 +       DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
35484 +#endif
35485 +       /* Process host channels associated with periodic transfers. */
35486 +       if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
35487 +            tr_type == DWC_OTG_TRANSACTION_ALL) &&
35488 +           !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
35489 +
35490 +               process_periodic_channels(hcd);
35491 +       }
35492 +
35493 +       /* Process host channels associated with non-periodic transfers. */
35494 +       if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
35495 +           tr_type == DWC_OTG_TRANSACTION_ALL) {
35496 +               if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
35497 +                       process_non_periodic_channels(hcd);
35498 +               } else {
35499 +                       /*
35500 +                        * Ensure NP Tx FIFO empty interrupt is disabled when
35501 +                        * there are no non-periodic transfers to process.
35502 +                        */
35503 +                       gintmsk_data_t gintmsk = {.d32 = 0 };
35504 +                       gintmsk.b.nptxfempty = 1;
35505 +                       DWC_MODIFY_REG32(&hcd->core_if->
35506 +                                        core_global_regs->gintmsk, gintmsk.d32,
35507 +                                        0);
35508 +               }
35509 +       }
35510 +}
35511 +
35512 +#ifdef DWC_HS_ELECT_TST
35513 +/*
35514 + * Quick and dirty hack to implement the HS Electrical Test
35515 + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
35516 + *
35517 + * This code was copied from our userspace app "hset". It sends a
35518 + * Get Device Descriptor control sequence in two parts, first the
35519 + * Setup packet by itself, followed some time later by the In and
35520 + * Ack packets. Rather than trying to figure out how to add this
35521 + * functionality to the normal driver code, we just hijack the
35522 + * hardware, using these two function to drive the hardware
35523 + * directly.
35524 + */
35525 +
35526 +static dwc_otg_core_global_regs_t *global_regs;
35527 +static dwc_otg_host_global_regs_t *hc_global_regs;
35528 +static dwc_otg_hc_regs_t *hc_regs;
35529 +static uint32_t *data_fifo;
35530 +
35531 +static void do_setup(void)
35532 +{
35533 +       gintsts_data_t gintsts;
35534 +       hctsiz_data_t hctsiz;
35535 +       hcchar_data_t hcchar;
35536 +       haint_data_t haint;
35537 +       hcint_data_t hcint;
35538 +
35539 +       /* Enable HAINTs */
35540 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35541 +
35542 +       /* Enable HCINTs */
35543 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35544 +
35545 +       /* Read GINTSTS */
35546 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35547 +
35548 +       /* Read HAINT */
35549 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35550 +
35551 +       /* Read HCINT */
35552 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35553 +
35554 +       /* Read HCCHAR */
35555 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35556 +
35557 +       /* Clear HCINT */
35558 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35559 +
35560 +       /* Clear HAINT */
35561 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35562 +
35563 +       /* Clear GINTSTS */
35564 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35565 +
35566 +       /* Read GINTSTS */
35567 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35568 +
35569 +       /*
35570 +        * Send Setup packet (Get Device Descriptor)
35571 +        */
35572 +
35573 +       /* Make sure channel is disabled */
35574 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35575 +       if (hcchar.b.chen) {
35576 +               hcchar.b.chdis = 1;
35577 +//              hcchar.b.chen = 1;
35578 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35579 +               //sleep(1);
35580 +               dwc_mdelay(1000);
35581 +
35582 +               /* Read GINTSTS */
35583 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35584 +
35585 +               /* Read HAINT */
35586 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35587 +
35588 +               /* Read HCINT */
35589 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35590 +
35591 +               /* Read HCCHAR */
35592 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35593 +
35594 +               /* Clear HCINT */
35595 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35596 +
35597 +               /* Clear HAINT */
35598 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35599 +
35600 +               /* Clear GINTSTS */
35601 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35602 +
35603 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35604 +       }
35605 +
35606 +       /* Set HCTSIZ */
35607 +       hctsiz.d32 = 0;
35608 +       hctsiz.b.xfersize = 8;
35609 +       hctsiz.b.pktcnt = 1;
35610 +       hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
35611 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35612 +
35613 +       /* Set HCCHAR */
35614 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35615 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35616 +       hcchar.b.epdir = 0;
35617 +       hcchar.b.epnum = 0;
35618 +       hcchar.b.mps = 8;
35619 +       hcchar.b.chen = 1;
35620 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35621 +
35622 +       /* Fill FIFO with Setup data for Get Device Descriptor */
35623 +       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35624 +       DWC_WRITE_REG32(data_fifo++, 0x01000680);
35625 +       DWC_WRITE_REG32(data_fifo++, 0x00080000);
35626 +
35627 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35628 +
35629 +       /* Wait for host channel interrupt */
35630 +       do {
35631 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35632 +       } while (gintsts.b.hcintr == 0);
35633 +
35634 +       /* Disable HCINTs */
35635 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35636 +
35637 +       /* Disable HAINTs */
35638 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35639 +
35640 +       /* Read HAINT */
35641 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35642 +
35643 +       /* Read HCINT */
35644 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35645 +
35646 +       /* Read HCCHAR */
35647 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35648 +
35649 +       /* Clear HCINT */
35650 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35651 +
35652 +       /* Clear HAINT */
35653 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35654 +
35655 +       /* Clear GINTSTS */
35656 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35657 +
35658 +       /* Read GINTSTS */
35659 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35660 +}
35661 +
35662 +static void do_in_ack(void)
35663 +{
35664 +       gintsts_data_t gintsts;
35665 +       hctsiz_data_t hctsiz;
35666 +       hcchar_data_t hcchar;
35667 +       haint_data_t haint;
35668 +       hcint_data_t hcint;
35669 +       host_grxsts_data_t grxsts;
35670 +
35671 +       /* Enable HAINTs */
35672 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
35673 +
35674 +       /* Enable HCINTs */
35675 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
35676 +
35677 +       /* Read GINTSTS */
35678 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35679 +
35680 +       /* Read HAINT */
35681 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35682 +
35683 +       /* Read HCINT */
35684 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35685 +
35686 +       /* Read HCCHAR */
35687 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35688 +
35689 +       /* Clear HCINT */
35690 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35691 +
35692 +       /* Clear HAINT */
35693 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35694 +
35695 +       /* Clear GINTSTS */
35696 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35697 +
35698 +       /* Read GINTSTS */
35699 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35700 +
35701 +       /*
35702 +        * Receive Control In packet
35703 +        */
35704 +
35705 +       /* Make sure channel is disabled */
35706 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35707 +       if (hcchar.b.chen) {
35708 +               hcchar.b.chdis = 1;
35709 +               hcchar.b.chen = 1;
35710 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35711 +               //sleep(1);
35712 +               dwc_mdelay(1000);
35713 +
35714 +               /* Read GINTSTS */
35715 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35716 +
35717 +               /* Read HAINT */
35718 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35719 +
35720 +               /* Read HCINT */
35721 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35722 +
35723 +               /* Read HCCHAR */
35724 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35725 +
35726 +               /* Clear HCINT */
35727 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35728 +
35729 +               /* Clear HAINT */
35730 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35731 +
35732 +               /* Clear GINTSTS */
35733 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35734 +
35735 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35736 +       }
35737 +
35738 +       /* Set HCTSIZ */
35739 +       hctsiz.d32 = 0;
35740 +       hctsiz.b.xfersize = 8;
35741 +       hctsiz.b.pktcnt = 1;
35742 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35743 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35744 +
35745 +       /* Set HCCHAR */
35746 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35747 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35748 +       hcchar.b.epdir = 1;
35749 +       hcchar.b.epnum = 0;
35750 +       hcchar.b.mps = 8;
35751 +       hcchar.b.chen = 1;
35752 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35753 +
35754 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35755 +
35756 +       /* Wait for receive status queue interrupt */
35757 +       do {
35758 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35759 +       } while (gintsts.b.rxstsqlvl == 0);
35760 +
35761 +       /* Read RXSTS */
35762 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35763 +
35764 +       /* Clear RXSTSQLVL in GINTSTS */
35765 +       gintsts.d32 = 0;
35766 +       gintsts.b.rxstsqlvl = 1;
35767 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35768 +
35769 +       switch (grxsts.b.pktsts) {
35770 +       case DWC_GRXSTS_PKTSTS_IN:
35771 +               /* Read the data into the host buffer */
35772 +               if (grxsts.b.bcnt > 0) {
35773 +                       int i;
35774 +                       int word_count = (grxsts.b.bcnt + 3) / 4;
35775 +
35776 +                       data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
35777 +
35778 +                       for (i = 0; i < word_count; i++) {
35779 +                               (void)DWC_READ_REG32(data_fifo++);
35780 +                       }
35781 +               }
35782 +               break;
35783 +
35784 +       default:
35785 +               break;
35786 +       }
35787 +
35788 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35789 +
35790 +       /* Wait for receive status queue interrupt */
35791 +       do {
35792 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35793 +       } while (gintsts.b.rxstsqlvl == 0);
35794 +
35795 +       /* Read RXSTS */
35796 +       grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
35797 +
35798 +       /* Clear RXSTSQLVL in GINTSTS */
35799 +       gintsts.d32 = 0;
35800 +       gintsts.b.rxstsqlvl = 1;
35801 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35802 +
35803 +       switch (grxsts.b.pktsts) {
35804 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
35805 +               break;
35806 +
35807 +       default:
35808 +               break;
35809 +       }
35810 +
35811 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35812 +
35813 +       /* Wait for host channel interrupt */
35814 +       do {
35815 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35816 +       } while (gintsts.b.hcintr == 0);
35817 +
35818 +       /* Read HAINT */
35819 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35820 +
35821 +       /* Read HCINT */
35822 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35823 +
35824 +       /* Read HCCHAR */
35825 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35826 +
35827 +       /* Clear HCINT */
35828 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35829 +
35830 +       /* Clear HAINT */
35831 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35832 +
35833 +       /* Clear GINTSTS */
35834 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35835 +
35836 +       /* Read GINTSTS */
35837 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35838 +
35839 +//      usleep(100000);
35840 +//      mdelay(100);
35841 +       dwc_mdelay(1);
35842 +
35843 +       /*
35844 +        * Send handshake packet
35845 +        */
35846 +
35847 +       /* Read HAINT */
35848 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35849 +
35850 +       /* Read HCINT */
35851 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35852 +
35853 +       /* Read HCCHAR */
35854 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35855 +
35856 +       /* Clear HCINT */
35857 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35858 +
35859 +       /* Clear HAINT */
35860 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35861 +
35862 +       /* Clear GINTSTS */
35863 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35864 +
35865 +       /* Read GINTSTS */
35866 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35867 +
35868 +       /* Make sure channel is disabled */
35869 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35870 +       if (hcchar.b.chen) {
35871 +               hcchar.b.chdis = 1;
35872 +               hcchar.b.chen = 1;
35873 +               DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35874 +               //sleep(1);
35875 +               dwc_mdelay(1000);
35876 +
35877 +               /* Read GINTSTS */
35878 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35879 +
35880 +               /* Read HAINT */
35881 +               haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35882 +
35883 +               /* Read HCINT */
35884 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35885 +
35886 +               /* Read HCCHAR */
35887 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35888 +
35889 +               /* Clear HCINT */
35890 +               DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35891 +
35892 +               /* Clear HAINT */
35893 +               DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35894 +
35895 +               /* Clear GINTSTS */
35896 +               DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35897 +
35898 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35899 +       }
35900 +
35901 +       /* Set HCTSIZ */
35902 +       hctsiz.d32 = 0;
35903 +       hctsiz.b.xfersize = 0;
35904 +       hctsiz.b.pktcnt = 1;
35905 +       hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
35906 +       DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
35907 +
35908 +       /* Set HCCHAR */
35909 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35910 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
35911 +       hcchar.b.epdir = 0;
35912 +       hcchar.b.epnum = 0;
35913 +       hcchar.b.mps = 8;
35914 +       hcchar.b.chen = 1;
35915 +       DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
35916 +
35917 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35918 +
35919 +       /* Wait for host channel interrupt */
35920 +       do {
35921 +               gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35922 +       } while (gintsts.b.hcintr == 0);
35923 +
35924 +       /* Disable HCINTs */
35925 +       DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
35926 +
35927 +       /* Disable HAINTs */
35928 +       DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
35929 +
35930 +       /* Read HAINT */
35931 +       haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
35932 +
35933 +       /* Read HCINT */
35934 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
35935 +
35936 +       /* Read HCCHAR */
35937 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
35938 +
35939 +       /* Clear HCINT */
35940 +       DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
35941 +
35942 +       /* Clear HAINT */
35943 +       DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
35944 +
35945 +       /* Clear GINTSTS */
35946 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
35947 +
35948 +       /* Read GINTSTS */
35949 +       gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
35950 +}
35951 +#endif
35952 +
35953 +/** Handles hub class-specific requests. */
35954 +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
35955 +                           uint16_t typeReq,
35956 +                           uint16_t wValue,
35957 +                           uint16_t wIndex, uint8_t * buf, uint16_t wLength)
35958 +{
35959 +       int retval = 0;
35960 +
35961 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
35962 +       usb_hub_descriptor_t *hub_desc;
35963 +       hprt0_data_t hprt0 = {.d32 = 0 };
35964 +
35965 +       uint32_t port_status;
35966 +
35967 +       switch (typeReq) {
35968 +       case UCR_CLEAR_HUB_FEATURE:
35969 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
35970 +                           "ClearHubFeature 0x%x\n", wValue);
35971 +               switch (wValue) {
35972 +               case UHF_C_HUB_LOCAL_POWER:
35973 +               case UHF_C_HUB_OVER_CURRENT:
35974 +                       /* Nothing required here */
35975 +                       break;
35976 +               default:
35977 +                       retval = -DWC_E_INVALID;
35978 +                       DWC_ERROR("DWC OTG HCD - "
35979 +                                 "ClearHubFeature request %xh unknown\n",
35980 +                                 wValue);
35981 +               }
35982 +               break;
35983 +       case UCR_CLEAR_PORT_FEATURE:
35984 +#ifdef CONFIG_USB_DWC_OTG_LPM
35985 +               if (wValue != UHF_PORT_L1)
35986 +#endif
35987 +                       if (!wIndex || wIndex > 1)
35988 +                               goto error;
35989 +
35990 +               switch (wValue) {
35991 +               case UHF_PORT_ENABLE:
35992 +                       DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
35993 +                                   "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
35994 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
35995 +                       hprt0.b.prtena = 1;
35996 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
35997 +                       break;
35998 +               case UHF_PORT_SUSPEND:
35999 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36000 +                                   "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
36001 +
36002 +                       if (core_if->power_down == 2) {
36003 +                               dwc_otg_host_hibernation_restore(core_if, 0, 0);
36004 +                       } else {
36005 +                               DWC_WRITE_REG32(core_if->pcgcctl, 0);
36006 +                               dwc_mdelay(5);
36007 +
36008 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36009 +                               hprt0.b.prtres = 1;
36010 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36011 +                               hprt0.b.prtsusp = 0;
36012 +                               /* Clear Resume bit */
36013 +                               dwc_mdelay(100);
36014 +                               hprt0.b.prtres = 0;
36015 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36016 +                       }
36017 +                       break;
36018 +#ifdef CONFIG_USB_DWC_OTG_LPM
36019 +               case UHF_PORT_L1:
36020 +                       {
36021 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36022 +                               glpmcfg_data_t lpmcfg = {.d32 = 0 };
36023 +
36024 +                               lpmcfg.d32 =
36025 +                                   DWC_READ_REG32(&core_if->
36026 +                                                  core_global_regs->glpmcfg);
36027 +                               lpmcfg.b.en_utmi_sleep = 0;
36028 +                               lpmcfg.b.hird_thres &= (~(1 << 4));
36029 +                               lpmcfg.b.prt_sleep_sts = 1;
36030 +                               DWC_WRITE_REG32(&core_if->
36031 +                                               core_global_regs->glpmcfg,
36032 +                                               lpmcfg.d32);
36033 +
36034 +                               /* Clear Enbl_L1Gating bit. */
36035 +                               pcgcctl.b.enbl_sleep_gating = 1;
36036 +                               DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
36037 +                                                0);
36038 +
36039 +                               dwc_mdelay(5);
36040 +
36041 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36042 +                               hprt0.b.prtres = 1;
36043 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36044 +                                               hprt0.d32);
36045 +                               /* This bit will be cleared in wakeup interrupt handle */
36046 +                               break;
36047 +                       }
36048 +#endif
36049 +               case UHF_PORT_POWER:
36050 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36051 +                                   "ClearPortFeature USB_PORT_FEAT_POWER\n");
36052 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36053 +                       hprt0.b.prtpwr = 0;
36054 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36055 +                       break;
36056 +               case UHF_PORT_INDICATOR:
36057 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36058 +                                   "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
36059 +                       /* Port inidicator not supported */
36060 +                       break;
36061 +               case UHF_C_PORT_CONNECTION:
36062 +                       /* Clears drivers internal connect status change
36063 +                        * flag */
36064 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36065 +                                   "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
36066 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 0;
36067 +                       break;
36068 +               case UHF_C_PORT_RESET:
36069 +                       /* Clears the driver's internal Port Reset Change
36070 +                        * flag */
36071 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36072 +                                   "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
36073 +                       dwc_otg_hcd->flags.b.port_reset_change = 0;
36074 +                       break;
36075 +               case UHF_C_PORT_ENABLE:
36076 +                       /* Clears the driver's internal Port
36077 +                        * Enable/Disable Change flag */
36078 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36079 +                                   "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
36080 +                       dwc_otg_hcd->flags.b.port_enable_change = 0;
36081 +                       break;
36082 +               case UHF_C_PORT_SUSPEND:
36083 +                       /* Clears the driver's internal Port Suspend
36084 +                        * Change flag, which is set when resume signaling on
36085 +                        * the host port is complete */
36086 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36087 +                                   "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
36088 +                       dwc_otg_hcd->flags.b.port_suspend_change = 0;
36089 +                       break;
36090 +#ifdef CONFIG_USB_DWC_OTG_LPM
36091 +               case UHF_C_PORT_L1:
36092 +                       dwc_otg_hcd->flags.b.port_l1_change = 0;
36093 +                       break;
36094 +#endif
36095 +               case UHF_C_PORT_OVER_CURRENT:
36096 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36097 +                                   "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
36098 +                       dwc_otg_hcd->flags.b.port_over_current_change = 0;
36099 +                       break;
36100 +               default:
36101 +                       retval = -DWC_E_INVALID;
36102 +                       DWC_ERROR("DWC OTG HCD - "
36103 +                                 "ClearPortFeature request %xh "
36104 +                                 "unknown or unsupported\n", wValue);
36105 +               }
36106 +               break;
36107 +       case UCR_GET_HUB_DESCRIPTOR:
36108 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36109 +                           "GetHubDescriptor\n");
36110 +               hub_desc = (usb_hub_descriptor_t *) buf;
36111 +               hub_desc->bDescLength = 9;
36112 +               hub_desc->bDescriptorType = 0x29;
36113 +               hub_desc->bNbrPorts = 1;
36114 +               USETW(hub_desc->wHubCharacteristics, 0x08);
36115 +               hub_desc->bPwrOn2PwrGood = 1;
36116 +               hub_desc->bHubContrCurrent = 0;
36117 +               hub_desc->DeviceRemovable[0] = 0;
36118 +               hub_desc->DeviceRemovable[1] = 0xff;
36119 +               break;
36120 +       case UCR_GET_HUB_STATUS:
36121 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36122 +                           "GetHubStatus\n");
36123 +               DWC_MEMSET(buf, 0, 4);
36124 +               break;
36125 +       case UCR_GET_PORT_STATUS:
36126 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36127 +                           "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
36128 +                           wIndex, dwc_otg_hcd->flags.d32);
36129 +               if (!wIndex || wIndex > 1)
36130 +                       goto error;
36131 +
36132 +               port_status = 0;
36133 +
36134 +               if (dwc_otg_hcd->flags.b.port_connect_status_change)
36135 +                       port_status |= (1 << UHF_C_PORT_CONNECTION);
36136 +
36137 +               if (dwc_otg_hcd->flags.b.port_enable_change)
36138 +                       port_status |= (1 << UHF_C_PORT_ENABLE);
36139 +
36140 +               if (dwc_otg_hcd->flags.b.port_suspend_change)
36141 +                       port_status |= (1 << UHF_C_PORT_SUSPEND);
36142 +
36143 +               if (dwc_otg_hcd->flags.b.port_l1_change)
36144 +                       port_status |= (1 << UHF_C_PORT_L1);
36145 +
36146 +               if (dwc_otg_hcd->flags.b.port_reset_change) {
36147 +                       port_status |= (1 << UHF_C_PORT_RESET);
36148 +               }
36149 +
36150 +               if (dwc_otg_hcd->flags.b.port_over_current_change) {
36151 +                       DWC_WARN("Overcurrent change detected\n");
36152 +                       port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
36153 +               }
36154 +
36155 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36156 +                       /*
36157 +                        * The port is disconnected, which means the core is
36158 +                        * either in device mode or it soon will be. Just
36159 +                        * return 0's for the remainder of the port status
36160 +                        * since the port register can't be read if the core
36161 +                        * is in device mode.
36162 +                        */
36163 +                       *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36164 +                       break;
36165 +               }
36166 +
36167 +               hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
36168 +               DWC_DEBUGPL(DBG_HCDV, "  HPRT0: 0x%08x\n", hprt0.d32);
36169 +
36170 +               if (hprt0.b.prtconnsts)
36171 +                       port_status |= (1 << UHF_PORT_CONNECTION);
36172 +
36173 +               if (hprt0.b.prtena)
36174 +                       port_status |= (1 << UHF_PORT_ENABLE);
36175 +
36176 +               if (hprt0.b.prtsusp)
36177 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36178 +
36179 +               if (hprt0.b.prtovrcurract)
36180 +                       port_status |= (1 << UHF_PORT_OVER_CURRENT);
36181 +
36182 +               if (hprt0.b.prtrst)
36183 +                       port_status |= (1 << UHF_PORT_RESET);
36184 +
36185 +               if (hprt0.b.prtpwr)
36186 +                       port_status |= (1 << UHF_PORT_POWER);
36187 +
36188 +               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
36189 +                       port_status |= (1 << UHF_PORT_HIGH_SPEED);
36190 +               else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
36191 +                       port_status |= (1 << UHF_PORT_LOW_SPEED);
36192 +
36193 +               if (hprt0.b.prttstctl)
36194 +                       port_status |= (1 << UHF_PORT_TEST);
36195 +               if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
36196 +                       port_status |= (1 << UHF_PORT_L1);
36197 +               }
36198 +               /*
36199 +                  For Synopsys HW emulation of Power down wkup_control asserts the
36200 +                  hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
36201 +                  We intentionally tell the software that port is in L2Suspend state.
36202 +                  Only for STE.
36203 +               */
36204 +               if ((core_if->power_down == 2)
36205 +                   && (core_if->hibernation_suspend == 1)) {
36206 +                       port_status |= (1 << UHF_PORT_SUSPEND);
36207 +               }
36208 +               /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
36209 +
36210 +               *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
36211 +
36212 +               break;
36213 +       case UCR_SET_HUB_FEATURE:
36214 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36215 +                           "SetHubFeature\n");
36216 +               /* No HUB features supported */
36217 +               break;
36218 +       case UCR_SET_PORT_FEATURE:
36219 +               if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
36220 +                       goto error;
36221 +
36222 +               if (!dwc_otg_hcd->flags.b.port_connect_status) {
36223 +                       /*
36224 +                        * The port is disconnected, which means the core is
36225 +                        * either in device mode or it soon will be. Just
36226 +                        * return without doing anything since the port
36227 +                        * register can't be written if the core is in device
36228 +                        * mode.
36229 +                        */
36230 +                       break;
36231 +               }
36232 +
36233 +               switch (wValue) {
36234 +               case UHF_PORT_SUSPEND:
36235 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36236 +                                   "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
36237 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
36238 +                               goto error;
36239 +                       }
36240 +                       if (core_if->power_down == 2) {
36241 +                               int timeout = 300;
36242 +                               dwc_irqflags_t flags;
36243 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36244 +                               gpwrdn_data_t gpwrdn = {.d32 = 0 };
36245 +                               gusbcfg_data_t gusbcfg = {.d32 = 0 };
36246 +#ifdef DWC_DEV_SRPCAP
36247 +                               int32_t otg_cap_param = core_if->core_params->otg_cap;
36248 +#endif
36249 +                               DWC_PRINTF("Preparing for complete power-off\n");
36250 +
36251 +                               /* Save registers before hibernation */
36252 +                               dwc_otg_save_global_regs(core_if);
36253 +                               dwc_otg_save_host_regs(core_if);
36254 +
36255 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36256 +                               hprt0.b.prtsusp = 1;
36257 +                               hprt0.b.prtena = 0;
36258 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36259 +                               /* Spin hprt0.b.prtsusp to became 1 */
36260 +                               do {
36261 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36262 +                                       if (hprt0.b.prtsusp) {
36263 +                                               break;
36264 +                                       }
36265 +                                       dwc_mdelay(1);
36266 +                               } while (--timeout);
36267 +                               if (!timeout) {
36268 +                                       DWC_WARN("Suspend wasn't genereted\n");
36269 +                               }
36270 +                               dwc_udelay(10);
36271 +
36272 +                               /*
36273 +                                * We need to disable interrupts to prevent servicing of any IRQ
36274 +                                * during going to hibernation
36275 +                                */
36276 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36277 +                               core_if->lx_state = DWC_OTG_L2;
36278 +#ifdef DWC_DEV_SRPCAP
36279 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36280 +                               hprt0.b.prtpwr = 0;
36281 +                               hprt0.b.prtena = 0;
36282 +                               DWC_WRITE_REG32(core_if->host_if->hprt0,
36283 +                                               hprt0.d32);
36284 +#endif
36285 +                               gusbcfg.d32 =
36286 +                                   DWC_READ_REG32(&core_if->core_global_regs->
36287 +                                                  gusbcfg);
36288 +                               if (gusbcfg.b.ulpi_utmi_sel == 1) {
36289 +                                       /* ULPI interface */
36290 +                                       /* Suspend the Phy Clock */
36291 +                                       pcgcctl.d32 = 0;
36292 +                                       pcgcctl.b.stoppclk = 1;
36293 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36294 +                                                        pcgcctl.d32);
36295 +                                       dwc_udelay(10);
36296 +                                       gpwrdn.b.pmuactv = 1;
36297 +                                       DWC_MODIFY_REG32(&core_if->
36298 +                                                        core_global_regs->
36299 +                                                        gpwrdn, 0, gpwrdn.d32);
36300 +                               } else {
36301 +                                       /* UTMI+ Interface */
36302 +                                       gpwrdn.b.pmuactv = 1;
36303 +                                       DWC_MODIFY_REG32(&core_if->
36304 +                                                        core_global_regs->
36305 +                                                        gpwrdn, 0, gpwrdn.d32);
36306 +                                       dwc_udelay(10);
36307 +                                       pcgcctl.b.stoppclk = 1;
36308 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
36309 +                                       dwc_udelay(10);
36310 +                               }
36311 +#ifdef DWC_DEV_SRPCAP
36312 +                               gpwrdn.d32 = 0;
36313 +                               gpwrdn.b.dis_vbus = 1;
36314 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36315 +                                                gpwrdn, 0, gpwrdn.d32);
36316 +#endif
36317 +                               gpwrdn.d32 = 0;
36318 +                               gpwrdn.b.pmuintsel = 1;
36319 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36320 +                                                gpwrdn, 0, gpwrdn.d32);
36321 +                               dwc_udelay(10);
36322 +
36323 +                               gpwrdn.d32 = 0;
36324 +#ifdef DWC_DEV_SRPCAP
36325 +                               gpwrdn.b.srp_det_msk = 1;
36326 +#endif
36327 +                               gpwrdn.b.disconn_det_msk = 1;
36328 +                               gpwrdn.b.lnstchng_msk = 1;
36329 +                               gpwrdn.b.sts_chngint_msk = 1;
36330 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36331 +                                                gpwrdn, 0, gpwrdn.d32);
36332 +                               dwc_udelay(10);
36333 +
36334 +                               /* Enable Power Down Clamp and all interrupts in GPWRDN */
36335 +                               gpwrdn.d32 = 0;
36336 +                               gpwrdn.b.pwrdnclmp = 1;
36337 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36338 +                                                gpwrdn, 0, gpwrdn.d32);
36339 +                               dwc_udelay(10);
36340 +
36341 +                               /* Switch off VDD */
36342 +                               gpwrdn.d32 = 0;
36343 +                               gpwrdn.b.pwrdnswtch = 1;
36344 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36345 +                                                gpwrdn, 0, gpwrdn.d32);
36346 +
36347 +#ifdef DWC_DEV_SRPCAP
36348 +                               if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
36349 +                               {
36350 +                                       core_if->pwron_timer_started = 1;
36351 +                                       DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
36352 +                               }
36353 +#endif
36354 +                               /* Save gpwrdn register for further usage if stschng interrupt */
36355 +                               core_if->gr_backup->gpwrdn_local =
36356 +                                               DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
36357 +
36358 +                               /* Set flag to indicate that we are in hibernation */
36359 +                               core_if->hibernation_suspend = 1;
36360 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
36361 +
36362 +                               DWC_PRINTF("Host hibernation completed\n");
36363 +                               // Exit from case statement
36364 +                               break;
36365 +
36366 +                       }
36367 +                       if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
36368 +                           dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36369 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36370 +                               gotgctl.b.hstsethnpen = 1;
36371 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36372 +                                                gotgctl, 0, gotgctl.d32);
36373 +                               core_if->op_state = A_SUSPEND;
36374 +                       }
36375 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36376 +                       hprt0.b.prtsusp = 1;
36377 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36378 +                       {
36379 +                               dwc_irqflags_t flags;
36380 +                               /* Update lx_state */
36381 +                               DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
36382 +                               core_if->lx_state = DWC_OTG_L2;
36383 +                               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
36384 +                       }
36385 +                       /* Suspend the Phy Clock */
36386 +                       {
36387 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36388 +                               pcgcctl.b.stoppclk = 1;
36389 +                               DWC_MODIFY_REG32(core_if->pcgcctl, 0,
36390 +                                                pcgcctl.d32);
36391 +                               dwc_udelay(10);
36392 +                       }
36393 +
36394 +                       /* For HNP the bus must be suspended for at least 200ms. */
36395 +                       if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
36396 +                               pcgcctl_data_t pcgcctl = {.d32 = 0 };
36397 +                               pcgcctl.b.stoppclk = 1;
36398 +                DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36399 +                               dwc_mdelay(200);
36400 +                       }
36401 +
36402 +                       /** @todo - check how sw can wait for 1 sec to check asesvld??? */
36403 +#if 0 //vahrama !!!!!!!!!!!!!!!!!!
36404 +                       if (core_if->adp_enable) {
36405 +                               gotgctl_data_t gotgctl = {.d32 = 0 };
36406 +                               gpwrdn_data_t gpwrdn;
36407 +
36408 +                               while (gotgctl.b.asesvld == 1) {
36409 +                                       gotgctl.d32 =
36410 +                                           DWC_READ_REG32(&core_if->
36411 +                                                          core_global_regs->
36412 +                                                          gotgctl);
36413 +                                       dwc_mdelay(100);
36414 +                               }
36415 +
36416 +                               /* Enable Power Down Logic */
36417 +                               gpwrdn.d32 = 0;
36418 +                               gpwrdn.b.pmuactv = 1;
36419 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36420 +                                                gpwrdn, 0, gpwrdn.d32);
36421 +
36422 +                               /* Unmask SRP detected interrupt from Power Down Logic */
36423 +                               gpwrdn.d32 = 0;
36424 +                               gpwrdn.b.srp_det_msk = 1;
36425 +                               DWC_MODIFY_REG32(&core_if->core_global_regs->
36426 +                                                gpwrdn, 0, gpwrdn.d32);
36427 +
36428 +                               dwc_otg_adp_probe_start(core_if);
36429 +                       }
36430 +#endif
36431 +                       break;
36432 +               case UHF_PORT_POWER:
36433 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36434 +                                   "SetPortFeature - USB_PORT_FEAT_POWER\n");
36435 +                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36436 +                       hprt0.b.prtpwr = 1;
36437 +                       DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36438 +                       break;
36439 +               case UHF_PORT_RESET:
36440 +                       if ((core_if->power_down == 2)
36441 +                           && (core_if->hibernation_suspend == 1)) {
36442 +                               /* If we are going to exit from Hibernated
36443 +                                * state via USB RESET.
36444 +                                */
36445 +                               dwc_otg_host_hibernation_restore(core_if, 0, 1);
36446 +                       } else {
36447 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36448 +
36449 +                               DWC_DEBUGPL(DBG_HCD,
36450 +                                           "DWC OTG HCD HUB CONTROL - "
36451 +                                           "SetPortFeature - USB_PORT_FEAT_RESET\n");
36452 +                               {
36453 +                                       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36454 +                                       pcgcctl.b.enbl_sleep_gating = 1;
36455 +                                       pcgcctl.b.stoppclk = 1;
36456 +                                       DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
36457 +                                       DWC_WRITE_REG32(core_if->pcgcctl, 0);
36458 +                               }
36459 +#ifdef CONFIG_USB_DWC_OTG_LPM
36460 +                               {
36461 +                                       glpmcfg_data_t lpmcfg;
36462 +                                       lpmcfg.d32 =
36463 +                                               DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36464 +                                       if (lpmcfg.b.prt_sleep_sts) {
36465 +                                               lpmcfg.b.en_utmi_sleep = 0;
36466 +                                               lpmcfg.b.hird_thres &= (~(1 << 4));
36467 +                                               DWC_WRITE_REG32
36468 +                                                   (&core_if->core_global_regs->glpmcfg,
36469 +                                                    lpmcfg.d32);
36470 +                                               dwc_mdelay(1);
36471 +                                       }
36472 +                               }
36473 +#endif
36474 +                               hprt0.d32 = dwc_otg_read_hprt0(core_if);
36475 +                               /* Clear suspend bit if resetting from suspended state. */
36476 +                               hprt0.b.prtsusp = 0;
36477 +                               /* When B-Host the Port reset bit is set in
36478 +                                * the Start HCD Callback function, so that
36479 +                                * the reset is started within 1ms of the HNP
36480 +                                * success interrupt. */
36481 +                               if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
36482 +                                       hprt0.b.prtpwr = 1;
36483 +                                       hprt0.b.prtrst = 1;
36484 +                                       DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
36485 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36486 +                                                       hprt0.d32);
36487 +                               }
36488 +                               /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
36489 +                               dwc_mdelay(60);
36490 +                               hprt0.b.prtrst = 0;
36491 +                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36492 +                               core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
36493 +                       }
36494 +                       break;
36495 +#ifdef DWC_HS_ELECT_TST
36496 +               case UHF_PORT_TEST:
36497 +                       {
36498 +                               uint32_t t;
36499 +                               gintmsk_data_t gintmsk;
36500 +
36501 +                               t = (wIndex >> 8);      /* MSB wIndex USB */
36502 +                               DWC_DEBUGPL(DBG_HCD,
36503 +                                           "DWC OTG HCD HUB CONTROL - "
36504 +                                           "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
36505 +                                           t);
36506 +                               DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
36507 +                               if (t < 6) {
36508 +                                       hprt0.d32 = dwc_otg_read_hprt0(core_if);
36509 +                                       hprt0.b.prttstctl = t;
36510 +                                       DWC_WRITE_REG32(core_if->host_if->hprt0,
36511 +                                                       hprt0.d32);
36512 +                               } else {
36513 +                                       /* Setup global vars with reg addresses (quick and
36514 +                                        * dirty hack, should be cleaned up)
36515 +                                        */
36516 +                                       global_regs = core_if->core_global_regs;
36517 +                                       hc_global_regs =
36518 +                                           core_if->host_if->host_global_regs;
36519 +                                       hc_regs =
36520 +                                           (dwc_otg_hc_regs_t *) ((char *)
36521 +                                                                  global_regs +
36522 +                                                                  0x500);
36523 +                                       data_fifo =
36524 +                                           (uint32_t *) ((char *)global_regs +
36525 +                                                         0x1000);
36526 +
36527 +                                       if (t == 6) {   /* HS_HOST_PORT_SUSPEND_RESUME */
36528 +                                               /* Save current interrupt mask */
36529 +                                               gintmsk.d32 =
36530 +                                                   DWC_READ_REG32
36531 +                                                   (&global_regs->gintmsk);
36532 +
36533 +                                               /* Disable all interrupts while we muck with
36534 +                                                * the hardware directly
36535 +                                                */
36536 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36537 +
36538 +                                               /* 15 second delay per the test spec */
36539 +                                               dwc_mdelay(15000);
36540 +
36541 +                                               /* Drive suspend on the root port */
36542 +                                               hprt0.d32 =
36543 +                                                   dwc_otg_read_hprt0(core_if);
36544 +                                               hprt0.b.prtsusp = 1;
36545 +                                               hprt0.b.prtres = 0;
36546 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36547 +
36548 +                                               /* 15 second delay per the test spec */
36549 +                                               dwc_mdelay(15000);
36550 +
36551 +                                               /* Drive resume on the root port */
36552 +                                               hprt0.d32 =
36553 +                                                   dwc_otg_read_hprt0(core_if);
36554 +                                               hprt0.b.prtsusp = 0;
36555 +                                               hprt0.b.prtres = 1;
36556 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36557 +                                               dwc_mdelay(100);
36558 +
36559 +                                               /* Clear the resume bit */
36560 +                                               hprt0.b.prtres = 0;
36561 +                                               DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
36562 +
36563 +                                               /* Restore interrupts */
36564 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36565 +                                       } else if (t == 7) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
36566 +                                               /* Save current interrupt mask */
36567 +                                               gintmsk.d32 =
36568 +                                                   DWC_READ_REG32
36569 +                                                   (&global_regs->gintmsk);
36570 +
36571 +                                               /* Disable all interrupts while we muck with
36572 +                                                * the hardware directly
36573 +                                                */
36574 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36575 +
36576 +                                               /* 15 second delay per the test spec */
36577 +                                               dwc_mdelay(15000);
36578 +
36579 +                                               /* Send the Setup packet */
36580 +                                               do_setup();
36581 +
36582 +                                               /* 15 second delay so nothing else happens for awhile */
36583 +                                               dwc_mdelay(15000);
36584 +
36585 +                                               /* Restore interrupts */
36586 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36587 +                                       } else if (t == 8) {    /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
36588 +                                               /* Save current interrupt mask */
36589 +                                               gintmsk.d32 =
36590 +                                                   DWC_READ_REG32
36591 +                                                   (&global_regs->gintmsk);
36592 +
36593 +                                               /* Disable all interrupts while we muck with
36594 +                                                * the hardware directly
36595 +                                                */
36596 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, 0);
36597 +
36598 +                                               /* Send the Setup packet */
36599 +                                               do_setup();
36600 +
36601 +                                               /* 15 second delay so nothing else happens for awhile */
36602 +                                               dwc_mdelay(15000);
36603 +
36604 +                                               /* Send the In and Ack packets */
36605 +                                               do_in_ack();
36606 +
36607 +                                               /* 15 second delay so nothing else happens for awhile */
36608 +                                               dwc_mdelay(15000);
36609 +
36610 +                                               /* Restore interrupts */
36611 +                                               DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
36612 +                                       }
36613 +                               }
36614 +                               break;
36615 +                       }
36616 +#endif /* DWC_HS_ELECT_TST */
36617 +
36618 +               case UHF_PORT_INDICATOR:
36619 +                       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
36620 +                                   "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
36621 +                       /* Not supported */
36622 +                       break;
36623 +               default:
36624 +                       retval = -DWC_E_INVALID;
36625 +                       DWC_ERROR("DWC OTG HCD - "
36626 +                                 "SetPortFeature request %xh "
36627 +                                 "unknown or unsupported\n", wValue);
36628 +                       break;
36629 +               }
36630 +               break;
36631 +#ifdef CONFIG_USB_DWC_OTG_LPM
36632 +       case UCR_SET_AND_TEST_PORT_FEATURE:
36633 +               if (wValue != UHF_PORT_L1) {
36634 +                       goto error;
36635 +               }
36636 +               {
36637 +                       int portnum, hird, devaddr, remwake;
36638 +                       glpmcfg_data_t lpmcfg;
36639 +                       uint32_t time_usecs;
36640 +                       gintsts_data_t gintsts;
36641 +                       gintmsk_data_t gintmsk;
36642 +
36643 +                       if (!dwc_otg_get_param_lpm_enable(core_if)) {
36644 +                               goto error;
36645 +                       }
36646 +                       if (wValue != UHF_PORT_L1 || wLength != 1) {
36647 +                               goto error;
36648 +                       }
36649 +                       /* Check if the port currently is in SLEEP state */
36650 +                       lpmcfg.d32 =
36651 +                           DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36652 +                       if (lpmcfg.b.prt_sleep_sts) {
36653 +                               DWC_INFO("Port is already in sleep mode\n");
36654 +                               buf[0] = 0;     /* Return success */
36655 +                               break;
36656 +                       }
36657 +
36658 +                       portnum = wIndex & 0xf;
36659 +                       hird = (wIndex >> 4) & 0xf;
36660 +                       devaddr = (wIndex >> 8) & 0x7f;
36661 +                       remwake = (wIndex >> 15);
36662 +
36663 +                       if (portnum != 1) {
36664 +                               retval = -DWC_E_INVALID;
36665 +                               DWC_WARN
36666 +                                   ("Wrong port number(%d) in SetandTestPortFeature request\n",
36667 +                                    portnum);
36668 +                               break;
36669 +                       }
36670 +
36671 +                       DWC_PRINTF
36672 +                           ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
36673 +                            portnum, hird, devaddr, remwake);
36674 +                       /* Disable LPM interrupt */
36675 +                       gintmsk.d32 = 0;
36676 +                       gintmsk.b.lpmtranrcvd = 1;
36677 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
36678 +                                        gintmsk.d32, 0);
36679 +
36680 +                       if (dwc_otg_hcd_send_lpm
36681 +                           (dwc_otg_hcd, devaddr, hird, remwake)) {
36682 +                               retval = -DWC_E_INVALID;
36683 +                               break;
36684 +                       }
36685 +
36686 +                       time_usecs = 10 * (lpmcfg.b.retry_count + 1);
36687 +                       /* We will consider timeout if time_usecs microseconds pass,
36688 +                        * and we don't receive LPM transaction status.
36689 +                        * After receiving non-error responce(ACK/NYET/STALL) from device,
36690 +                        *  core will set lpmtranrcvd bit.
36691 +                        */
36692 +                       do {
36693 +                               gintsts.d32 =
36694 +                                   DWC_READ_REG32(&core_if->core_global_regs->gintsts);
36695 +                               if (gintsts.b.lpmtranrcvd) {
36696 +                                       break;
36697 +                               }
36698 +                               dwc_udelay(1);
36699 +                       } while (--time_usecs);
36700 +                       /* lpm_int bit will be cleared in LPM interrupt handler */
36701 +
36702 +                       /* Now fill status
36703 +                        * 0x00 - Success
36704 +                        * 0x10 - NYET
36705 +                        * 0x11 - Timeout
36706 +                        */
36707 +                       if (!gintsts.b.lpmtranrcvd) {
36708 +                               buf[0] = 0x3;   /* Completion code is Timeout */
36709 +                               dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
36710 +                       } else {
36711 +                               lpmcfg.d32 =
36712 +                                   DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
36713 +                               if (lpmcfg.b.lpm_resp == 0x3) {
36714 +                                       /* ACK responce from the device */
36715 +                                       buf[0] = 0x00;  /* Success */
36716 +                               } else if (lpmcfg.b.lpm_resp == 0x2) {
36717 +                                       /* NYET responce from the device */
36718 +                                       buf[0] = 0x2;
36719 +                               } else {
36720 +                                       /* Otherwise responce with Timeout */
36721 +                                       buf[0] = 0x3;
36722 +                               }
36723 +                       }
36724 +                       DWC_PRINTF("Device responce to LPM trans is %x\n",
36725 +                                  lpmcfg.b.lpm_resp);
36726 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
36727 +                                        gintmsk.d32);
36728 +
36729 +                       break;
36730 +               }
36731 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36732 +       default:
36733 +error:
36734 +               retval = -DWC_E_INVALID;
36735 +               DWC_WARN("DWC OTG HCD - "
36736 +                        "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
36737 +                        typeReq, wIndex, wValue);
36738 +               break;
36739 +       }
36740 +
36741 +       return retval;
36742 +}
36743 +
36744 +#ifdef CONFIG_USB_DWC_OTG_LPM
36745 +/** Returns index of host channel to perform LPM transaction. */
36746 +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
36747 +{
36748 +       dwc_otg_core_if_t *core_if = hcd->core_if;
36749 +       dwc_hc_t *hc;
36750 +       hcchar_data_t hcchar;
36751 +       gintmsk_data_t gintmsk = {.d32 = 0 };
36752 +
36753 +       if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
36754 +               DWC_PRINTF("No free channel to select for LPM transaction\n");
36755 +               return -1;
36756 +       }
36757 +
36758 +       hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
36759 +
36760 +       /* Mask host channel interrupts. */
36761 +       gintmsk.b.hcintr = 1;
36762 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
36763 +
36764 +       /* Fill fields that core needs for LPM transaction */
36765 +       hcchar.b.devaddr = devaddr;
36766 +       hcchar.b.epnum = 0;
36767 +       hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
36768 +       hcchar.b.mps = 64;
36769 +       hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
36770 +       hcchar.b.epdir = 0;     /* OUT */
36771 +       DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
36772 +                       hcchar.d32);
36773 +
36774 +       /* Remove the host channel from the free list. */
36775 +       DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
36776 +
36777 +       DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
36778 +
36779 +       return hc->hc_num;
36780 +}
36781 +
36782 +/** Release hc after performing LPM transaction */
36783 +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
36784 +{
36785 +       dwc_hc_t *hc;
36786 +       glpmcfg_data_t lpmcfg;
36787 +       uint8_t hc_num;
36788 +
36789 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36790 +       hc_num = lpmcfg.b.lpm_chan_index;
36791 +
36792 +       hc = hcd->hc_ptr_array[hc_num];
36793 +
36794 +       DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
36795 +       /* Return host channel to free list */
36796 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
36797 +}
36798 +
36799 +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
36800 +                        uint8_t bRemoteWake)
36801 +{
36802 +       glpmcfg_data_t lpmcfg;
36803 +       pcgcctl_data_t pcgcctl = {.d32 = 0 };
36804 +       int channel;
36805 +
36806 +       channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
36807 +       if (channel < 0) {
36808 +               return channel;
36809 +       }
36810 +
36811 +       pcgcctl.b.enbl_sleep_gating = 1;
36812 +       DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
36813 +
36814 +       /* Read LPM config register */
36815 +       lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
36816 +
36817 +       /* Program LPM transaction fields */
36818 +       lpmcfg.b.rem_wkup_en = bRemoteWake;
36819 +       lpmcfg.b.hird = hird;
36820 +       lpmcfg.b.hird_thres = 0x1c;
36821 +       lpmcfg.b.lpm_chan_index = channel;
36822 +       lpmcfg.b.en_utmi_sleep = 1;
36823 +       /* Program LPM config register */
36824 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36825 +
36826 +       /* Send LPM transaction */
36827 +       lpmcfg.b.send_lpm = 1;
36828 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
36829 +
36830 +       return 0;
36831 +}
36832 +
36833 +#endif /* CONFIG_USB_DWC_OTG_LPM */
36834 +
36835 +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
36836 +{
36837 +       int retval;
36838 +
36839 +       if (port != 1) {
36840 +               return -DWC_E_INVALID;
36841 +       }
36842 +
36843 +       retval = (hcd->flags.b.port_connect_status_change ||
36844 +                 hcd->flags.b.port_reset_change ||
36845 +                 hcd->flags.b.port_enable_change ||
36846 +                 hcd->flags.b.port_suspend_change ||
36847 +                 hcd->flags.b.port_over_current_change);
36848 +#ifdef DEBUG
36849 +       if (retval) {
36850 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
36851 +                           " Root port status changed\n");
36852 +               DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",
36853 +                           hcd->flags.b.port_connect_status_change);
36854 +               DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",
36855 +                           hcd->flags.b.port_reset_change);
36856 +               DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",
36857 +                           hcd->flags.b.port_enable_change);
36858 +               DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",
36859 +                           hcd->flags.b.port_suspend_change);
36860 +               DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",
36861 +                           hcd->flags.b.port_over_current_change);
36862 +       }
36863 +#endif
36864 +       return retval;
36865 +}
36866 +
36867 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
36868 +{
36869 +       hfnum_data_t hfnum;
36870 +       hfnum.d32 =
36871 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
36872 +                          hfnum);
36873 +
36874 +#ifdef DEBUG_SOF
36875 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
36876 +                   hfnum.b.frnum);
36877 +#endif
36878 +       return hfnum.b.frnum;
36879 +}
36880 +
36881 +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
36882 +                     struct dwc_otg_hcd_function_ops *fops)
36883 +{
36884 +       int retval = 0;
36885 +
36886 +       hcd->fops = fops;
36887 +       if (!dwc_otg_is_device_mode(hcd->core_if) &&
36888 +               (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
36889 +               dwc_otg_hcd_reinit(hcd);
36890 +       } else {
36891 +               retval = -DWC_E_NO_DEVICE;
36892 +       }
36893 +
36894 +       return retval;
36895 +}
36896 +
36897 +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
36898 +{
36899 +       return hcd->priv;
36900 +}
36901 +
36902 +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
36903 +{
36904 +       hcd->priv = priv_data;
36905 +}
36906 +
36907 +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
36908 +{
36909 +       return hcd->otg_port;
36910 +}
36911 +
36912 +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
36913 +{
36914 +       uint32_t is_b_host;
36915 +       if (hcd->core_if->op_state == B_HOST) {
36916 +               is_b_host = 1;
36917 +       } else {
36918 +               is_b_host = 0;
36919 +       }
36920 +
36921 +       return is_b_host;
36922 +}
36923 +
36924 +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
36925 +                                        int iso_desc_count, int atomic_alloc)
36926 +{
36927 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
36928 +       uint32_t size;
36929 +
36930 +       size =
36931 +           sizeof(*dwc_otg_urb) +
36932 +           iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
36933 +       if (atomic_alloc)
36934 +               dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
36935 +       else
36936 +               dwc_otg_urb = DWC_ALLOC(size);
36937 +
36938 +        if (NULL != dwc_otg_urb)
36939 +                dwc_otg_urb->packet_count = iso_desc_count;
36940 +        else {
36941 +                dwc_otg_urb->packet_count = 0;
36942 +                if (size != 0) {
36943 +                        DWC_ERROR("**** DWC OTG HCD URB alloc - "
36944 +                                  "%salloc of %db failed\n",
36945 +                                  atomic_alloc?"atomic ":"", size);
36946 +                }
36947 +        }
36948 +
36949 +       return dwc_otg_urb;
36950 +}
36951 +
36952 +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
36953 +                                 uint8_t dev_addr, uint8_t ep_num,
36954 +                                 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
36955 +{
36956 +       dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
36957 +                             ep_type, ep_dir, mps);
36958 +#if 0
36959 +       DWC_PRINTF
36960 +           ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
36961 +            dev_addr, ep_num, ep_dir, ep_type, mps);
36962 +#endif
36963 +}
36964 +
36965 +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
36966 +                               void *urb_handle, void *buf, dwc_dma_t dma,
36967 +                               uint32_t buflen, void *setup_packet,
36968 +                               dwc_dma_t setup_dma, uint32_t flags,
36969 +                               uint16_t interval)
36970 +{
36971 +       dwc_otg_urb->priv = urb_handle;
36972 +       dwc_otg_urb->buf = buf;
36973 +       dwc_otg_urb->dma = dma;
36974 +       dwc_otg_urb->length = buflen;
36975 +       dwc_otg_urb->setup_packet = setup_packet;
36976 +       dwc_otg_urb->setup_dma = setup_dma;
36977 +       dwc_otg_urb->flags = flags;
36978 +       dwc_otg_urb->interval = interval;
36979 +       dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
36980 +}
36981 +
36982 +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
36983 +{
36984 +       return dwc_otg_urb->status;
36985 +}
36986 +
36987 +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
36988 +{
36989 +       return dwc_otg_urb->actual_length;
36990 +}
36991 +
36992 +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
36993 +{
36994 +       return dwc_otg_urb->error_count;
36995 +}
36996 +
36997 +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
36998 +                                        int desc_num, uint32_t offset,
36999 +                                        uint32_t length)
37000 +{
37001 +       dwc_otg_urb->iso_descs[desc_num].offset = offset;
37002 +       dwc_otg_urb->iso_descs[desc_num].length = length;
37003 +}
37004 +
37005 +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
37006 +                                            int desc_num)
37007 +{
37008 +       return dwc_otg_urb->iso_descs[desc_num].status;
37009 +}
37010 +
37011 +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
37012 +                                                   dwc_otg_urb, int desc_num)
37013 +{
37014 +       return dwc_otg_urb->iso_descs[desc_num].actual_length;
37015 +}
37016 +
37017 +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
37018 +{
37019 +       int allocated = 0;
37020 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37021 +
37022 +       if (qh) {
37023 +               if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37024 +                       allocated = 1;
37025 +               }
37026 +       }
37027 +       return allocated;
37028 +}
37029 +
37030 +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
37031 +{
37032 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37033 +       int freed = 0;
37034 +       DWC_ASSERT(qh, "qh is not allocated\n");
37035 +
37036 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
37037 +               freed = 1;
37038 +       }
37039 +
37040 +       return freed;
37041 +}
37042 +
37043 +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
37044 +{
37045 +       dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
37046 +       DWC_ASSERT(qh, "qh is not allocated\n");
37047 +       return qh->usecs;
37048 +}
37049 +
37050 +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
37051 +{
37052 +#ifdef DEBUG
37053 +       int num_channels;
37054 +       int i;
37055 +       gnptxsts_data_t np_tx_status;
37056 +       hptxsts_data_t p_tx_status;
37057 +
37058 +       num_channels = hcd->core_if->core_params->host_channels;
37059 +       DWC_PRINTF("\n");
37060 +       DWC_PRINTF
37061 +           ("************************************************************\n");
37062 +       DWC_PRINTF("HCD State:\n");
37063 +       DWC_PRINTF("  Num channels: %d\n", num_channels);
37064 +       for (i = 0; i < num_channels; i++) {
37065 +               dwc_hc_t *hc = hcd->hc_ptr_array[i];
37066 +               DWC_PRINTF("  Channel %d:\n", i);
37067 +               DWC_PRINTF("    dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
37068 +                          hc->dev_addr, hc->ep_num, hc->ep_is_in);
37069 +               DWC_PRINTF("    speed: %d\n", hc->speed);
37070 +               DWC_PRINTF("    ep_type: %d\n", hc->ep_type);
37071 +               DWC_PRINTF("    max_packet: %d\n", hc->max_packet);
37072 +               DWC_PRINTF("    data_pid_start: %d\n", hc->data_pid_start);
37073 +               DWC_PRINTF("    multi_count: %d\n", hc->multi_count);
37074 +               DWC_PRINTF("    xfer_started: %d\n", hc->xfer_started);
37075 +               DWC_PRINTF("    xfer_buff: %p\n", hc->xfer_buff);
37076 +               DWC_PRINTF("    xfer_len: %d\n", hc->xfer_len);
37077 +               DWC_PRINTF("    xfer_count: %d\n", hc->xfer_count);
37078 +               DWC_PRINTF("    halt_on_queue: %d\n", hc->halt_on_queue);
37079 +               DWC_PRINTF("    halt_pending: %d\n", hc->halt_pending);
37080 +               DWC_PRINTF("    halt_status: %d\n", hc->halt_status);
37081 +               DWC_PRINTF("    do_split: %d\n", hc->do_split);
37082 +               DWC_PRINTF("    complete_split: %d\n", hc->complete_split);
37083 +               DWC_PRINTF("    hub_addr: %d\n", hc->hub_addr);
37084 +               DWC_PRINTF("    port_addr: %d\n", hc->port_addr);
37085 +               DWC_PRINTF("    xact_pos: %d\n", hc->xact_pos);
37086 +               DWC_PRINTF("    requests: %d\n", hc->requests);
37087 +               DWC_PRINTF("    qh: %p\n", hc->qh);
37088 +               if (hc->xfer_started) {
37089 +                       hfnum_data_t hfnum;
37090 +                       hcchar_data_t hcchar;
37091 +                       hctsiz_data_t hctsiz;
37092 +                       hcint_data_t hcint;
37093 +                       hcintmsk_data_t hcintmsk;
37094 +                       hfnum.d32 =
37095 +                           DWC_READ_REG32(&hcd->core_if->
37096 +                                          host_if->host_global_regs->hfnum);
37097 +                       hcchar.d32 =
37098 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37099 +                                          hc_regs[i]->hcchar);
37100 +                       hctsiz.d32 =
37101 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37102 +                                          hc_regs[i]->hctsiz);
37103 +                       hcint.d32 =
37104 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37105 +                                          hc_regs[i]->hcint);
37106 +                       hcintmsk.d32 =
37107 +                           DWC_READ_REG32(&hcd->core_if->host_if->
37108 +                                          hc_regs[i]->hcintmsk);
37109 +                       DWC_PRINTF("    hfnum: 0x%08x\n", hfnum.d32);
37110 +                       DWC_PRINTF("    hcchar: 0x%08x\n", hcchar.d32);
37111 +                       DWC_PRINTF("    hctsiz: 0x%08x\n", hctsiz.d32);
37112 +                       DWC_PRINTF("    hcint: 0x%08x\n", hcint.d32);
37113 +                       DWC_PRINTF("    hcintmsk: 0x%08x\n", hcintmsk.d32);
37114 +               }
37115 +               if (hc->xfer_started && hc->qh) {
37116 +                       dwc_otg_qtd_t *qtd;
37117 +                       dwc_otg_hcd_urb_t *urb;
37118 +
37119 +                       DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
37120 +                               if (!qtd->in_process)
37121 +                                       break;
37122 +
37123 +                               urb = qtd->urb;
37124 +                       DWC_PRINTF("    URB Info:\n");
37125 +                       DWC_PRINTF("      qtd: %p, urb: %p\n", qtd, urb);
37126 +                       if (urb) {
37127 +                               DWC_PRINTF("      Dev: %d, EP: %d %s\n",
37128 +                                          dwc_otg_hcd_get_dev_addr(&urb->
37129 +                                                                   pipe_info),
37130 +                                          dwc_otg_hcd_get_ep_num(&urb->
37131 +                                                                 pipe_info),
37132 +                                          dwc_otg_hcd_is_pipe_in(&urb->
37133 +                                                                 pipe_info) ?
37134 +                                          "IN" : "OUT");
37135 +                               DWC_PRINTF("      Max packet size: %d\n",
37136 +                                          dwc_otg_hcd_get_mps(&urb->
37137 +                                                              pipe_info));
37138 +                               DWC_PRINTF("      transfer_buffer: %p\n",
37139 +                                          urb->buf);
37140 +                               DWC_PRINTF("      transfer_dma: %p\n",
37141 +                                          (void *)urb->dma);
37142 +                               DWC_PRINTF("      transfer_buffer_length: %d\n",
37143 +                                          urb->length);
37144 +                                       DWC_PRINTF("      actual_length: %d\n",
37145 +                                                  urb->actual_length);
37146 +                               }
37147 +                       }
37148 +               }
37149 +       }
37150 +       DWC_PRINTF("  non_periodic_channels: %d\n", hcd->non_periodic_channels);
37151 +       DWC_PRINTF("  periodic_channels: %d\n", hcd->periodic_channels);
37152 +       DWC_PRINTF("  periodic_usecs: %d\n", hcd->periodic_usecs);
37153 +       np_tx_status.d32 =
37154 +           DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
37155 +       DWC_PRINTF("  NP Tx Req Queue Space Avail: %d\n",
37156 +                  np_tx_status.b.nptxqspcavail);
37157 +       DWC_PRINTF("  NP Tx FIFO Space Avail: %d\n",
37158 +                  np_tx_status.b.nptxfspcavail);
37159 +       p_tx_status.d32 =
37160 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
37161 +       DWC_PRINTF("  P Tx Req Queue Space Avail: %d\n",
37162 +                  p_tx_status.b.ptxqspcavail);
37163 +       DWC_PRINTF("  P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
37164 +       dwc_otg_hcd_dump_frrem(hcd);
37165 +       dwc_otg_dump_global_registers(hcd->core_if);
37166 +       dwc_otg_dump_host_registers(hcd->core_if);
37167 +       DWC_PRINTF
37168 +           ("************************************************************\n");
37169 +       DWC_PRINTF("\n");
37170 +#endif
37171 +}
37172 +
37173 +#ifdef DEBUG
37174 +void dwc_print_setup_data(uint8_t * setup)
37175 +{
37176 +       int i;
37177 +       if (CHK_DEBUG_LEVEL(DBG_HCD)) {
37178 +               DWC_PRINTF("Setup Data = MSB ");
37179 +               for (i = 7; i >= 0; i--)
37180 +                       DWC_PRINTF("%02x ", setup[i]);
37181 +               DWC_PRINTF("\n");
37182 +               DWC_PRINTF("  bmRequestType Tranfer = %s\n",
37183 +                          (setup[0] & 0x80) ? "Device-to-Host" :
37184 +                          "Host-to-Device");
37185 +               DWC_PRINTF("  bmRequestType Type = ");
37186 +               switch ((setup[0] & 0x60) >> 5) {
37187 +               case 0:
37188 +                       DWC_PRINTF("Standard\n");
37189 +                       break;
37190 +               case 1:
37191 +                       DWC_PRINTF("Class\n");
37192 +                       break;
37193 +               case 2:
37194 +                       DWC_PRINTF("Vendor\n");
37195 +                       break;
37196 +               case 3:
37197 +                       DWC_PRINTF("Reserved\n");
37198 +                       break;
37199 +               }
37200 +               DWC_PRINTF("  bmRequestType Recipient = ");
37201 +               switch (setup[0] & 0x1f) {
37202 +               case 0:
37203 +                       DWC_PRINTF("Device\n");
37204 +                       break;
37205 +               case 1:
37206 +                       DWC_PRINTF("Interface\n");
37207 +                       break;
37208 +               case 2:
37209 +                       DWC_PRINTF("Endpoint\n");
37210 +                       break;
37211 +               case 3:
37212 +                       DWC_PRINTF("Other\n");
37213 +                       break;
37214 +               default:
37215 +                       DWC_PRINTF("Reserved\n");
37216 +                       break;
37217 +               }
37218 +               DWC_PRINTF("  bRequest = 0x%0x\n", setup[1]);
37219 +               DWC_PRINTF("  wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
37220 +               DWC_PRINTF("  wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
37221 +               DWC_PRINTF("  wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
37222 +       }
37223 +}
37224 +#endif
37225 +
37226 +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
37227 +{
37228 +#if 0
37229 +       DWC_PRINTF("Frame remaining at SOF:\n");
37230 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37231 +                  hcd->frrem_samples, hcd->frrem_accum,
37232 +                  (hcd->frrem_samples > 0) ?
37233 +                  hcd->frrem_accum / hcd->frrem_samples : 0);
37234 +
37235 +       DWC_PRINTF("\n");
37236 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
37237 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37238 +                  hcd->core_if->hfnum_7_samples,
37239 +                  hcd->core_if->hfnum_7_frrem_accum,
37240 +                  (hcd->core_if->hfnum_7_samples >
37241 +                   0) ? hcd->core_if->hfnum_7_frrem_accum /
37242 +                  hcd->core_if->hfnum_7_samples : 0);
37243 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
37244 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37245 +                  hcd->core_if->hfnum_0_samples,
37246 +                  hcd->core_if->hfnum_0_frrem_accum,
37247 +                  (hcd->core_if->hfnum_0_samples >
37248 +                   0) ? hcd->core_if->hfnum_0_frrem_accum /
37249 +                  hcd->core_if->hfnum_0_samples : 0);
37250 +       DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
37251 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37252 +                  hcd->core_if->hfnum_other_samples,
37253 +                  hcd->core_if->hfnum_other_frrem_accum,
37254 +                  (hcd->core_if->hfnum_other_samples >
37255 +                   0) ? hcd->core_if->hfnum_other_frrem_accum /
37256 +                  hcd->core_if->hfnum_other_samples : 0);
37257 +
37258 +       DWC_PRINTF("\n");
37259 +       DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
37260 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37261 +                  hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
37262 +                  (hcd->hfnum_7_samples_a > 0) ?
37263 +                  hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
37264 +       DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
37265 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37266 +                  hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
37267 +                  (hcd->hfnum_0_samples_a > 0) ?
37268 +                  hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
37269 +       DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
37270 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37271 +                  hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
37272 +                  (hcd->hfnum_other_samples_a > 0) ?
37273 +                  hcd->hfnum_other_frrem_accum_a /
37274 +                  hcd->hfnum_other_samples_a : 0);
37275 +
37276 +       DWC_PRINTF("\n");
37277 +       DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
37278 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37279 +                  hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
37280 +                  (hcd->hfnum_7_samples_b > 0) ?
37281 +                  hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
37282 +       DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
37283 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37284 +                  hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
37285 +                  (hcd->hfnum_0_samples_b > 0) ?
37286 +                  hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
37287 +       DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
37288 +       DWC_PRINTF("  samples %u, accum %llu, avg %llu\n",
37289 +                  hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
37290 +                  (hcd->hfnum_other_samples_b > 0) ?
37291 +                  hcd->hfnum_other_frrem_accum_b /
37292 +                  hcd->hfnum_other_samples_b : 0);
37293 +#endif
37294 +}
37295 +
37296 +#endif /* DWC_DEVICE_ONLY */
37297 --- /dev/null
37298 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
37299 @@ -0,0 +1,824 @@
37300 +/* ==========================================================================
37301 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
37302 + * $Revision: #58 $
37303 + * $Date: 2011/09/15 $
37304 + * $Change: 1846647 $
37305 + *
37306 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
37307 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
37308 + * otherwise expressly agreed to in writing between Synopsys and you.
37309 + *
37310 + * The Software IS NOT an item of Licensed Software or Licensed Product under
37311 + * any End User Software License Agreement or Agreement for Licensed Product
37312 + * with Synopsys or any supplement thereto. You are permitted to use and
37313 + * redistribute this Software in source and binary forms, with or without
37314 + * modification, provided that redistributions of source code must retain this
37315 + * notice. You may not view, use, disclose, copy or distribute this file or
37316 + * any information contained herein except pursuant to this license grant from
37317 + * Synopsys. If you do not agree with this notice, including the disclaimer
37318 + * below, then you are not authorized to use the Software.
37319 + *
37320 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
37321 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37322 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37323 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
37324 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37325 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37326 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37327 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37328 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37329 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
37330 + * DAMAGE.
37331 + * ========================================================================== */
37332 +#ifndef DWC_DEVICE_ONLY
37333 +#ifndef __DWC_HCD_H__
37334 +#define __DWC_HCD_H__
37335 +
37336 +#include "dwc_otg_os_dep.h"
37337 +#include "usb.h"
37338 +#include "dwc_otg_hcd_if.h"
37339 +#include "dwc_otg_core_if.h"
37340 +#include "dwc_list.h"
37341 +#include "dwc_otg_cil.h"
37342 +
37343 +/**
37344 + * @file
37345 + *
37346 + * This file contains the structures, constants, and interfaces for
37347 + * the Host Contoller Driver (HCD).
37348 + *
37349 + * The Host Controller Driver (HCD) is responsible for translating requests
37350 + * from the USB Driver into the appropriate actions on the DWC_otg controller.
37351 + * It isolates the USBD from the specifics of the controller by providing an
37352 + * API to the USBD.
37353 + */
37354 +
37355 +struct dwc_otg_hcd_pipe_info {
37356 +       uint8_t dev_addr;
37357 +       uint8_t ep_num;
37358 +       uint8_t pipe_type;
37359 +       uint8_t pipe_dir;
37360 +       uint16_t mps;
37361 +};
37362 +
37363 +struct dwc_otg_hcd_iso_packet_desc {
37364 +       uint32_t offset;
37365 +       uint32_t length;
37366 +       uint32_t actual_length;
37367 +       uint32_t status;
37368 +};
37369 +
37370 +struct dwc_otg_qtd;
37371 +
37372 +struct dwc_otg_hcd_urb {
37373 +       void *priv;
37374 +       struct dwc_otg_qtd *qtd;
37375 +       void *buf;
37376 +       dwc_dma_t dma;
37377 +       void *setup_packet;
37378 +       dwc_dma_t setup_dma;
37379 +       uint32_t length;
37380 +       uint32_t actual_length;
37381 +       uint32_t status;
37382 +       uint32_t error_count;
37383 +       uint32_t packet_count;
37384 +       uint32_t flags;
37385 +       uint16_t interval;
37386 +       struct dwc_otg_hcd_pipe_info pipe_info;
37387 +       struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
37388 +};
37389 +
37390 +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
37391 +{
37392 +       return pipe->ep_num;
37393 +}
37394 +
37395 +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
37396 +                                               *pipe)
37397 +{
37398 +       return pipe->pipe_type;
37399 +}
37400 +
37401 +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
37402 +{
37403 +       return pipe->mps;
37404 +}
37405 +
37406 +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
37407 +                                              *pipe)
37408 +{
37409 +       return pipe->dev_addr;
37410 +}
37411 +
37412 +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
37413 +                                              *pipe)
37414 +{
37415 +       return (pipe->pipe_type == UE_ISOCHRONOUS);
37416 +}
37417 +
37418 +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
37419 +                                             *pipe)
37420 +{
37421 +       return (pipe->pipe_type == UE_INTERRUPT);
37422 +}
37423 +
37424 +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
37425 +                                              *pipe)
37426 +{
37427 +       return (pipe->pipe_type == UE_BULK);
37428 +}
37429 +
37430 +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
37431 +                                                 *pipe)
37432 +{
37433 +       return (pipe->pipe_type == UE_CONTROL);
37434 +}
37435 +
37436 +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
37437 +{
37438 +       return (pipe->pipe_dir == UE_DIR_IN);
37439 +}
37440 +
37441 +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
37442 +                                             *pipe)
37443 +{
37444 +       return (!dwc_otg_hcd_is_pipe_in(pipe));
37445 +}
37446 +
37447 +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
37448 +                                        uint8_t devaddr, uint8_t ep_num,
37449 +                                        uint8_t pipe_type, uint8_t pipe_dir,
37450 +                                        uint16_t mps)
37451 +{
37452 +       pipe->dev_addr = devaddr;
37453 +       pipe->ep_num = ep_num;
37454 +       pipe->pipe_type = pipe_type;
37455 +       pipe->pipe_dir = pipe_dir;
37456 +       pipe->mps = mps;
37457 +}
37458 +
37459 +/**
37460 + * Phases for control transfers.
37461 + */
37462 +typedef enum dwc_otg_control_phase {
37463 +       DWC_OTG_CONTROL_SETUP,
37464 +       DWC_OTG_CONTROL_DATA,
37465 +       DWC_OTG_CONTROL_STATUS
37466 +} dwc_otg_control_phase_e;
37467 +
37468 +/** Transaction types. */
37469 +typedef enum dwc_otg_transaction_type {
37470 +       DWC_OTG_TRANSACTION_NONE,
37471 +       DWC_OTG_TRANSACTION_PERIODIC,
37472 +       DWC_OTG_TRANSACTION_NON_PERIODIC,
37473 +       DWC_OTG_TRANSACTION_ALL
37474 +} dwc_otg_transaction_type_e;
37475 +
37476 +struct dwc_otg_qh;
37477 +
37478 +/**
37479 + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
37480 + * interrupt, or isochronous transfer. A single QTD is created for each URB
37481 + * (of one of these types) submitted to the HCD. The transfer associated with
37482 + * a QTD may require one or multiple transactions.
37483 + *
37484 + * A QTD is linked to a Queue Head, which is entered in either the
37485 + * non-periodic or periodic schedule for execution. When a QTD is chosen for
37486 + * execution, some or all of its transactions may be executed. After
37487 + * execution, the state of the QTD is updated. The QTD may be retired if all
37488 + * its transactions are complete or if an error occurred. Otherwise, it
37489 + * remains in the schedule so more transactions can be executed later.
37490 + */
37491 +typedef struct dwc_otg_qtd {
37492 +       /**
37493 +        * Determines the PID of the next data packet for the data phase of
37494 +        * control transfers. Ignored for other transfer types.<br>
37495 +        * One of the following values:
37496 +        *      - DWC_OTG_HC_PID_DATA0
37497 +        *      - DWC_OTG_HC_PID_DATA1
37498 +        */
37499 +       uint8_t data_toggle;
37500 +
37501 +       /** Current phase for control transfers (Setup, Data, or Status). */
37502 +       dwc_otg_control_phase_e control_phase;
37503 +
37504 +       /** Keep track of the current split type
37505 +        * for FS/LS endpoints on a HS Hub */
37506 +       uint8_t complete_split;
37507 +
37508 +       /** How many bytes transferred during SSPLIT OUT */
37509 +       uint32_t ssplit_out_xfer_count;
37510 +
37511 +       /**
37512 +        * Holds the number of bus errors that have occurred for a transaction
37513 +        * within this transfer.
37514 +        */
37515 +       uint8_t error_count;
37516 +
37517 +       /**
37518 +        * Index of the next frame descriptor for an isochronous transfer. A
37519 +        * frame descriptor describes the buffer position and length of the
37520 +        * data to be transferred in the next scheduled (micro)frame of an
37521 +        * isochronous transfer. It also holds status for that transaction.
37522 +        * The frame index starts at 0.
37523 +        */
37524 +       uint16_t isoc_frame_index;
37525 +
37526 +       /** Position of the ISOC split on full/low speed */
37527 +       uint8_t isoc_split_pos;
37528 +
37529 +       /** Position of the ISOC split in the buffer for the current frame */
37530 +       uint16_t isoc_split_offset;
37531 +
37532 +       /** URB for this transfer */
37533 +       struct dwc_otg_hcd_urb *urb;
37534 +
37535 +       struct dwc_otg_qh *qh;
37536 +
37537 +       /** This list of QTDs */
37538 +        DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
37539 +
37540 +       /** Indicates if this QTD is currently processed by HW. */
37541 +       uint8_t in_process;
37542 +
37543 +       /** Number of DMA descriptors for this QTD */
37544 +       uint8_t n_desc;
37545 +
37546 +       /**
37547 +        * Last activated frame(packet) index.
37548 +        * Used in Descriptor DMA mode only.
37549 +        */
37550 +       uint16_t isoc_frame_index_last;
37551 +
37552 +} dwc_otg_qtd_t;
37553 +
37554 +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
37555 +
37556 +/**
37557 + * A Queue Head (QH) holds the static characteristics of an endpoint and
37558 + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
37559 + * be entered in either the non-periodic or periodic schedule.
37560 + */
37561 +typedef struct dwc_otg_qh {
37562 +       /**
37563 +        * Endpoint type.
37564 +        * One of the following values:
37565 +        *      - UE_CONTROL
37566 +        *      - UE_BULK
37567 +        *      - UE_INTERRUPT
37568 +        *      - UE_ISOCHRONOUS
37569 +        */
37570 +       uint8_t ep_type;
37571 +       uint8_t ep_is_in;
37572 +
37573 +       /** wMaxPacketSize Field of Endpoint Descriptor. */
37574 +       uint16_t maxp;
37575 +
37576 +       /**
37577 +        * Device speed.
37578 +        * One of the following values:
37579 +        *      - DWC_OTG_EP_SPEED_LOW
37580 +        *      - DWC_OTG_EP_SPEED_FULL
37581 +        *      - DWC_OTG_EP_SPEED_HIGH
37582 +        */
37583 +       uint8_t dev_speed;
37584 +
37585 +       /**
37586 +        * Determines the PID of the next data packet for non-control
37587 +        * transfers. Ignored for control transfers.<br>
37588 +        * One of the following values:
37589 +        *      - DWC_OTG_HC_PID_DATA0
37590 +        *      - DWC_OTG_HC_PID_DATA1
37591 +        */
37592 +       uint8_t data_toggle;
37593 +
37594 +       /** Ping state if 1. */
37595 +       uint8_t ping_state;
37596 +
37597 +       /**
37598 +        * List of QTDs for this QH.
37599 +        */
37600 +       struct dwc_otg_qtd_list qtd_list;
37601 +
37602 +       /** Host channel currently processing transfers for this QH. */
37603 +       struct dwc_hc *channel;
37604 +
37605 +       /** Full/low speed endpoint on high-speed hub requires split. */
37606 +       uint8_t do_split;
37607 +
37608 +       /** @name Periodic schedule information */
37609 +       /** @{ */
37610 +
37611 +       /** Bandwidth in microseconds per (micro)frame. */
37612 +       uint16_t usecs;
37613 +
37614 +       /** Interval between transfers in (micro)frames. */
37615 +       uint16_t interval;
37616 +
37617 +       /**
37618 +        * (micro)frame to initialize a periodic transfer. The transfer
37619 +        * executes in the following (micro)frame.
37620 +        */
37621 +       uint16_t sched_frame;
37622 +
37623 +       /** (micro)frame at which last start split was initialized. */
37624 +       uint16_t start_split_frame;
37625 +
37626 +       /** @} */
37627 +
37628 +       /**
37629 +        * Used instead of original buffer if
37630 +        * it(physical address) is not dword-aligned.
37631 +        */
37632 +       uint8_t *dw_align_buf;
37633 +       dwc_dma_t dw_align_buf_dma;
37634 +
37635 +       /** Entry for QH in either the periodic or non-periodic schedule. */
37636 +       dwc_list_link_t qh_list_entry;
37637 +
37638 +       /** @name Descriptor DMA support */
37639 +       /** @{ */
37640 +
37641 +       /** Descriptor List. */
37642 +       dwc_otg_host_dma_desc_t *desc_list;
37643 +
37644 +       /** Descriptor List physical address. */
37645 +       dwc_dma_t desc_list_dma;
37646 +
37647 +       /**
37648 +        * Xfer Bytes array.
37649 +        * Each element corresponds to a descriptor and indicates
37650 +        * original XferSize size value for the descriptor.
37651 +        */
37652 +       uint32_t *n_bytes;
37653 +
37654 +       /** Actual number of transfer descriptors in a list. */
37655 +       uint16_t ntd;
37656 +
37657 +       /** First activated isochronous transfer descriptor index. */
37658 +       uint8_t td_first;
37659 +       /** Last activated isochronous transfer descriptor index. */
37660 +       uint8_t td_last;
37661 +
37662 +       /** @} */
37663 +
37664 +
37665 +       uint16_t speed;
37666 +       uint16_t frame_usecs[8];
37667 +} dwc_otg_qh_t;
37668 +
37669 +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
37670 +
37671 +/**
37672 + * This structure holds the state of the HCD, including the non-periodic and
37673 + * periodic schedules.
37674 + */
37675 +struct dwc_otg_hcd {
37676 +       /** The DWC otg device pointer */
37677 +       struct dwc_otg_device *otg_dev;
37678 +       /** DWC OTG Core Interface Layer */
37679 +       dwc_otg_core_if_t *core_if;
37680 +
37681 +       /** Function HCD driver callbacks */
37682 +       struct dwc_otg_hcd_function_ops *fops;
37683 +
37684 +       /** Internal DWC HCD Flags */
37685 +       volatile union dwc_otg_hcd_internal_flags {
37686 +               uint32_t d32;
37687 +               struct {
37688 +                       unsigned port_connect_status_change:1;
37689 +                       unsigned port_connect_status:1;
37690 +                       unsigned port_reset_change:1;
37691 +                       unsigned port_enable_change:1;
37692 +                       unsigned port_suspend_change:1;
37693 +                       unsigned port_over_current_change:1;
37694 +                       unsigned port_l1_change:1;
37695 +                       unsigned reserved:26;
37696 +               } b;
37697 +       } flags;
37698 +
37699 +       /**
37700 +        * Inactive items in the non-periodic schedule. This is a list of
37701 +        * Queue Heads. Transfers associated with these Queue Heads are not
37702 +        * currently assigned to a host channel.
37703 +        */
37704 +       dwc_list_link_t non_periodic_sched_inactive;
37705 +
37706 +       /**
37707 +        * Active items in the non-periodic schedule. This is a list of
37708 +        * Queue Heads. Transfers associated with these Queue Heads are
37709 +        * currently assigned to a host channel.
37710 +        */
37711 +       dwc_list_link_t non_periodic_sched_active;
37712 +
37713 +       /**
37714 +        * Pointer to the next Queue Head to process in the active
37715 +        * non-periodic schedule.
37716 +        */
37717 +       dwc_list_link_t *non_periodic_qh_ptr;
37718 +
37719 +       /**
37720 +        * Inactive items in the periodic schedule. This is a list of QHs for
37721 +        * periodic transfers that are _not_ scheduled for the next frame.
37722 +        * Each QH in the list has an interval counter that determines when it
37723 +        * needs to be scheduled for execution. This scheduling mechanism
37724 +        * allows only a simple calculation for periodic bandwidth used (i.e.
37725 +        * must assume that all periodic transfers may need to execute in the
37726 +        * same frame). However, it greatly simplifies scheduling and should
37727 +        * be sufficient for the vast majority of OTG hosts, which need to
37728 +        * connect to a small number of peripherals at one time.
37729 +        *
37730 +        * Items move from this list to periodic_sched_ready when the QH
37731 +        * interval counter is 0 at SOF.
37732 +        */
37733 +       dwc_list_link_t periodic_sched_inactive;
37734 +
37735 +       /**
37736 +        * List of periodic QHs that are ready for execution in the next
37737 +        * frame, but have not yet been assigned to host channels.
37738 +        *
37739 +        * Items move from this list to periodic_sched_assigned as host
37740 +        * channels become available during the current frame.
37741 +        */
37742 +       dwc_list_link_t periodic_sched_ready;
37743 +
37744 +       /**
37745 +        * List of periodic QHs to be executed in the next frame that are
37746 +        * assigned to host channels.
37747 +        *
37748 +        * Items move from this list to periodic_sched_queued as the
37749 +        * transactions for the QH are queued to the DWC_otg controller.
37750 +        */
37751 +       dwc_list_link_t periodic_sched_assigned;
37752 +
37753 +       /**
37754 +        * List of periodic QHs that have been queued for execution.
37755 +        *
37756 +        * Items move from this list to either periodic_sched_inactive or
37757 +        * periodic_sched_ready when the channel associated with the transfer
37758 +        * is released. If the interval for the QH is 1, the item moves to
37759 +        * periodic_sched_ready because it must be rescheduled for the next
37760 +        * frame. Otherwise, the item moves to periodic_sched_inactive.
37761 +        */
37762 +       dwc_list_link_t periodic_sched_queued;
37763 +
37764 +       /**
37765 +        * Total bandwidth claimed so far for periodic transfers. This value
37766 +        * is in microseconds per (micro)frame. The assumption is that all
37767 +        * periodic transfers may occur in the same (micro)frame.
37768 +        */
37769 +       uint16_t periodic_usecs;
37770 +
37771 +       /**
37772 +        * Total bandwidth claimed so far for all periodic transfers
37773 +        * in a frame.
37774 +        * This will include a mixture of HS and FS transfers.
37775 +        * Units are microseconds per (micro)frame.
37776 +        * We have a budget per frame and have to schedule
37777 +        * transactions accordingly.
37778 +        * Watch out for the fact that things are actually scheduled for the
37779 +        * "next frame".
37780 +        */
37781 +       uint16_t                frame_usecs[8];
37782 +
37783 +
37784 +       /**
37785 +        * Frame number read from the core at SOF. The value ranges from 0 to
37786 +        * DWC_HFNUM_MAX_FRNUM.
37787 +        */
37788 +       uint16_t frame_number;
37789 +
37790 +       /**
37791 +        * Count of periodic QHs, if using several eps. For SOF enable/disable.
37792 +        */
37793 +       uint16_t periodic_qh_count;
37794 +
37795 +       /**
37796 +        * Free host channels in the controller. This is a list of
37797 +        * dwc_hc_t items.
37798 +        */
37799 +       struct hc_list free_hc_list;
37800 +       /**
37801 +        * Number of host channels assigned to periodic transfers. Currently
37802 +        * assuming that there is a dedicated host channel for each periodic
37803 +        * transaction and at least one host channel available for
37804 +        * non-periodic transactions.
37805 +        */
37806 +       int periodic_channels; /* microframe_schedule==0 */
37807 +
37808 +       /**
37809 +        * Number of host channels assigned to non-periodic transfers.
37810 +        */
37811 +       int non_periodic_channels; /* microframe_schedule==0 */
37812 +
37813 +       /**
37814 +        * Number of host channels assigned to non-periodic transfers.
37815 +        */
37816 +       int available_host_channels;
37817 +
37818 +       /**
37819 +        * Array of pointers to the host channel descriptors. Allows accessing
37820 +        * a host channel descriptor given the host channel number. This is
37821 +        * useful in interrupt handlers.
37822 +        */
37823 +       struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
37824 +
37825 +       /**
37826 +        * Buffer to use for any data received during the status phase of a
37827 +        * control transfer. Normally no data is transferred during the status
37828 +        * phase. This buffer is used as a bit bucket.
37829 +        */
37830 +       uint8_t *status_buf;
37831 +
37832 +       /**
37833 +        * DMA address for status_buf.
37834 +        */
37835 +       dma_addr_t status_buf_dma;
37836 +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
37837 +
37838 +       /**
37839 +        * Connection timer. An OTG host must display a message if the device
37840 +        * does not connect. Started when the VBus power is turned on via
37841 +        * sysfs attribute "buspower".
37842 +        */
37843 +       dwc_timer_t *conn_timer;
37844 +
37845 +       /* Tasket to do a reset */
37846 +       dwc_tasklet_t *reset_tasklet;
37847 +
37848 +       /*  */
37849 +       dwc_spinlock_t *lock;
37850 +
37851 +       /**
37852 +        * Private data that could be used by OS wrapper.
37853 +        */
37854 +       void *priv;
37855 +
37856 +       uint8_t otg_port;
37857 +
37858 +       /** Frame List */
37859 +       uint32_t *frame_list;
37860 +
37861 +       /** Frame List DMA address */
37862 +       dma_addr_t frame_list_dma;
37863 +
37864 +#ifdef DEBUG
37865 +       uint32_t frrem_samples;
37866 +       uint64_t frrem_accum;
37867 +
37868 +       uint32_t hfnum_7_samples_a;
37869 +       uint64_t hfnum_7_frrem_accum_a;
37870 +       uint32_t hfnum_0_samples_a;
37871 +       uint64_t hfnum_0_frrem_accum_a;
37872 +       uint32_t hfnum_other_samples_a;
37873 +       uint64_t hfnum_other_frrem_accum_a;
37874 +
37875 +       uint32_t hfnum_7_samples_b;
37876 +       uint64_t hfnum_7_frrem_accum_b;
37877 +       uint32_t hfnum_0_samples_b;
37878 +       uint64_t hfnum_0_frrem_accum_b;
37879 +       uint32_t hfnum_other_samples_b;
37880 +       uint64_t hfnum_other_frrem_accum_b;
37881 +#endif
37882 +};
37883 +
37884 +/** @name Transaction Execution Functions */
37885 +/** @{ */
37886 +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
37887 +                                                                 * hcd);
37888 +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
37889 +                                          dwc_otg_transaction_type_e tr_type);
37890 +
37891 +/** @} */
37892 +
37893 +/** @name Interrupt Handler Functions */
37894 +/** @{ */
37895 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37896 +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37897 +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
37898 +                                                        dwc_otg_hcd);
37899 +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
37900 +                                                       dwc_otg_hcd);
37901 +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
37902 +                                                          dwc_otg_hcd);
37903 +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
37904 +                                                          dwc_otg_hcd);
37905 +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37906 +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
37907 +                                                            dwc_otg_hcd);
37908 +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37909 +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37910 +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
37911 +                                           uint32_t num);
37912 +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
37913 +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
37914 +                                                      dwc_otg_hcd);
37915 +/** @} */
37916 +
37917 +/** @name Schedule Queue Functions */
37918 +/** @{ */
37919 +
37920 +/* Implemented in dwc_otg_hcd_queue.c */
37921 +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
37922 +                                          dwc_otg_hcd_urb_t * urb, int atomic_alloc);
37923 +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37924 +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37925 +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
37926 +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
37927 +                                     int sched_csplit);
37928 +
37929 +/** Remove and free a QH */
37930 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
37931 +                                                 dwc_otg_qh_t * qh)
37932 +{
37933 +       dwc_irqflags_t flags;
37934 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
37935 +       dwc_otg_hcd_qh_remove(hcd, qh);
37936 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
37937 +       dwc_otg_hcd_qh_free(hcd, qh);
37938 +}
37939 +
37940 +/** Allocates memory for a QH structure.
37941 + * @return Returns the memory allocate or NULL on error. */
37942 +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
37943 +{
37944 +       if (atomic_alloc)
37945 +               return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
37946 +       else
37947 +               return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
37948 +}
37949 +
37950 +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
37951 +                                            int atomic_alloc);
37952 +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
37953 +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
37954 +                              dwc_otg_qh_t ** qh, int atomic_alloc);
37955 +
37956 +/** Allocates memory for a QTD structure.
37957 + * @return Returns the memory allocate or NULL on error. */
37958 +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
37959 +{
37960 +       if (atomic_alloc)
37961 +               return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
37962 +       else
37963 +               return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
37964 +}
37965 +
37966 +/** Frees the memory for a QTD structure.  QTD should already be removed from
37967 + * list.
37968 + * @param qtd QTD to free.*/
37969 +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
37970 +{
37971 +       DWC_FREE(qtd);
37972 +}
37973 +
37974 +/** Removes a QTD from list.
37975 + * @param hcd HCD instance.
37976 + * @param qtd QTD to remove from list.
37977 + * @param qh QTD belongs to.
37978 + */
37979 +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
37980 +                                         dwc_otg_qtd_t * qtd,
37981 +                                         dwc_otg_qh_t * qh)
37982 +{
37983 +       DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
37984 +}
37985 +
37986 +/** Remove and free a QTD
37987 +  * Need to disable IRQ and hold hcd lock while calling this function out of
37988 +  * interrupt servicing chain */
37989 +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
37990 +                                                  dwc_otg_qtd_t * qtd,
37991 +                                                  dwc_otg_qh_t * qh)
37992 +{
37993 +       dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
37994 +       dwc_otg_hcd_qtd_free(qtd);
37995 +}
37996 +
37997 +/** @} */
37998 +
37999 +/** @name Descriptor DMA Supporting Functions */
38000 +/** @{ */
38001 +
38002 +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38003 +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
38004 +                                          dwc_hc_t * hc,
38005 +                                          dwc_otg_hc_regs_t * hc_regs,
38006 +                                          dwc_otg_halt_status_e halt_status);
38007 +
38008 +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38009 +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
38010 +
38011 +/** @} */
38012 +
38013 +/** @name Internal Functions */
38014 +/** @{ */
38015 +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
38016 +/** @} */
38017 +
38018 +#ifdef CONFIG_USB_DWC_OTG_LPM
38019 +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
38020 +                                          uint8_t devaddr);
38021 +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
38022 +#endif
38023 +
38024 +/** Gets the QH that contains the list_head */
38025 +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
38026 +
38027 +/** Gets the QTD that contains the list_head */
38028 +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
38029 +
38030 +/** Check if QH is non-periodic  */
38031 +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
38032 +                                    (_qh_ptr_->ep_type == UE_CONTROL))
38033 +
38034 +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
38035 +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
38036 +
38037 +/** Packet size for any kind of endpoint descriptor */
38038 +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
38039 +
38040 +/**
38041 + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
38042 + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
38043 + * frame number when the max frame number is reached.
38044 + */
38045 +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
38046 +{
38047 +       return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
38048 +           (DWC_HFNUM_MAX_FRNUM >> 1);
38049 +}
38050 +
38051 +/**
38052 + * Returns true if _frame1 is greater than _frame2. The comparison is done
38053 + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
38054 + * number when the max frame number is reached.
38055 + */
38056 +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
38057 +{
38058 +       return (frame1 != frame2) &&
38059 +           (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
38060 +            (DWC_HFNUM_MAX_FRNUM >> 1));
38061 +}
38062 +
38063 +/**
38064 + * Increments _frame by the amount specified by _inc. The addition is done
38065 + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
38066 + */
38067 +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
38068 +{
38069 +       return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
38070 +}
38071 +
38072 +static inline uint16_t dwc_full_frame_num(uint16_t frame)
38073 +{
38074 +       return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
38075 +}
38076 +
38077 +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
38078 +{
38079 +       return frame & 0x7;
38080 +}
38081 +
38082 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
38083 +                                 dwc_otg_hc_regs_t * hc_regs,
38084 +                                 dwc_otg_qtd_t * qtd);
38085 +
38086 +#ifdef DEBUG
38087 +/**
38088 + * Macro to sample the remaining PHY clocks left in the current frame. This
38089 + * may be used during debugging to determine the average time it takes to
38090 + * execute sections of code. There are two possible sample points, "a" and
38091 + * "b", so the _letter argument must be one of these values.
38092 + *
38093 + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
38094 + * example, "cat /sys/devices/lm0/hcd_frrem".
38095 + */
38096 +#define dwc_sample_frrem(_hcd, _qh, _letter) \
38097 +{ \
38098 +       hfnum_data_t hfnum; \
38099 +       dwc_otg_qtd_t *qtd; \
38100 +       qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
38101 +       if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
38102 +               hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
38103 +               switch (hfnum.b.frnum & 0x7) { \
38104 +               case 7: \
38105 +                       _hcd->hfnum_7_samples_##_letter++; \
38106 +                       _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
38107 +                       break; \
38108 +               case 0: \
38109 +                       _hcd->hfnum_0_samples_##_letter++; \
38110 +                       _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
38111 +                       break; \
38112 +               default: \
38113 +                       _hcd->hfnum_other_samples_##_letter++; \
38114 +                       _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
38115 +                       break; \
38116 +               } \
38117 +       } \
38118 +}
38119 +#else
38120 +#define dwc_sample_frrem(_hcd, _qh, _letter)
38121 +#endif
38122 +#endif
38123 +#endif /* DWC_DEVICE_ONLY */
38124 --- /dev/null
38125 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
38126 @@ -0,0 +1,1133 @@
38127 +/*==========================================================================
38128 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
38129 + * $Revision: #10 $
38130 + * $Date: 2011/10/20 $
38131 + * $Change: 1869464 $
38132 + *
38133 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
38134 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
38135 + * otherwise expressly agreed to in writing between Synopsys and you.
38136 + *
38137 + * The Software IS NOT an item of Licensed Software or Licensed Product under
38138 + * any End User Software License Agreement or Agreement for Licensed Product
38139 + * with Synopsys or any supplement thereto. You are permitted to use and
38140 + * redistribute this Software in source and binary forms, with or without
38141 + * modification, provided that redistributions of source code must retain this
38142 + * notice. You may not view, use, disclose, copy or distribute this file or
38143 + * any information contained herein except pursuant to this license grant from
38144 + * Synopsys. If you do not agree with this notice, including the disclaimer
38145 + * below, then you are not authorized to use the Software.
38146 + *
38147 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
38148 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38149 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38150 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
38151 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38152 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38153 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38154 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38155 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38156 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38157 + * DAMAGE.
38158 + * ========================================================================== */
38159 +#ifndef DWC_DEVICE_ONLY
38160 +
38161 +/** @file
38162 + * This file contains Descriptor DMA support implementation for host mode.
38163 + */
38164 +
38165 +#include "dwc_otg_hcd.h"
38166 +#include "dwc_otg_regs.h"
38167 +
38168 +extern bool microframe_schedule;
38169 +
38170 +static inline uint8_t frame_list_idx(uint16_t frame)
38171 +{
38172 +       return (frame & (MAX_FRLIST_EN_NUM - 1));
38173 +}
38174 +
38175 +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
38176 +{
38177 +       return (idx + inc) &
38178 +           (((speed ==
38179 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38180 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38181 +}
38182 +
38183 +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
38184 +{
38185 +       return (idx - inc) &
38186 +           (((speed ==
38187 +              DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
38188 +             MAX_DMA_DESC_NUM_GENERIC) - 1);
38189 +}
38190 +
38191 +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
38192 +{
38193 +       return (((qh->ep_type == UE_ISOCHRONOUS)
38194 +                && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))
38195 +               ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);
38196 +}
38197 +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
38198 +{
38199 +       return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)
38200 +               ? ((qh->interval + 8 - 1) / 8)
38201 +               : qh->interval);
38202 +}
38203 +
38204 +static int desc_list_alloc(dwc_otg_qh_t * qh)
38205 +{
38206 +       int retval = 0;
38207 +
38208 +       qh->desc_list = (dwc_otg_host_dma_desc_t *)
38209 +           DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
38210 +                         &qh->desc_list_dma);
38211 +
38212 +       if (!qh->desc_list) {
38213 +               retval = -DWC_E_NO_MEMORY;
38214 +               DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
38215 +
38216 +       }
38217 +
38218 +       dwc_memset(qh->desc_list, 0x00,
38219 +                  sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38220 +
38221 +       qh->n_bytes =
38222 +           (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));
38223 +
38224 +       if (!qh->n_bytes) {
38225 +               retval = -DWC_E_NO_MEMORY;
38226 +               DWC_ERROR
38227 +                   ("%s: Failed to allocate array for descriptors' size actual values\n",
38228 +                    __func__);
38229 +
38230 +       }
38231 +       return retval;
38232 +
38233 +}
38234 +
38235 +static void desc_list_free(dwc_otg_qh_t * qh)
38236 +{
38237 +       if (qh->desc_list) {
38238 +               DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,
38239 +                            qh->desc_list_dma);
38240 +               qh->desc_list = NULL;
38241 +       }
38242 +
38243 +       if (qh->n_bytes) {
38244 +               DWC_FREE(qh->n_bytes);
38245 +               qh->n_bytes = NULL;
38246 +       }
38247 +}
38248 +
38249 +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
38250 +{
38251 +       int retval = 0;
38252 +       if (hcd->frame_list)
38253 +               return 0;
38254 +
38255 +       hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,
38256 +                                       &hcd->frame_list_dma);
38257 +       if (!hcd->frame_list) {
38258 +               retval = -DWC_E_NO_MEMORY;
38259 +               DWC_ERROR("%s: Frame List allocation failed\n", __func__);
38260 +       }
38261 +
38262 +       dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
38263 +
38264 +       return retval;
38265 +}
38266 +
38267 +static void frame_list_free(dwc_otg_hcd_t * hcd)
38268 +{
38269 +       if (!hcd->frame_list)
38270 +               return;
38271 +
38272 +       DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
38273 +       hcd->frame_list = NULL;
38274 +}
38275 +
38276 +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
38277 +{
38278 +
38279 +       hcfg_data_t hcfg;
38280 +
38281 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38282 +
38283 +       if (hcfg.b.perschedena) {
38284 +               /* already enabled */
38285 +               return;
38286 +       }
38287 +
38288 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,
38289 +                       hcd->frame_list_dma);
38290 +
38291 +       switch (fr_list_en) {
38292 +       case 64:
38293 +               hcfg.b.frlisten = 3;
38294 +               break;
38295 +       case 32:
38296 +               hcfg.b.frlisten = 2;
38297 +               break;
38298 +       case 16:
38299 +               hcfg.b.frlisten = 1;
38300 +               break;
38301 +       case 8:
38302 +               hcfg.b.frlisten = 0;
38303 +               break;
38304 +       default:
38305 +               break;
38306 +       }
38307 +
38308 +       hcfg.b.perschedena = 1;
38309 +
38310 +       DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
38311 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38312 +
38313 +}
38314 +
38315 +static void per_sched_disable(dwc_otg_hcd_t * hcd)
38316 +{
38317 +       hcfg_data_t hcfg;
38318 +
38319 +       hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
38320 +
38321 +       if (!hcfg.b.perschedena) {
38322 +               /* already disabled */
38323 +               return;
38324 +       }
38325 +       hcfg.b.perschedena = 0;
38326 +
38327 +       DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
38328 +       DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
38329 +}
38330 +
38331 +/*
38332 + * Activates/Deactivates FrameList entries for the channel
38333 + * based on endpoint servicing period.
38334 + */
38335 +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
38336 +{
38337 +       uint16_t i, j, inc;
38338 +       dwc_hc_t *hc = NULL;
38339 +
38340 +       if (!qh->channel) {
38341 +               DWC_ERROR("qh->channel = %p", qh->channel);
38342 +               return;
38343 +       }
38344 +
38345 +       if (!hcd) {
38346 +               DWC_ERROR("------hcd = %p", hcd);
38347 +               return;
38348 +       }
38349 +
38350 +       if (!hcd->frame_list) {
38351 +               DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);
38352 +               return;
38353 +       }
38354 +
38355 +       hc = qh->channel;
38356 +       inc = frame_incr_val(qh);
38357 +       if (qh->ep_type == UE_ISOCHRONOUS)
38358 +               i = frame_list_idx(qh->sched_frame);
38359 +       else
38360 +               i = 0;
38361 +
38362 +       j = i;
38363 +       do {
38364 +               if (enable)
38365 +                       hcd->frame_list[j] |= (1 << hc->hc_num);
38366 +               else
38367 +                       hcd->frame_list[j] &= ~(1 << hc->hc_num);
38368 +               j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
38369 +       }
38370 +       while (j != i);
38371 +       if (!enable)
38372 +               return;
38373 +       hc->schinfo = 0;
38374 +       if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
38375 +               j = 1;
38376 +               /* TODO - check this */
38377 +               inc = (8 + qh->interval - 1) / qh->interval;
38378 +               for (i = 0; i < inc; i++) {
38379 +                       hc->schinfo |= j;
38380 +                       j = j << qh->interval;
38381 +               }
38382 +       } else {
38383 +               hc->schinfo = 0xff;
38384 +       }
38385 +}
38386 +
38387 +#if 1
38388 +void dump_frame_list(dwc_otg_hcd_t * hcd)
38389 +{
38390 +       int i = 0;
38391 +       DWC_PRINTF("--FRAME LIST (hex) --\n");
38392 +       for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
38393 +               DWC_PRINTF("%x\t", hcd->frame_list[i]);
38394 +               if (!(i % 8) && i)
38395 +                       DWC_PRINTF("\n");
38396 +       }
38397 +       DWC_PRINTF("\n----\n");
38398 +
38399 +}
38400 +#endif
38401 +
38402 +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38403 +{
38404 +       dwc_irqflags_t flags;
38405 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
38406 +
38407 +       dwc_hc_t *hc = qh->channel;
38408 +       if (dwc_qh_is_non_per(qh)) {
38409 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
38410 +               if (!microframe_schedule)
38411 +                       hcd->non_periodic_channels--;
38412 +               else
38413 +                       hcd->available_host_channels++;
38414 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
38415 +       } else
38416 +               update_frame_list(hcd, qh, 0);
38417 +
38418 +       /*
38419 +        * The condition is added to prevent double cleanup try in case of device
38420 +        * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
38421 +        */
38422 +       if (hc->qh) {
38423 +               dwc_otg_hc_cleanup(hcd->core_if, hc);
38424 +               DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
38425 +               hc->qh = NULL;
38426 +       }
38427 +
38428 +       qh->channel = NULL;
38429 +       qh->ntd = 0;
38430 +
38431 +       if (qh->desc_list) {
38432 +               dwc_memset(qh->desc_list, 0x00,
38433 +                          sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
38434 +       }
38435 +       DWC_SPINLOCK_FREE(channel_lock);
38436 +}
38437 +
38438 +/**
38439 + * Initializes a QH structure's Descriptor DMA related members.
38440 + * Allocates memory for descriptor list.
38441 + * On first periodic QH, allocates memory for FrameList
38442 + * and enables periodic scheduling.
38443 + *
38444 + * @param hcd The HCD state structure for the DWC OTG controller.
38445 + * @param qh The QH to init.
38446 + *
38447 + * @return 0 if successful, negative error code otherwise.
38448 + */
38449 +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38450 +{
38451 +       int retval = 0;
38452 +
38453 +       if (qh->do_split) {
38454 +               DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
38455 +               return -1;
38456 +       }
38457 +
38458 +       retval = desc_list_alloc(qh);
38459 +
38460 +       if ((retval == 0)
38461 +           && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
38462 +               if (!hcd->frame_list) {
38463 +                       retval = frame_list_alloc(hcd);
38464 +                       /* Enable periodic schedule on first periodic QH */
38465 +                       if (retval == 0)
38466 +                               per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
38467 +               }
38468 +       }
38469 +
38470 +       qh->ntd = 0;
38471 +
38472 +       return retval;
38473 +}
38474 +
38475 +/**
38476 + * Frees descriptor list memory associated with the QH.
38477 + * If QH is periodic and the last, frees FrameList memory
38478 + * and disables periodic scheduling.
38479 + *
38480 + * @param hcd The HCD state structure for the DWC OTG controller.
38481 + * @param qh The QH to init.
38482 + */
38483 +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38484 +{
38485 +       desc_list_free(qh);
38486 +
38487 +       /*
38488 +        * Channel still assigned due to some reasons.
38489 +        * Seen on Isoc URB dequeue. Channel halted but no subsequent
38490 +        * ChHalted interrupt to release the channel. Afterwards
38491 +        * when it comes here from endpoint disable routine
38492 +        * channel remains assigned.
38493 +        */
38494 +       if (qh->channel)
38495 +               release_channel_ddma(hcd, qh);
38496 +
38497 +       if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)
38498 +           && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {
38499 +
38500 +               per_sched_disable(hcd);
38501 +               frame_list_free(hcd);
38502 +       }
38503 +}
38504 +
38505 +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
38506 +{
38507 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38508 +               /*
38509 +                * Descriptor set(8 descriptors) index
38510 +                * which is 8-aligned.
38511 +                */
38512 +               return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
38513 +       } else {
38514 +               return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
38515 +       }
38516 +}
38517 +
38518 +/*
38519 + * Determine starting frame for Isochronous transfer.
38520 + * Few frames skipped to prevent race condition with HC.
38521 + */
38522 +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38523 +                                  uint8_t * skip_frames)
38524 +{
38525 +       uint16_t frame = 0;
38526 +       hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
38527 +
38528 +       /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
38529 +
38530 +       /*
38531 +        * skip_frames is used to limit activated descriptors number
38532 +        * to avoid the situation when HC services the last activated
38533 +        * descriptor firstly.
38534 +        * Example for FS:
38535 +        * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
38536 +        * corresponding to curr_frame+1, the descriptor corresponding to frame 2
38537 +        * will be fetched. If the number of descriptors is max=64 (or greather) the
38538 +        * list will be fully programmed with Active descriptors and it is possible
38539 +        * case(rare) that the latest descriptor(considering rollback) corresponding
38540 +        * to frame 2 will be serviced first. HS case is more probable because, in fact,
38541 +        * up to 11 uframes(16 in the code) may be skipped.
38542 +        */
38543 +       if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
38544 +               /*
38545 +                * Consider uframe counter also, to start xfer asap.
38546 +                * If half of the frame elapsed skip 2 frames otherwise
38547 +                * just 1 frame.
38548 +                * Starting descriptor index must be 8-aligned, so
38549 +                * if the current frame is near to complete the next one
38550 +                * is skipped as well.
38551 +                */
38552 +
38553 +               if (dwc_micro_frame_num(hcd->frame_number) >= 5) {
38554 +                       *skip_frames = 2 * 8;
38555 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38556 +               } else {
38557 +                       *skip_frames = 1 * 8;
38558 +                       frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
38559 +               }
38560 +
38561 +               frame = dwc_full_frame_num(frame);
38562 +       } else {
38563 +               /*
38564 +                * Two frames are skipped for FS - the current and the next.
38565 +                * But for descriptor programming, 1 frame(descriptor) is enough,
38566 +                * see example above.
38567 +                */
38568 +               *skip_frames = 1;
38569 +               frame = dwc_frame_num_inc(hcd->frame_number, 2);
38570 +       }
38571 +
38572 +       return frame;
38573 +}
38574 +
38575 +/*
38576 + * Calculate initial descriptor index for isochronous transfer
38577 + * based on scheduled frame.
38578 + */
38579 +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38580 +{
38581 +       uint16_t frame = 0, fr_idx, fr_idx_tmp;
38582 +       uint8_t skip_frames = 0;
38583 +       /*
38584 +        * With current ISOC processing algorithm the channel is being
38585 +        * released when no more QTDs in the list(qh->ntd == 0).
38586 +        * Thus this function is called only when qh->ntd == 0 and qh->channel == 0.
38587 +        *
38588 +        * So qh->channel != NULL branch is not used and just not removed from the
38589 +        * source file. It is required for another possible approach which is,
38590 +        * do not disable and release the channel when ISOC session completed,
38591 +        * just move QH to inactive schedule until new QTD arrives.
38592 +        * On new QTD, the QH moved back to 'ready' schedule,
38593 +        * starting frame and therefore starting desc_index are recalculated.
38594 +        * In this case channel is released only on ep_disable.
38595 +        */
38596 +
38597 +       /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
38598 +       if (qh->channel) {
38599 +               frame = calc_starting_frame(hcd, qh, &skip_frames);
38600 +               /*
38601 +                * Calculate initial descriptor index based on FrameList current bitmap
38602 +                * and servicing period.
38603 +                */
38604 +               fr_idx_tmp = frame_list_idx(frame);
38605 +               fr_idx =
38606 +                   (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -
38607 +                    fr_idx_tmp)
38608 +                   % frame_incr_val(qh);
38609 +               fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
38610 +       } else {
38611 +               qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);
38612 +               fr_idx = frame_list_idx(qh->sched_frame);
38613 +       }
38614 +
38615 +       qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);
38616 +
38617 +       return skip_frames;
38618 +}
38619 +
38620 +#define        ISOC_URB_GIVEBACK_ASAP
38621 +
38622 +#define MAX_ISOC_XFER_SIZE_FS 1023
38623 +#define MAX_ISOC_XFER_SIZE_HS 3072
38624 +#define DESCNUM_THRESHOLD 4
38625 +
38626 +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
38627 +                              uint8_t skip_frames)
38628 +{
38629 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
38630 +       dwc_otg_qtd_t *qtd;
38631 +       dwc_otg_host_dma_desc_t *dma_desc;
38632 +       uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
38633 +
38634 +       idx = qh->td_last;
38635 +       inc = qh->interval;
38636 +       n_desc = 0;
38637 +
38638 +       ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
38639 +       if (skip_frames && !qh->channel)
38640 +               ntd_max = ntd_max - skip_frames / qh->interval;
38641 +
38642 +       max_xfer_size =
38643 +           (qh->dev_speed ==
38644 +            DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :
38645 +           MAX_ISOC_XFER_SIZE_FS;
38646 +
38647 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38648 +               while ((qh->ntd < ntd_max)
38649 +                      && (qtd->isoc_frame_index_last <
38650 +                          qtd->urb->packet_count)) {
38651 +
38652 +                       dma_desc = &qh->desc_list[idx];
38653 +                       dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
38654 +
38655 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
38656 +
38657 +                       if (frame_desc->length > max_xfer_size)
38658 +                               qh->n_bytes[idx] = max_xfer_size;
38659 +                       else
38660 +                               qh->n_bytes[idx] = frame_desc->length;
38661 +                       dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
38662 +                       dma_desc->status.b_isoc.a = 1;
38663 +                       dma_desc->status.b_isoc.sts = 0;
38664 +
38665 +                       dma_desc->buf = qtd->urb->dma + frame_desc->offset;
38666 +
38667 +                       qh->ntd++;
38668 +
38669 +                       qtd->isoc_frame_index_last++;
38670 +
38671 +#ifdef ISOC_URB_GIVEBACK_ASAP
38672 +                       /*
38673 +                        * Set IOC for each descriptor corresponding to the
38674 +                        * last frame of the URB.
38675 +                        */
38676 +                       if (qtd->isoc_frame_index_last ==
38677 +                           qtd->urb->packet_count)
38678 +                               dma_desc->status.b_isoc.ioc = 1;
38679 +
38680 +#endif
38681 +                       idx = desclist_idx_inc(idx, inc, qh->dev_speed);
38682 +                       n_desc++;
38683 +
38684 +               }
38685 +               qtd->in_process = 1;
38686 +       }
38687 +
38688 +       qh->td_last = idx;
38689 +
38690 +#ifdef ISOC_URB_GIVEBACK_ASAP
38691 +       /* Set IOC for the last descriptor if descriptor list is full */
38692 +       if (qh->ntd == ntd_max) {
38693 +               idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38694 +               qh->desc_list[idx].status.b_isoc.ioc = 1;
38695 +       }
38696 +#else
38697 +       /*
38698 +        * Set IOC bit only for one descriptor.
38699 +        * Always try to be ahead of HW processing,
38700 +        * i.e. on IOC generation driver activates next descriptors but
38701 +        * core continues to process descriptors followed the one with IOC set.
38702 +        */
38703 +
38704 +       if (n_desc > DESCNUM_THRESHOLD) {
38705 +               /*
38706 +                * Move IOC "up". Required even if there is only one QTD
38707 +                * in the list, cause QTDs migth continue to be queued,
38708 +                * but during the activation it was only one queued.
38709 +                * Actually more than one QTD might be in the list if this function called
38710 +                * from XferCompletion - QTDs was queued during HW processing of the previous
38711 +                * descriptor chunk.
38712 +                */
38713 +               idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
38714 +       } else {
38715 +               /*
38716 +                * Set the IOC for the latest descriptor
38717 +                * if either number of descriptor is not greather than threshold
38718 +                * or no more new descriptors activated.
38719 +                */
38720 +               idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
38721 +       }
38722 +
38723 +       qh->desc_list[idx].status.b_isoc.ioc = 1;
38724 +#endif
38725 +}
38726 +
38727 +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38728 +{
38729 +
38730 +       dwc_hc_t *hc;
38731 +       dwc_otg_host_dma_desc_t *dma_desc;
38732 +       dwc_otg_qtd_t *qtd;
38733 +       int num_packets, len, n_desc = 0;
38734 +
38735 +       hc = qh->channel;
38736 +
38737 +       /*
38738 +        * Start with hc->xfer_buff initialized in
38739 +        * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
38740 +        * this pointer re-assigned to the buffer of the currently processed QTD.
38741 +        * For non-SG request there is always one QTD active.
38742 +        */
38743 +
38744 +       DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
38745 +
38746 +               if (n_desc) {
38747 +                       /* SG request - more than 1 QTDs */
38748 +                       hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
38749 +                       hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
38750 +               }
38751 +
38752 +               qtd->n_desc = 0;
38753 +
38754 +               do {
38755 +                       dma_desc = &qh->desc_list[n_desc];
38756 +                       len = hc->xfer_len;
38757 +
38758 +                       if (len > MAX_DMA_DESC_SIZE)
38759 +                               len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
38760 +
38761 +                       if (hc->ep_is_in) {
38762 +                               if (len > 0) {
38763 +                                       num_packets = (len + hc->max_packet - 1) / hc->max_packet;
38764 +                               } else {
38765 +                                       /* Need 1 packet for transfer length of 0. */
38766 +                                       num_packets = 1;
38767 +                               }
38768 +                               /* Always program an integral # of max packets for IN transfers. */
38769 +                               len = num_packets * hc->max_packet;
38770 +                       }
38771 +
38772 +                       dma_desc->status.b.n_bytes = len;
38773 +
38774 +                       qh->n_bytes[n_desc] = len;
38775 +
38776 +                       if ((qh->ep_type == UE_CONTROL)
38777 +                           && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
38778 +                               dma_desc->status.b.sup = 1;     /* Setup Packet */
38779 +
38780 +                       dma_desc->status.b.a = 1;       /* Active descriptor */
38781 +                       dma_desc->status.b.sts = 0;
38782 +
38783 +                       dma_desc->buf =
38784 +                           ((unsigned long)hc->xfer_buff & 0xffffffff);
38785 +
38786 +                       /*
38787 +                        * Last descriptor(or single) of IN transfer
38788 +                        * with actual size less than MaxPacket.
38789 +                        */
38790 +                       if (len > hc->xfer_len) {
38791 +                               hc->xfer_len = 0;
38792 +                       } else {
38793 +                               hc->xfer_buff += len;
38794 +                               hc->xfer_len -= len;
38795 +                       }
38796 +
38797 +                       qtd->n_desc++;
38798 +                       n_desc++;
38799 +               }
38800 +               while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
38801 +
38802 +
38803 +               qtd->in_process = 1;
38804 +
38805 +               if (qh->ep_type == UE_CONTROL)
38806 +                       break;
38807 +
38808 +               if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
38809 +                       break;
38810 +       }
38811 +
38812 +       if (n_desc) {
38813 +               /* Request Transfer Complete interrupt for the last descriptor */
38814 +               qh->desc_list[n_desc - 1].status.b.ioc = 1;
38815 +               /* End of List indicator */
38816 +               qh->desc_list[n_desc - 1].status.b.eol = 1;
38817 +
38818 +               hc->ntd = n_desc;
38819 +       }
38820 +}
38821 +
38822 +/**
38823 + * For Control and Bulk endpoints initializes descriptor list
38824 + * and starts the transfer.
38825 + *
38826 + * For Interrupt and Isochronous endpoints initializes descriptor list
38827 + * then updates FrameList, marking appropriate entries as active.
38828 + * In case of Isochronous, the starting descriptor index is calculated based
38829 + * on the scheduled frame, but only on the first transfer descriptor within a session.
38830 + * Then starts the transfer via enabling the channel.
38831 + * For Isochronous endpoint the channel is not halted on XferComplete
38832 + * interrupt so remains assigned to the endpoint(QH) until session is done.
38833 + *
38834 + * @param hcd The HCD state structure for the DWC OTG controller.
38835 + * @param qh The QH to init.
38836 + *
38837 + * @return 0 if successful, negative error code otherwise.
38838 + */
38839 +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
38840 +{
38841 +       /* Channel is already assigned */
38842 +       dwc_hc_t *hc = qh->channel;
38843 +       uint8_t skip_frames = 0;
38844 +
38845 +       switch (hc->ep_type) {
38846 +       case DWC_OTG_EP_TYPE_CONTROL:
38847 +       case DWC_OTG_EP_TYPE_BULK:
38848 +               init_non_isoc_dma_desc(hcd, qh);
38849 +
38850 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38851 +               break;
38852 +       case DWC_OTG_EP_TYPE_INTR:
38853 +               init_non_isoc_dma_desc(hcd, qh);
38854 +
38855 +               update_frame_list(hcd, qh, 1);
38856 +
38857 +               dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38858 +               break;
38859 +       case DWC_OTG_EP_TYPE_ISOC:
38860 +
38861 +               if (!qh->ntd)
38862 +                       skip_frames = recalc_initial_desc_idx(hcd, qh);
38863 +
38864 +               init_isoc_dma_desc(hcd, qh, skip_frames);
38865 +
38866 +               if (!hc->xfer_started) {
38867 +
38868 +                       update_frame_list(hcd, qh, 1);
38869 +
38870 +                       /*
38871 +                        * Always set to max, instead of actual size.
38872 +                        * Otherwise ntd will be changed with
38873 +                        * channel being enabled. Not recommended.
38874 +                        *
38875 +                        */
38876 +                       hc->ntd = max_desc_num(qh);
38877 +                       /* Enable channel only once for ISOC */
38878 +                       dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
38879 +               }
38880 +
38881 +               break;
38882 +       default:
38883 +
38884 +               break;
38885 +       }
38886 +}
38887 +
38888 +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
38889 +                                   dwc_hc_t * hc,
38890 +                                   dwc_otg_hc_regs_t * hc_regs,
38891 +                                   dwc_otg_halt_status_e halt_status)
38892 +{
38893 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
38894 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
38895 +       dwc_otg_qh_t *qh;
38896 +       dwc_otg_host_dma_desc_t *dma_desc;
38897 +       uint16_t idx, remain;
38898 +       uint8_t urb_compl;
38899 +
38900 +       qh = hc->qh;
38901 +       idx = qh->td_first;
38902 +
38903 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
38904 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
38905 +                   qtd->in_process = 0;
38906 +               return;
38907 +       } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||
38908 +                  (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
38909 +               /*
38910 +                * Channel is halted in these error cases.
38911 +                * Considered as serious issues.
38912 +                * Complete all URBs marking all frames as failed,
38913 +                * irrespective whether some of the descriptors(frames) succeeded or no.
38914 +                * Pass error code to completion routine as well, to
38915 +                * update urb->status, some of class drivers might use it to stop
38916 +                * queing transfer requests.
38917 +                */
38918 +               int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)
38919 +                   ? (-DWC_E_IO)
38920 +                   : (-DWC_E_OVERFLOW);
38921 +
38922 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
38923 +                       for (idx = 0; idx < qtd->urb->packet_count; idx++) {
38924 +                               frame_desc = &qtd->urb->iso_descs[idx];
38925 +                               frame_desc->status = err;
38926 +                       }
38927 +                       hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
38928 +                       dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
38929 +               }
38930 +               return;
38931 +       }
38932 +
38933 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
38934 +
38935 +               if (!qtd->in_process)
38936 +                       break;
38937 +
38938 +               urb_compl = 0;
38939 +
38940 +               do {
38941 +
38942 +                       dma_desc = &qh->desc_list[idx];
38943 +
38944 +                       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
38945 +                       remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
38946 +
38947 +                       if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
38948 +                               /*
38949 +                                * XactError or, unable to complete all the transactions
38950 +                                * in the scheduled micro-frame/frame,
38951 +                                * both indicated by DMA_DESC_STS_PKTERR.
38952 +                                */
38953 +                               qtd->urb->error_count++;
38954 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
38955 +                               frame_desc->status = -DWC_E_PROTOCOL;
38956 +                       } else {
38957 +                               /* Success */
38958 +
38959 +                               frame_desc->actual_length = qh->n_bytes[idx] - remain;
38960 +                               frame_desc->status = 0;
38961 +                       }
38962 +
38963 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
38964 +                               /*
38965 +                                * urb->status is not used for isoc transfers here.
38966 +                                * The individual frame_desc status are used instead.
38967 +                                */
38968 +
38969 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
38970 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
38971 +
38972 +                               /*
38973 +                                * This check is necessary because urb_dequeue can be called
38974 +                                * from urb complete callback(sound driver example).
38975 +                                * All pending URBs are dequeued there, so no need for
38976 +                                * further processing.
38977 +                                */
38978 +                               if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
38979 +                                       return;
38980 +                               }
38981 +
38982 +                               urb_compl = 1;
38983 +
38984 +                       }
38985 +
38986 +                       qh->ntd--;
38987 +
38988 +                       /* Stop if IOC requested descriptor reached */
38989 +                       if (dma_desc->status.b_isoc.ioc) {
38990 +                               idx = desclist_idx_inc(idx, qh->interval, hc->speed);
38991 +                               goto stop_scan;
38992 +                       }
38993 +
38994 +                       idx = desclist_idx_inc(idx, qh->interval, hc->speed);
38995 +
38996 +                       if (urb_compl)
38997 +                               break;
38998 +               }
38999 +               while (idx != qh->td_first);
39000 +       }
39001 +stop_scan:
39002 +       qh->td_first = idx;
39003 +}
39004 +
39005 +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
39006 +                                      dwc_hc_t * hc,
39007 +                                      dwc_otg_qtd_t * qtd,
39008 +                                      dwc_otg_host_dma_desc_t * dma_desc,
39009 +                                      dwc_otg_halt_status_e halt_status,
39010 +                                      uint32_t n_bytes, uint8_t * xfer_done)
39011 +{
39012 +
39013 +       uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
39014 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
39015 +
39016 +       if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
39017 +               urb->status = -DWC_E_IO;
39018 +               return 1;
39019 +       }
39020 +       if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
39021 +               switch (halt_status) {
39022 +               case DWC_OTG_HC_XFER_STALL:
39023 +                       urb->status = -DWC_E_PIPE;
39024 +                       break;
39025 +               case DWC_OTG_HC_XFER_BABBLE_ERR:
39026 +                       urb->status = -DWC_E_OVERFLOW;
39027 +                       break;
39028 +               case DWC_OTG_HC_XFER_XACT_ERR:
39029 +                       urb->status = -DWC_E_PROTOCOL;
39030 +                       break;
39031 +               default:
39032 +                       DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
39033 +                                 halt_status);
39034 +                       break;
39035 +               }
39036 +               return 1;
39037 +       }
39038 +
39039 +       if (dma_desc->status.b.a == 1) {
39040 +               DWC_DEBUGPL(DBG_HCDV,
39041 +                           "Active descriptor encountered on channel %d\n",
39042 +                           hc->hc_num);
39043 +               return 0;
39044 +       }
39045 +
39046 +       if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
39047 +               if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39048 +                       urb->actual_length += n_bytes - remain;
39049 +                       if (remain || urb->actual_length == urb->length) {
39050 +                               /*
39051 +                                * For Control Data stage do not set urb->status=0 to prevent
39052 +                                * URB callback. Set it when Status phase done. See below.
39053 +                                */
39054 +                               *xfer_done = 1;
39055 +                       }
39056 +
39057 +               } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
39058 +                       urb->status = 0;
39059 +                       *xfer_done = 1;
39060 +               }
39061 +               /* No handling for SETUP stage */
39062 +       } else {
39063 +               /* BULK and INTR */
39064 +               urb->actual_length += n_bytes - remain;
39065 +               if (remain || urb->actual_length == urb->length) {
39066 +                       urb->status = 0;
39067 +                       *xfer_done = 1;
39068 +               }
39069 +       }
39070 +
39071 +       return 0;
39072 +}
39073 +
39074 +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
39075 +                                       dwc_hc_t * hc,
39076 +                                       dwc_otg_hc_regs_t * hc_regs,
39077 +                                       dwc_otg_halt_status_e halt_status)
39078 +{
39079 +       dwc_otg_hcd_urb_t *urb = NULL;
39080 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
39081 +       dwc_otg_qh_t *qh;
39082 +       dwc_otg_host_dma_desc_t *dma_desc;
39083 +       uint32_t n_bytes, n_desc, i;
39084 +       uint8_t failed = 0, xfer_done;
39085 +
39086 +       n_desc = 0;
39087 +
39088 +       qh = hc->qh;
39089 +
39090 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
39091 +               DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
39092 +                       qtd->in_process = 0;
39093 +               }
39094 +               return;
39095 +       }
39096 +
39097 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
39098 +
39099 +               urb = qtd->urb;
39100 +
39101 +               n_bytes = 0;
39102 +               xfer_done = 0;
39103 +
39104 +               for (i = 0; i < qtd->n_desc; i++) {
39105 +                       dma_desc = &qh->desc_list[n_desc];
39106 +
39107 +                       n_bytes = qh->n_bytes[n_desc];
39108 +
39109 +                       failed =
39110 +                           update_non_isoc_urb_state_ddma(hcd, hc, qtd,
39111 +                                                          dma_desc,
39112 +                                                          halt_status, n_bytes,
39113 +                                                          &xfer_done);
39114 +
39115 +                       if (failed
39116 +                           || (xfer_done
39117 +                               && (urb->status != -DWC_E_IN_PROGRESS))) {
39118 +
39119 +                               hcd->fops->complete(hcd, urb->priv, urb,
39120 +                                                   urb->status);
39121 +                               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
39122 +
39123 +                               if (failed)
39124 +                                       goto stop_scan;
39125 +                       } else if (qh->ep_type == UE_CONTROL) {
39126 +                               if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
39127 +                                       if (urb->length > 0) {
39128 +                                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
39129 +                                       } else {
39130 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39131 +                                       }
39132 +                                       DWC_DEBUGPL(DBG_HCDV, "  Control setup transaction done\n");
39133 +                               } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
39134 +                                       if (xfer_done) {
39135 +                                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
39136 +                                               DWC_DEBUGPL(DBG_HCDV, "  Control data transfer done\n");
39137 +                                       } else if (i + 1 == qtd->n_desc) {
39138 +                                               /*
39139 +                                                * Last descriptor for Control data stage which is
39140 +                                                * not completed yet.
39141 +                                                */
39142 +                                               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39143 +                                       }
39144 +                               }
39145 +                       }
39146 +
39147 +                       n_desc++;
39148 +               }
39149 +
39150 +       }
39151 +
39152 +stop_scan:
39153 +
39154 +       if (qh->ep_type != UE_CONTROL) {
39155 +               /*
39156 +                * Resetting the data toggle for bulk
39157 +                * and interrupt endpoints in case of stall. See handle_hc_stall_intr()
39158 +                */
39159 +               if (halt_status == DWC_OTG_HC_XFER_STALL)
39160 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
39161 +               else
39162 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
39163 +       }
39164 +
39165 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39166 +               hcint_data_t hcint;
39167 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
39168 +               if (hcint.b.nyet) {
39169 +                       /*
39170 +                        * Got a NYET on the last transaction of the transfer. It
39171 +                        * means that the endpoint should be in the PING state at the
39172 +                        * beginning of the next transfer.
39173 +                        */
39174 +                       qh->ping_state = 1;
39175 +                       clear_hc_int(hc_regs, nyet);
39176 +               }
39177 +
39178 +       }
39179 +
39180 +}
39181 +
39182 +/**
39183 + * This function is called from interrupt handlers.
39184 + * Scans the descriptor list, updates URB's status and
39185 + * calls completion routine for the URB if it's done.
39186 + * Releases the channel to be used by other transfers.
39187 + * In case of Isochronous endpoint the channel is not halted until
39188 + * the end of the session, i.e. QTD list is empty.
39189 + * If periodic channel released the FrameList is updated accordingly.
39190 + *
39191 + * Calls transaction selection routines to activate pending transfers.
39192 + *
39193 + * @param hcd The HCD state structure for the DWC OTG controller.
39194 + * @param hc Host channel, the transfer is completed on.
39195 + * @param hc_regs Host channel registers.
39196 + * @param halt_status Reason the channel is being halted,
39197 + *                   or just XferComplete for isochronous transfer
39198 + */
39199 +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
39200 +                                   dwc_hc_t * hc,
39201 +                                   dwc_otg_hc_regs_t * hc_regs,
39202 +                                   dwc_otg_halt_status_e halt_status)
39203 +{
39204 +       uint8_t continue_isoc_xfer = 0;
39205 +       dwc_otg_transaction_type_e tr_type;
39206 +       dwc_otg_qh_t *qh = hc->qh;
39207 +
39208 +       if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
39209 +
39210 +               complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39211 +
39212 +               /* Release the channel if halted or session completed */
39213 +               if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
39214 +                   DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39215 +
39216 +                       /* Halt the channel if session completed */
39217 +                       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
39218 +                               dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
39219 +                       }
39220 +
39221 +                       release_channel_ddma(hcd, qh);
39222 +                       dwc_otg_hcd_qh_remove(hcd, qh);
39223 +               } else {
39224 +                       /* Keep in assigned schedule to continue transfer */
39225 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
39226 +                                          &qh->qh_list_entry);
39227 +                       continue_isoc_xfer = 1;
39228 +
39229 +               }
39230 +               /** @todo Consider the case when period exceeds FrameList size.
39231 +                *  Frame Rollover interrupt should be used.
39232 +                */
39233 +       } else {
39234 +               /* Scan descriptor list to complete the URB(s), then release the channel */
39235 +               complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
39236 +
39237 +               release_channel_ddma(hcd, qh);
39238 +               dwc_otg_hcd_qh_remove(hcd, qh);
39239 +
39240 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
39241 +                       /* Add back to inactive non-periodic schedule on normal completion */
39242 +                       dwc_otg_hcd_qh_add(hcd, qh);
39243 +               }
39244 +
39245 +       }
39246 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
39247 +       if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
39248 +               if (continue_isoc_xfer) {
39249 +                       if (tr_type == DWC_OTG_TRANSACTION_NONE) {
39250 +                               tr_type = DWC_OTG_TRANSACTION_PERIODIC;
39251 +                       } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
39252 +                               tr_type = DWC_OTG_TRANSACTION_ALL;
39253 +                       }
39254 +               }
39255 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
39256 +       }
39257 +}
39258 +
39259 +#endif /* DWC_DEVICE_ONLY */
39260 --- /dev/null
39261 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
39262 @@ -0,0 +1,412 @@
39263 +/* ==========================================================================
39264 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
39265 + * $Revision: #12 $
39266 + * $Date: 2011/10/26 $
39267 + * $Change: 1873028 $
39268 + *
39269 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39270 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39271 + * otherwise expressly agreed to in writing between Synopsys and you.
39272 + *
39273 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39274 + * any End User Software License Agreement or Agreement for Licensed Product
39275 + * with Synopsys or any supplement thereto. You are permitted to use and
39276 + * redistribute this Software in source and binary forms, with or without
39277 + * modification, provided that redistributions of source code must retain this
39278 + * notice. You may not view, use, disclose, copy or distribute this file or
39279 + * any information contained herein except pursuant to this license grant from
39280 + * Synopsys. If you do not agree with this notice, including the disclaimer
39281 + * below, then you are not authorized to use the Software.
39282 + *
39283 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39284 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39285 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39286 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39287 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39288 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39289 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39290 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39291 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39292 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39293 + * DAMAGE.
39294 + * ========================================================================== */
39295 +#ifndef DWC_DEVICE_ONLY
39296 +#ifndef __DWC_HCD_IF_H__
39297 +#define __DWC_HCD_IF_H__
39298 +
39299 +#include "dwc_otg_core_if.h"
39300 +
39301 +/** @file
39302 + * This file defines DWC_OTG HCD Core API.
39303 + */
39304 +
39305 +struct dwc_otg_hcd;
39306 +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
39307 +
39308 +struct dwc_otg_hcd_urb;
39309 +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
39310 +
39311 +/** @name HCD Function Driver Callbacks */
39312 +/** @{ */
39313 +
39314 +/** This function is called whenever core switches to host mode. */
39315 +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
39316 +
39317 +/** This function is called when device has been disconnected */
39318 +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
39319 +
39320 +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
39321 +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39322 +                                                  void *urb_handle,
39323 +                                                  uint32_t * hub_addr,
39324 +                                                  uint32_t * port_addr);
39325 +/** Via this function HCD core gets device speed */
39326 +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
39327 +                                               void *urb_handle);
39328 +
39329 +/** This function is called when urb is completed */
39330 +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
39331 +                                             void *urb_handle,
39332 +                                             dwc_otg_hcd_urb_t * dwc_otg_urb,
39333 +                                             int32_t status);
39334 +
39335 +/** Via this function HCD core gets b_hnp_enable parameter */
39336 +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
39337 +
39338 +struct dwc_otg_hcd_function_ops {
39339 +       dwc_otg_hcd_start_cb_t start;
39340 +       dwc_otg_hcd_disconnect_cb_t disconnect;
39341 +       dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
39342 +       dwc_otg_hcd_speed_from_urb_cb_t speed;
39343 +       dwc_otg_hcd_complete_urb_cb_t complete;
39344 +       dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
39345 +};
39346 +/** @} */
39347 +
39348 +/** @name HCD Core API */
39349 +/** @{ */
39350 +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
39351 +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
39352 +
39353 +/** This function should be called to initiate HCD Core.
39354 + *
39355 + * @param hcd The HCD
39356 + * @param core_if The DWC_OTG Core
39357 + *
39358 + * Returns -DWC_E_NO_MEMORY if no enough memory.
39359 + * Returns 0 on success
39360 + */
39361 +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
39362 +
39363 +/** Frees HCD
39364 + *
39365 + * @param hcd The HCD
39366 + */
39367 +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
39368 +
39369 +/** This function should be called on every hardware interrupt.
39370 + *
39371 + * @param dwc_otg_hcd The HCD
39372 + *
39373 + * Returns non zero if interrupt is handled
39374 + * Return 0 if interrupt is not handled
39375 + */
39376 +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
39377 +
39378 +/**
39379 + * Returns private data set by
39380 + * dwc_otg_hcd_set_priv_data function.
39381 + *
39382 + * @param hcd The HCD
39383 + */
39384 +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
39385 +
39386 +/**
39387 + * Set private data.
39388 + *
39389 + * @param hcd The HCD
39390 + * @param priv_data pointer to be stored in private data
39391 + */
39392 +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
39393 +
39394 +/**
39395 + * This function initializes the HCD Core.
39396 + *
39397 + * @param hcd The HCD
39398 + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
39399 + *
39400 + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
39401 + * Returns 0 on success
39402 + */
39403 +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
39404 +                            struct dwc_otg_hcd_function_ops *fops);
39405 +
39406 +/**
39407 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
39408 + * stopped.
39409 + *
39410 + * @param hcd The HCD
39411 + */
39412 +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
39413 +
39414 +/**
39415 + * Handles hub class-specific requests.
39416 + *
39417 + * @param dwc_otg_hcd The HCD
39418 + * @param typeReq Request Type
39419 + * @param wValue wValue from control request
39420 + * @param wIndex wIndex from control request
39421 + * @param buf data buffer
39422 + * @param wLength data buffer length
39423 + *
39424 + * Returns -DWC_E_INVALID if invalid argument is passed
39425 + * Returns 0 on success
39426 + */
39427 +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
39428 +                                  uint16_t typeReq, uint16_t wValue,
39429 +                                  uint16_t wIndex, uint8_t * buf,
39430 +                                  uint16_t wLength);
39431 +
39432 +/**
39433 + * Returns otg port number.
39434 + *
39435 + * @param hcd The HCD
39436 + */
39437 +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
39438 +
39439 +/**
39440 + * Returns OTG version - either 1.3 or 2.0.
39441 + *
39442 + * @param core_if The core_if structure pointer
39443 + */
39444 +extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
39445 +
39446 +/**
39447 + * Returns 1 if currently core is acting as B host, and 0 otherwise.
39448 + *
39449 + * @param hcd The HCD
39450 + */
39451 +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
39452 +
39453 +/**
39454 + * Returns current frame number.
39455 + *
39456 + * @param hcd The HCD
39457 + */
39458 +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
39459 +
39460 +/**
39461 + * Dumps hcd state.
39462 + *
39463 + * @param hcd The HCD
39464 + */
39465 +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
39466 +
39467 +/**
39468 + * Dump the average frame remaining at SOF. This can be used to
39469 + * determine average interrupt latency. Frame remaining is also shown for
39470 + * start transfer and two additional sample points.
39471 + * Currently this function is not implemented.
39472 + *
39473 + * @param hcd The HCD
39474 + */
39475 +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
39476 +
39477 +/**
39478 + * Sends LPM transaction to the local device.
39479 + *
39480 + * @param hcd The HCD
39481 + * @param devaddr Device Address
39482 + * @param hird Host initiated resume duration
39483 + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
39484 + *
39485 + * Returns negative value if sending LPM transaction was not succeeded.
39486 + * Returns 0 on success.
39487 + */
39488 +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
39489 +                               uint8_t hird, uint8_t bRemoteWake);
39490 +
39491 +/* URB interface */
39492 +
39493 +/**
39494 + * Allocates memory for dwc_otg_hcd_urb structure.
39495 + * Allocated memory should be freed by call of DWC_FREE.
39496 + *
39497 + * @param hcd The HCD
39498 + * @param iso_desc_count Count of ISOC descriptors
39499 + * @param atomic_alloc Specefies whether to perform atomic allocation.
39500 + */
39501 +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
39502 +                                               int iso_desc_count,
39503 +                                               int atomic_alloc);
39504 +
39505 +/**
39506 + * Set pipe information in URB.
39507 + *
39508 + * @param hcd_urb DWC_OTG URB
39509 + * @param devaddr Device Address
39510 + * @param ep_num Endpoint Number
39511 + * @param ep_type Endpoint Type
39512 + * @param ep_dir Endpoint Direction
39513 + * @param mps Max Packet Size
39514 + */
39515 +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
39516 +                                        uint8_t devaddr, uint8_t ep_num,
39517 +                                        uint8_t ep_type, uint8_t ep_dir,
39518 +                                        uint16_t mps);
39519 +
39520 +/* Transfer flags */
39521 +#define URB_GIVEBACK_ASAP 0x1
39522 +#define URB_SEND_ZERO_PACKET 0x2
39523 +
39524 +/**
39525 + * Sets dwc_otg_hcd_urb parameters.
39526 + *
39527 + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
39528 + * @param urb_handle Unique handle for request, this will be passed back
39529 + * to function driver in completion callback.
39530 + * @param buf The buffer for the data
39531 + * @param dma The DMA buffer for the data
39532 + * @param buflen Transfer length
39533 + * @param sp Buffer for setup data
39534 + * @param sp_dma DMA address of setup data buffer
39535 + * @param flags Transfer flags
39536 + * @param interval Polling interval for interrupt or isochronous transfers.
39537 + */
39538 +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
39539 +                                      void *urb_handle, void *buf,
39540 +                                      dwc_dma_t dma, uint32_t buflen, void *sp,
39541 +                                      dwc_dma_t sp_dma, uint32_t flags,
39542 +                                      uint16_t interval);
39543 +
39544 +/** Gets status from dwc_otg_hcd_urb
39545 + *
39546 + * @param dwc_otg_urb DWC_OTG URB
39547 + */
39548 +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
39549 +
39550 +/** Gets actual length from dwc_otg_hcd_urb
39551 + *
39552 + * @param dwc_otg_urb DWC_OTG URB
39553 + */
39554 +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
39555 +                                                 dwc_otg_urb);
39556 +
39557 +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
39558 + *
39559 + * @param dwc_otg_urb DWC_OTG URB
39560 + */
39561 +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
39562 +                                               dwc_otg_urb);
39563 +
39564 +/** Set ISOC descriptor offset and length
39565 + *
39566 + * @param dwc_otg_urb DWC_OTG URB
39567 + * @param desc_num ISOC descriptor number
39568 + * @param offset Offset from beginig of buffer.
39569 + * @param length Transaction length
39570 + */
39571 +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
39572 +                                               int desc_num, uint32_t offset,
39573 +                                               uint32_t length);
39574 +
39575 +/** Get status of ISOC descriptor, specified by desc_num
39576 + *
39577 + * @param dwc_otg_urb DWC_OTG URB
39578 + * @param desc_num ISOC descriptor number
39579 + */
39580 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
39581 +                                                   dwc_otg_urb, int desc_num);
39582 +
39583 +/** Get actual length of ISOC descriptor, specified by desc_num
39584 + *
39585 + * @param dwc_otg_urb DWC_OTG URB
39586 + * @param desc_num ISOC descriptor number
39587 + */
39588 +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
39589 +                                                          dwc_otg_urb,
39590 +                                                          int desc_num);
39591 +
39592 +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
39593 + *
39594 + * @param dwc_otg_hcd The HCD
39595 + * @param dwc_otg_urb DWC_OTG URB
39596 + * @param ep_handle Out parameter for returning endpoint handle
39597 + * @param atomic_alloc Flag to do atomic allocation if needed
39598 + *
39599 + * Returns -DWC_E_NO_DEVICE if no device is connected.
39600 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
39601 + * Returns 0 on success.
39602 + */
39603 +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
39604 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb,
39605 +                                  void **ep_handle, int atomic_alloc);
39606 +
39607 +/** De-queue the specified URB
39608 + *
39609 + * @param dwc_otg_hcd The HCD
39610 + * @param dwc_otg_urb DWC_OTG URB
39611 + */
39612 +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
39613 +                                  dwc_otg_hcd_urb_t * dwc_otg_urb);
39614 +
39615 +/** Frees resources in the DWC_otg controller related to a given endpoint.
39616 + * Any URBs for the endpoint must already be dequeued.
39617 + *
39618 + * @param hcd The HCD
39619 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39620 + * @param retry Number of retries if there are queued transfers.
39621 + *
39622 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39623 + * Returns 0 on success
39624 + */
39625 +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
39626 +                                       int retry);
39627 +
39628 +/* Resets the data toggle in qh structure. This function can be called from
39629 + * usb_clear_halt routine.
39630 + *
39631 + * @param hcd The HCD
39632 + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
39633 + *
39634 + * Returns -DWC_E_INVALID if invalid arguments are passed.
39635 + * Returns 0 on success
39636 + */
39637 +extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);
39638 +
39639 +/** Returns 1 if status of specified port is changed and 0 otherwise.
39640 + *
39641 + * @param hcd The HCD
39642 + * @param port Port number
39643 + */
39644 +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
39645 +
39646 +/** Call this function to check if bandwidth was allocated for specified endpoint.
39647 + * Only for ISOC and INTERRUPT endpoints.
39648 + *
39649 + * @param hcd The HCD
39650 + * @param ep_handle Endpoint handle
39651 + */
39652 +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
39653 +                                             void *ep_handle);
39654 +
39655 +/** Call this function to check if bandwidth was freed for specified endpoint.
39656 + *
39657 + * @param hcd The HCD
39658 + * @param ep_handle Endpoint handle
39659 + */
39660 +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
39661 +
39662 +/** Returns bandwidth allocated for specified endpoint in microseconds.
39663 + * Only for ISOC and INTERRUPT endpoints.
39664 + *
39665 + * @param hcd The HCD
39666 + * @param ep_handle Endpoint handle
39667 + */
39668 +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
39669 +                                           void *ep_handle);
39670 +
39671 +/** @} */
39672 +
39673 +#endif /* __DWC_HCD_IF_H__ */
39674 +#endif /* DWC_DEVICE_ONLY */
39675 --- /dev/null
39676 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39677 @@ -0,0 +1,2106 @@
39678 +/* ==========================================================================
39679 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
39680 + * $Revision: #89 $
39681 + * $Date: 2011/10/20 $
39682 + * $Change: 1869487 $
39683 + *
39684 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
39685 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
39686 + * otherwise expressly agreed to in writing between Synopsys and you.
39687 + *
39688 + * The Software IS NOT an item of Licensed Software or Licensed Product under
39689 + * any End User Software License Agreement or Agreement for Licensed Product
39690 + * with Synopsys or any supplement thereto. You are permitted to use and
39691 + * redistribute this Software in source and binary forms, with or without
39692 + * modification, provided that redistributions of source code must retain this
39693 + * notice. You may not view, use, disclose, copy or distribute this file or
39694 + * any information contained herein except pursuant to this license grant from
39695 + * Synopsys. If you do not agree with this notice, including the disclaimer
39696 + * below, then you are not authorized to use the Software.
39697 + *
39698 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
39699 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39700 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39701 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
39702 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39703 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39704 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39705 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39706 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39707 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39708 + * DAMAGE.
39709 + * ========================================================================== */
39710 +#ifndef DWC_DEVICE_ONLY
39711 +
39712 +#include "dwc_otg_hcd.h"
39713 +#include "dwc_otg_regs.h"
39714 +
39715 +extern bool microframe_schedule;
39716 +
39717 +/** @file
39718 + * This file contains the implementation of the HCD Interrupt handlers.
39719 + */
39720 +
39721 +/** This function handles interrupts for the HCD. */
39722 +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39723 +{
39724 +       int retval = 0;
39725 +
39726 +       dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
39727 +       gintsts_data_t gintsts;
39728 +#ifdef DEBUG
39729 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
39730 +
39731 +        //GRAYG: debugging
39732 +        if (NULL == global_regs) {
39733 +                DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
39734 +                            "core_if=%p\n",
39735 +                            dwc_otg_hcd, global_regs);
39736 +                return retval;
39737 +        }
39738 +#endif
39739 +
39740 +       /* Exit from ISR if core is hibernated */
39741 +       if (core_if->hibernation_suspend == 1) {
39742 +               return retval;
39743 +       }
39744 +       DWC_SPINLOCK(dwc_otg_hcd->lock);
39745 +       /* Check if HOST Mode */
39746 +       if (dwc_otg_is_host_mode(core_if)) {
39747 +               gintsts.d32 = dwc_otg_read_core_intr(core_if);
39748 +               if (!gintsts.d32) {
39749 +                       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39750 +                       return 0;
39751 +               }
39752 +#ifdef DEBUG
39753 +               /* Don't print debug message in the interrupt handler on SOF */
39754 +#ifndef DEBUG_SOF
39755 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39756 +#endif
39757 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39758 +#endif
39759 +
39760 +#ifdef DEBUG
39761 +#ifndef DEBUG_SOF
39762 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39763 +#endif
39764 +                       DWC_DEBUGPL(DBG_HCDI,
39765 +                                   "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
39766 +                                   gintsts.d32, core_if);
39767 +#endif
39768 +
39769 +               if (gintsts.b.sofintr) {
39770 +                       retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
39771 +               }
39772 +               if (gintsts.b.rxstsqlvl) {
39773 +                       retval |=
39774 +                           dwc_otg_hcd_handle_rx_status_q_level_intr
39775 +                           (dwc_otg_hcd);
39776 +               }
39777 +               if (gintsts.b.nptxfempty) {
39778 +                       retval |=
39779 +                           dwc_otg_hcd_handle_np_tx_fifo_empty_intr
39780 +                           (dwc_otg_hcd);
39781 +               }
39782 +               if (gintsts.b.i2cintr) {
39783 +                       /** @todo Implement i2cintr handler. */
39784 +               }
39785 +               if (gintsts.b.portintr) {
39786 +                       retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
39787 +               }
39788 +               if (gintsts.b.hcintr) {
39789 +                       retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
39790 +               }
39791 +               if (gintsts.b.ptxfempty) {
39792 +                       retval |=
39793 +                           dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
39794 +                           (dwc_otg_hcd);
39795 +               }
39796 +#ifdef DEBUG
39797 +#ifndef DEBUG_SOF
39798 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39799 +#endif
39800 +               {
39801 +                       DWC_DEBUGPL(DBG_HCDI,
39802 +                                   "DWC OTG HCD Finished Servicing Interrupts\n");
39803 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
39804 +                                   DWC_READ_REG32(&global_regs->gintsts));
39805 +                       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
39806 +                                   DWC_READ_REG32(&global_regs->gintmsk));
39807 +               }
39808 +#endif
39809 +
39810 +#ifdef DEBUG
39811 +#ifndef DEBUG_SOF
39812 +               if (gintsts.d32 != DWC_SOF_INTR_MASK)
39813 +#endif
39814 +                       DWC_DEBUGPL(DBG_HCDI, "\n");
39815 +#endif
39816 +
39817 +       }
39818 +       DWC_SPINUNLOCK(dwc_otg_hcd->lock);
39819 +       return retval;
39820 +}
39821 +
39822 +#ifdef DWC_TRACK_MISSED_SOFS
39823 +#warning Compiling code to track missed SOFs
39824 +#define FRAME_NUM_ARRAY_SIZE 1000
39825 +/**
39826 + * This function is for debug only.
39827 + */
39828 +static inline void track_missed_sofs(uint16_t curr_frame_number)
39829 +{
39830 +       static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
39831 +       static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
39832 +       static int frame_num_idx = 0;
39833 +       static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
39834 +       static int dumped_frame_num_array = 0;
39835 +
39836 +       if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
39837 +               if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
39838 +                   curr_frame_number) {
39839 +                       frame_num_array[frame_num_idx] = curr_frame_number;
39840 +                       last_frame_num_array[frame_num_idx++] = last_frame_num;
39841 +               }
39842 +       } else if (!dumped_frame_num_array) {
39843 +               int i;
39844 +               DWC_PRINTF("Frame     Last Frame\n");
39845 +               DWC_PRINTF("-----     ----------\n");
39846 +               for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
39847 +                       DWC_PRINTF("0x%04x    0x%04x\n",
39848 +                                  frame_num_array[i], last_frame_num_array[i]);
39849 +               }
39850 +               dumped_frame_num_array = 1;
39851 +       }
39852 +       last_frame_num = curr_frame_number;
39853 +}
39854 +#endif
39855 +
39856 +/**
39857 + * Handles the start-of-frame interrupt in host mode. Non-periodic
39858 + * transactions may be queued to the DWC_otg controller for the current
39859 + * (micro)frame. Periodic transactions may be queued to the controller for the
39860 + * next (micro)frame.
39861 + */
39862 +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
39863 +{
39864 +       hfnum_data_t hfnum;
39865 +       dwc_list_link_t *qh_entry;
39866 +       dwc_otg_qh_t *qh;
39867 +       dwc_otg_transaction_type_e tr_type;
39868 +       gintsts_data_t gintsts = {.d32 = 0 };
39869 +
39870 +       hfnum.d32 =
39871 +           DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
39872 +
39873 +#ifdef DEBUG_SOF
39874 +       DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
39875 +#endif
39876 +       hcd->frame_number = hfnum.b.frnum;
39877 +
39878 +#ifdef DEBUG
39879 +       hcd->frrem_accum += hfnum.b.frrem;
39880 +       hcd->frrem_samples++;
39881 +#endif
39882 +
39883 +#ifdef DWC_TRACK_MISSED_SOFS
39884 +       track_missed_sofs(hcd->frame_number);
39885 +#endif
39886 +       /* Determine whether any periodic QHs should be executed. */
39887 +       qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
39888 +       while (qh_entry != &hcd->periodic_sched_inactive) {
39889 +               qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
39890 +               qh_entry = qh_entry->next;
39891 +               if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
39892 +                       /*
39893 +                        * Move QH to the ready list to be executed next
39894 +                        * (micro)frame.
39895 +                        */
39896 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
39897 +                                          &qh->qh_list_entry);
39898 +               }
39899 +       }
39900 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
39901 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
39902 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
39903 +       }
39904 +
39905 +       /* Clear interrupt */
39906 +       gintsts.b.sofintr = 1;
39907 +       DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
39908 +
39909 +       return 1;
39910 +}
39911 +
39912 +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
39913 + * least one packet in the Rx FIFO.  The packets are moved from the FIFO to
39914 + * memory if the DWC_otg controller is operating in Slave mode. */
39915 +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39916 +{
39917 +       host_grxsts_data_t grxsts;
39918 +       dwc_hc_t *hc = NULL;
39919 +
39920 +       DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
39921 +
39922 +       grxsts.d32 =
39923 +           DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
39924 +
39925 +       hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
39926 +       if (!hc) {
39927 +               DWC_ERROR("Unable to get corresponding channel\n");
39928 +               return 0;
39929 +       }
39930 +
39931 +       /* Packet Status */
39932 +       DWC_DEBUGPL(DBG_HCDV, "    Ch num = %d\n", grxsts.b.chnum);
39933 +       DWC_DEBUGPL(DBG_HCDV, "    Count = %d\n", grxsts.b.bcnt);
39934 +       DWC_DEBUGPL(DBG_HCDV, "    DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
39935 +                   hc->data_pid_start);
39936 +       DWC_DEBUGPL(DBG_HCDV, "    PStatus = %d\n", grxsts.b.pktsts);
39937 +
39938 +       switch (grxsts.b.pktsts) {
39939 +       case DWC_GRXSTS_PKTSTS_IN:
39940 +               /* Read the data into the host buffer. */
39941 +               if (grxsts.b.bcnt > 0) {
39942 +                       dwc_otg_read_packet(dwc_otg_hcd->core_if,
39943 +                                           hc->xfer_buff, grxsts.b.bcnt);
39944 +
39945 +                       /* Update the HC fields for the next packet received. */
39946 +                       hc->xfer_count += grxsts.b.bcnt;
39947 +                       hc->xfer_buff += grxsts.b.bcnt;
39948 +               }
39949 +
39950 +       case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
39951 +       case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
39952 +       case DWC_GRXSTS_PKTSTS_CH_HALTED:
39953 +               /* Handled in interrupt, just ignore data */
39954 +               break;
39955 +       default:
39956 +               DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
39957 +                         grxsts.b.pktsts);
39958 +               break;
39959 +       }
39960 +
39961 +       return 1;
39962 +}
39963 +
39964 +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
39965 + * data packets may be written to the FIFO for OUT transfers. More requests
39966 + * may be written to the non-periodic request queue for IN transfers. This
39967 + * interrupt is enabled only in Slave mode. */
39968 +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39969 +{
39970 +       DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
39971 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
39972 +                                      DWC_OTG_TRANSACTION_NON_PERIODIC);
39973 +       return 1;
39974 +}
39975 +
39976 +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
39977 + * packets may be written to the FIFO for OUT transfers. More requests may be
39978 + * written to the periodic request queue for IN transfers. This interrupt is
39979 + * enabled only in Slave mode. */
39980 +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39981 +{
39982 +       DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
39983 +       dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
39984 +                                      DWC_OTG_TRANSACTION_PERIODIC);
39985 +       return 1;
39986 +}
39987 +
39988 +/** There are multiple conditions that can cause a port interrupt. This function
39989 + * determines which interrupt conditions have occurred and handles them
39990 + * appropriately. */
39991 +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
39992 +{
39993 +       int retval = 0;
39994 +       hprt0_data_t hprt0;
39995 +       hprt0_data_t hprt0_modify;
39996 +
39997 +       hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
39998 +       hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
39999 +
40000 +       /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
40001 +        * GINTSTS */
40002 +
40003 +       hprt0_modify.b.prtena = 0;
40004 +       hprt0_modify.b.prtconndet = 0;
40005 +       hprt0_modify.b.prtenchng = 0;
40006 +       hprt0_modify.b.prtovrcurrchng = 0;
40007 +
40008 +       /* Port Connect Detected
40009 +        * Set flag and clear if detected */
40010 +       if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
40011 +               // Dont modify port status if we are in hibernation state
40012 +               hprt0_modify.b.prtconndet = 1;
40013 +               hprt0_modify.b.prtenchng = 1;
40014 +               DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40015 +               hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
40016 +               return retval;
40017 +       }
40018 +
40019 +       if (hprt0.b.prtconndet) {
40020 +               /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
40021 +               if (dwc_otg_hcd->core_if->adp_enable &&
40022 +                               dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
40023 +                       DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
40024 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
40025 +                       dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40026 +                       /* TODO - check if this is required, as
40027 +                        * host initialization was already performed
40028 +                        * after initial ADP probing
40029 +                        */
40030 +                       /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
40031 +                       dwc_otg_core_init(dwc_otg_hcd->core_if);
40032 +                       dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
40033 +                       cil_hcd_start(dwc_otg_hcd->core_if);*/
40034 +               } else {
40035 +
40036 +                       DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
40037 +                                   "Port Connect Detected--\n", hprt0.d32);
40038 +                       dwc_otg_hcd->flags.b.port_connect_status_change = 1;
40039 +                       dwc_otg_hcd->flags.b.port_connect_status = 1;
40040 +                       hprt0_modify.b.prtconndet = 1;
40041 +
40042 +                       /* B-Device has connected, Delete the connection timer. */
40043 +                       DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
40044 +               }
40045 +               /* The Hub driver asserts a reset when it sees port connect
40046 +                * status change flag */
40047 +               retval |= 1;
40048 +       }
40049 +
40050 +       /* Port Enable Changed
40051 +        * Clear if detected - Set internal flag if disabled */
40052 +       if (hprt0.b.prtenchng) {
40053 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40054 +                           "Port Enable Changed--\n", hprt0.d32);
40055 +               hprt0_modify.b.prtenchng = 1;
40056 +               if (hprt0.b.prtena == 1) {
40057 +                       hfir_data_t hfir;
40058 +                       int do_reset = 0;
40059 +                       dwc_otg_core_params_t *params =
40060 +                           dwc_otg_hcd->core_if->core_params;
40061 +                       dwc_otg_core_global_regs_t *global_regs =
40062 +                           dwc_otg_hcd->core_if->core_global_regs;
40063 +                       dwc_otg_host_if_t *host_if =
40064 +                           dwc_otg_hcd->core_if->host_if;
40065 +
40066 +                       /* Every time when port enables calculate
40067 +                        * HFIR.FrInterval
40068 +                        */
40069 +                       hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
40070 +                       hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
40071 +                       DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
40072 +
40073 +                       /* Check if we need to adjust the PHY clock speed for
40074 +                        * low power and adjust it */
40075 +                       if (params->host_support_fs_ls_low_power) {
40076 +                               gusbcfg_data_t usbcfg;
40077 +
40078 +                               usbcfg.d32 =
40079 +                                   DWC_READ_REG32(&global_regs->gusbcfg);
40080 +
40081 +                               if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
40082 +                                   || hprt0.b.prtspd ==
40083 +                                   DWC_HPRT0_PRTSPD_FULL_SPEED) {
40084 +                                       /*
40085 +                                        * Low power
40086 +                                        */
40087 +                                       hcfg_data_t hcfg;
40088 +                                       if (usbcfg.b.phylpwrclksel == 0) {
40089 +                                               /* Set PHY low power clock select for FS/LS devices */
40090 +                                               usbcfg.b.phylpwrclksel = 1;
40091 +                                               DWC_WRITE_REG32
40092 +                                                   (&global_regs->gusbcfg,
40093 +                                                    usbcfg.d32);
40094 +                                               do_reset = 1;
40095 +                                       }
40096 +
40097 +                                       hcfg.d32 =
40098 +                                           DWC_READ_REG32
40099 +                                           (&host_if->host_global_regs->hcfg);
40100 +
40101 +                                       if (hprt0.b.prtspd ==
40102 +                                           DWC_HPRT0_PRTSPD_LOW_SPEED
40103 +                                           && params->host_ls_low_power_phy_clk
40104 +                                           ==
40105 +                                           DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
40106 +                                       {
40107 +                                               /* 6 MHZ */
40108 +                                               DWC_DEBUGPL(DBG_CIL,
40109 +                                                           "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
40110 +                                               if (hcfg.b.fslspclksel !=
40111 +                                                   DWC_HCFG_6_MHZ) {
40112 +                                                       hcfg.b.fslspclksel =
40113 +                                                           DWC_HCFG_6_MHZ;
40114 +                                                       DWC_WRITE_REG32
40115 +                                                           (&host_if->host_global_regs->hcfg,
40116 +                                                            hcfg.d32);
40117 +                                                       do_reset = 1;
40118 +                                               }
40119 +                                       } else {
40120 +                                               /* 48 MHZ */
40121 +                                               DWC_DEBUGPL(DBG_CIL,
40122 +                                                           "FS_PHY programming HCFG to 48 MHz ()\n");
40123 +                                               if (hcfg.b.fslspclksel !=
40124 +                                                   DWC_HCFG_48_MHZ) {
40125 +                                                       hcfg.b.fslspclksel =
40126 +                                                           DWC_HCFG_48_MHZ;
40127 +                                                       DWC_WRITE_REG32
40128 +                                                           (&host_if->host_global_regs->hcfg,
40129 +                                                            hcfg.d32);
40130 +                                                       do_reset = 1;
40131 +                                               }
40132 +                                       }
40133 +                               } else {
40134 +                                       /*
40135 +                                        * Not low power
40136 +                                        */
40137 +                                       if (usbcfg.b.phylpwrclksel == 1) {
40138 +                                               usbcfg.b.phylpwrclksel = 0;
40139 +                                               DWC_WRITE_REG32
40140 +                                                   (&global_regs->gusbcfg,
40141 +                                                    usbcfg.d32);
40142 +                                               do_reset = 1;
40143 +                                       }
40144 +                               }
40145 +
40146 +                               if (do_reset) {
40147 +                                       DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
40148 +                               }
40149 +                       }
40150 +
40151 +                       if (!do_reset) {
40152 +                               /* Port has been enabled set the reset change flag */
40153 +                               dwc_otg_hcd->flags.b.port_reset_change = 1;
40154 +                       }
40155 +               } else {
40156 +                       dwc_otg_hcd->flags.b.port_enable_change = 1;
40157 +               }
40158 +               retval |= 1;
40159 +       }
40160 +
40161 +       /** Overcurrent Change Interrupt */
40162 +       if (hprt0.b.prtovrcurrchng) {
40163 +               DWC_DEBUGPL(DBG_HCD, "  --Port Interrupt HPRT0=0x%08x "
40164 +                           "Port Overcurrent Changed--\n", hprt0.d32);
40165 +               dwc_otg_hcd->flags.b.port_over_current_change = 1;
40166 +               hprt0_modify.b.prtovrcurrchng = 1;
40167 +               retval |= 1;
40168 +       }
40169 +
40170 +       /* Clear Port Interrupts */
40171 +       DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
40172 +
40173 +       return retval;
40174 +}
40175 +
40176 +/** This interrupt indicates that one or more host channels has a pending
40177 + * interrupt. There are multiple conditions that can cause each host channel
40178 + * interrupt. This function determines which conditions have occurred for each
40179 + * host channel interrupt and handles them appropriately. */
40180 +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
40181 +{
40182 +       int i;
40183 +       int retval = 0;
40184 +       haint_data_t haint;
40185 +
40186 +       /* Clear appropriate bits in HCINTn to clear the interrupt bit in
40187 +        * GINTSTS */
40188 +
40189 +       haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
40190 +
40191 +       for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
40192 +               if (haint.b2.chint & (1 << i)) {
40193 +                       retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
40194 +               }
40195 +       }
40196 +
40197 +       return retval;
40198 +}
40199 +
40200 +/**
40201 + * Gets the actual length of a transfer after the transfer halts. _halt_status
40202 + * holds the reason for the halt.
40203 + *
40204 + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
40205 + * *short_read is set to 1 upon return if less than the requested
40206 + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
40207 + * return. short_read may also be NULL on entry, in which case it remains
40208 + * unchanged.
40209 + */
40210 +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
40211 +                                      dwc_otg_hc_regs_t * hc_regs,
40212 +                                      dwc_otg_qtd_t * qtd,
40213 +                                      dwc_otg_halt_status_e halt_status,
40214 +                                      int *short_read)
40215 +{
40216 +       hctsiz_data_t hctsiz;
40217 +       uint32_t length;
40218 +
40219 +       if (short_read != NULL) {
40220 +               *short_read = 0;
40221 +       }
40222 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40223 +
40224 +       if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
40225 +               if (hc->ep_is_in) {
40226 +                       length = hc->xfer_len - hctsiz.b.xfersize;
40227 +                       if (short_read != NULL) {
40228 +                               *short_read = (hctsiz.b.xfersize != 0);
40229 +                       }
40230 +               } else if (hc->qh->do_split) {
40231 +                       length = qtd->ssplit_out_xfer_count;
40232 +               } else {
40233 +                       length = hc->xfer_len;
40234 +               }
40235 +       } else {
40236 +               /*
40237 +                * Must use the hctsiz.pktcnt field to determine how much data
40238 +                * has been transferred. This field reflects the number of
40239 +                * packets that have been transferred via the USB. This is
40240 +                * always an integral number of packets if the transfer was
40241 +                * halted before its normal completion. (Can't use the
40242 +                * hctsiz.xfersize field because that reflects the number of
40243 +                * bytes transferred via the AHB, not the USB).
40244 +                */
40245 +               length =
40246 +                   (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
40247 +       }
40248 +
40249 +       return length;
40250 +}
40251 +
40252 +/**
40253 + * Updates the state of the URB after a Transfer Complete interrupt on the
40254 + * host channel. Updates the actual_length field of the URB based on the
40255 + * number of bytes transferred via the host channel. Sets the URB status
40256 + * if the data transfer is finished.
40257 + *
40258 + * @return 1 if the data transfer specified by the URB is completely finished,
40259 + * 0 otherwise.
40260 + */
40261 +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
40262 +                                     dwc_otg_hc_regs_t * hc_regs,
40263 +                                     dwc_otg_hcd_urb_t * urb,
40264 +                                     dwc_otg_qtd_t * qtd)
40265 +{
40266 +       int xfer_done = 0;
40267 +       int short_read = 0;
40268 +
40269 +       int xfer_length;
40270 +
40271 +       xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
40272 +                                            DWC_OTG_HC_XFER_COMPLETE,
40273 +                                            &short_read);
40274 +
40275 +
40276 +       /* non DWORD-aligned buffer case handling. */
40277 +       if (hc->align_buff && xfer_length && hc->ep_is_in) {
40278 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40279 +                          xfer_length);
40280 +       }
40281 +
40282 +       urb->actual_length += xfer_length;
40283 +
40284 +       if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
40285 +           (urb->flags & URB_SEND_ZERO_PACKET)
40286 +           && (urb->actual_length == urb->length)
40287 +           && !(urb->length % hc->max_packet)) {
40288 +               xfer_done = 0;
40289 +       } else if (short_read || urb->actual_length >= urb->length) {
40290 +               xfer_done = 1;
40291 +               urb->status = 0;
40292 +       }
40293 +
40294 +#ifdef DEBUG
40295 +       {
40296 +               hctsiz_data_t hctsiz;
40297 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40298 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40299 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
40300 +                           hc->hc_num);
40301 +               DWC_DEBUGPL(DBG_HCDV, "  hc->xfer_len %d\n", hc->xfer_len);
40302 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.xfersize %d\n",
40303 +                           hctsiz.b.xfersize);
40304 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
40305 +                           urb->length);
40306 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
40307 +                           urb->actual_length);
40308 +               DWC_DEBUGPL(DBG_HCDV, "  short_read %d, xfer_done %d\n",
40309 +                           short_read, xfer_done);
40310 +       }
40311 +#endif
40312 +
40313 +       return xfer_done;
40314 +}
40315 +
40316 +/*
40317 + * Save the starting data toggle for the next transfer. The data toggle is
40318 + * saved in the QH for non-control transfers and it's saved in the QTD for
40319 + * control transfers.
40320 + */
40321 +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
40322 +                            dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
40323 +{
40324 +       hctsiz_data_t hctsiz;
40325 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40326 +
40327 +       if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
40328 +               dwc_otg_qh_t *qh = hc->qh;
40329 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40330 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
40331 +               } else {
40332 +                       qh->data_toggle = DWC_OTG_HC_PID_DATA1;
40333 +               }
40334 +       } else {
40335 +               if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
40336 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
40337 +               } else {
40338 +                       qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
40339 +               }
40340 +       }
40341 +}
40342 +
40343 +/**
40344 + * Updates the state of an Isochronous URB when the transfer is stopped for
40345 + * any reason. The fields of the current entry in the frame descriptor array
40346 + * are set based on the transfer state and the input _halt_status. Completes
40347 + * the Isochronous URB if all the URB frames have been completed.
40348 + *
40349 + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
40350 + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
40351 + */
40352 +static dwc_otg_halt_status_e
40353 +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
40354 +                     dwc_hc_t * hc,
40355 +                     dwc_otg_hc_regs_t * hc_regs,
40356 +                     dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40357 +{
40358 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40359 +       dwc_otg_halt_status_e ret_val = halt_status;
40360 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40361 +
40362 +       frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
40363 +       switch (halt_status) {
40364 +       case DWC_OTG_HC_XFER_COMPLETE:
40365 +               frame_desc->status = 0;
40366 +               frame_desc->actual_length =
40367 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40368 +
40369 +               /* non DWORD-aligned buffer case handling. */
40370 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40371 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40372 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40373 +               }
40374 +
40375 +               break;
40376 +       case DWC_OTG_HC_XFER_FRAME_OVERRUN:
40377 +               urb->error_count++;
40378 +               if (hc->ep_is_in) {
40379 +                       frame_desc->status = -DWC_E_NO_STREAM_RES;
40380 +               } else {
40381 +                       frame_desc->status = -DWC_E_COMMUNICATION;
40382 +               }
40383 +               frame_desc->actual_length = 0;
40384 +               break;
40385 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40386 +               urb->error_count++;
40387 +               frame_desc->status = -DWC_E_OVERFLOW;
40388 +               /* Don't need to update actual_length in this case. */
40389 +               break;
40390 +       case DWC_OTG_HC_XFER_XACT_ERR:
40391 +               urb->error_count++;
40392 +               frame_desc->status = -DWC_E_PROTOCOL;
40393 +               frame_desc->actual_length =
40394 +                   get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
40395 +
40396 +               /* non DWORD-aligned buffer case handling. */
40397 +               if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
40398 +                       dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
40399 +                                  hc->qh->dw_align_buf, frame_desc->actual_length);
40400 +               }
40401 +               /* Skip whole frame */
40402 +               if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
40403 +                   hc->ep_is_in && hcd->core_if->dma_enable) {
40404 +                       qtd->complete_split = 0;
40405 +                       qtd->isoc_split_offset = 0;
40406 +               }
40407 +
40408 +               break;
40409 +       default:
40410 +               DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
40411 +               break;
40412 +       }
40413 +       if (++qtd->isoc_frame_index == urb->packet_count) {
40414 +               /*
40415 +                * urb->status is not used for isoc transfers.
40416 +                * The individual frame_desc statuses are used instead.
40417 +                */
40418 +               hcd->fops->complete(hcd, urb->priv, urb, 0);
40419 +               ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
40420 +       } else {
40421 +               ret_val = DWC_OTG_HC_XFER_COMPLETE;
40422 +       }
40423 +       return ret_val;
40424 +}
40425 +
40426 +/**
40427 + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
40428 + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
40429 + * still linked to the QH, the QH is added to the end of the inactive
40430 + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
40431 + * schedule if no more QTDs are linked to the QH.
40432 + */
40433 +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
40434 +{
40435 +       int continue_split = 0;
40436 +       dwc_otg_qtd_t *qtd;
40437 +
40438 +       DWC_DEBUGPL(DBG_HCDV, "  %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
40439 +
40440 +       qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
40441 +
40442 +       if (qtd->complete_split) {
40443 +               continue_split = 1;
40444 +       } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
40445 +                  qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
40446 +               continue_split = 1;
40447 +       }
40448 +
40449 +       if (free_qtd) {
40450 +               dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
40451 +               continue_split = 0;
40452 +       }
40453 +
40454 +       qh->channel = NULL;
40455 +       dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
40456 +}
40457 +
40458 +/**
40459 + * Releases a host channel for use by other transfers. Attempts to select and
40460 + * queue more transactions since at least one host channel is available.
40461 + *
40462 + * @param hcd The HCD state structure.
40463 + * @param hc The host channel to release.
40464 + * @param qtd The QTD associated with the host channel. This QTD may be freed
40465 + * if the transfer is complete or an error has occurred.
40466 + * @param halt_status Reason the channel is being released. This status
40467 + * determines the actions taken by this function.
40468 + */
40469 +static void release_channel(dwc_otg_hcd_t * hcd,
40470 +                           dwc_hc_t * hc,
40471 +                           dwc_otg_qtd_t * qtd,
40472 +                           dwc_otg_halt_status_e halt_status)
40473 +{
40474 +       dwc_otg_transaction_type_e tr_type;
40475 +       int free_qtd;
40476 +       dwc_irqflags_t flags;
40477 +       dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
40478 +
40479 +       DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d, xfer_len %d\n",
40480 +                   __func__, hc->hc_num, halt_status, hc->xfer_len);
40481 +
40482 +       switch (halt_status) {
40483 +       case DWC_OTG_HC_XFER_URB_COMPLETE:
40484 +               free_qtd = 1;
40485 +               break;
40486 +       case DWC_OTG_HC_XFER_AHB_ERR:
40487 +       case DWC_OTG_HC_XFER_STALL:
40488 +       case DWC_OTG_HC_XFER_BABBLE_ERR:
40489 +               free_qtd = 1;
40490 +               break;
40491 +       case DWC_OTG_HC_XFER_XACT_ERR:
40492 +               if (qtd->error_count >= 3) {
40493 +                       DWC_DEBUGPL(DBG_HCDV,
40494 +                                   "  Complete URB with transaction error\n");
40495 +                       free_qtd = 1;
40496 +                       qtd->urb->status = -DWC_E_PROTOCOL;
40497 +                       hcd->fops->complete(hcd, qtd->urb->priv,
40498 +                                           qtd->urb, -DWC_E_PROTOCOL);
40499 +               } else {
40500 +                       free_qtd = 0;
40501 +               }
40502 +               break;
40503 +       case DWC_OTG_HC_XFER_URB_DEQUEUE:
40504 +               /*
40505 +                * The QTD has already been removed and the QH has been
40506 +                * deactivated. Don't want to do anything except release the
40507 +                * host channel and try to queue more transfers.
40508 +                */
40509 +               goto cleanup;
40510 +       case DWC_OTG_HC_XFER_NO_HALT_STATUS:
40511 +               free_qtd = 0;
40512 +               break;
40513 +       case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
40514 +               DWC_DEBUGPL(DBG_HCDV,
40515 +                       "  Complete URB with I/O error\n");
40516 +               free_qtd = 1;
40517 +               qtd->urb->status = -DWC_E_IO;
40518 +               hcd->fops->complete(hcd, qtd->urb->priv,
40519 +                       qtd->urb, -DWC_E_IO);
40520 +               break;
40521 +       default:
40522 +               free_qtd = 0;
40523 +               break;
40524 +       }
40525 +
40526 +       deactivate_qh(hcd, hc->qh, free_qtd);
40527 +
40528 +cleanup:
40529 +       /*
40530 +        * Release the host channel for use by other transfers. The cleanup
40531 +        * function clears the channel interrupt enables and conditions, so
40532 +        * there's no need to clear the Channel Halted interrupt separately.
40533 +        */
40534 +       dwc_otg_hc_cleanup(hcd->core_if, hc);
40535 +       DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
40536 +
40537 +       if (!microframe_schedule) {
40538 +               switch (hc->ep_type) {
40539 +               case DWC_OTG_EP_TYPE_CONTROL:
40540 +               case DWC_OTG_EP_TYPE_BULK:
40541 +                       hcd->non_periodic_channels--;
40542 +                       break;
40543 +
40544 +               default:
40545 +                       /*
40546 +                        * Don't release reservations for periodic channels here.
40547 +                        * That's done when a periodic transfer is descheduled (i.e.
40548 +                        * when the QH is removed from the periodic schedule).
40549 +                        */
40550 +                       break;
40551 +               }
40552 +       } else {
40553 +
40554 +               DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
40555 +               hcd->available_host_channels++;
40556 +               DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
40557 +       }
40558 +
40559 +       /* Try to queue more transfers now that there's a free channel. */
40560 +       tr_type = dwc_otg_hcd_select_transactions(hcd);
40561 +       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
40562 +               dwc_otg_hcd_queue_transactions(hcd, tr_type);
40563 +       }
40564 +       DWC_SPINLOCK_FREE(channel_lock);
40565 +}
40566 +
40567 +/**
40568 + * Halts a host channel. If the channel cannot be halted immediately because
40569 + * the request queue is full, this function ensures that the FIFO empty
40570 + * interrupt for the appropriate queue is enabled so that the halt request can
40571 + * be queued when there is space in the request queue.
40572 + *
40573 + * This function may also be called in DMA mode. In that case, the channel is
40574 + * simply released since the core always halts the channel automatically in
40575 + * DMA mode.
40576 + */
40577 +static void halt_channel(dwc_otg_hcd_t * hcd,
40578 +                        dwc_hc_t * hc,
40579 +                        dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
40580 +{
40581 +       if (hcd->core_if->dma_enable) {
40582 +               release_channel(hcd, hc, qtd, halt_status);
40583 +               return;
40584 +       }
40585 +
40586 +       /* Slave mode processing... */
40587 +       dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
40588 +
40589 +       if (hc->halt_on_queue) {
40590 +               gintmsk_data_t gintmsk = {.d32 = 0 };
40591 +               dwc_otg_core_global_regs_t *global_regs;
40592 +               global_regs = hcd->core_if->core_global_regs;
40593 +
40594 +               if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
40595 +                   hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
40596 +                       /*
40597 +                        * Make sure the Non-periodic Tx FIFO empty interrupt
40598 +                        * is enabled so that the non-periodic schedule will
40599 +                        * be processed.
40600 +                        */
40601 +                       gintmsk.b.nptxfempty = 1;
40602 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40603 +               } else {
40604 +                       /*
40605 +                        * Move the QH from the periodic queued schedule to
40606 +                        * the periodic assigned schedule. This allows the
40607 +                        * halt to be queued when the periodic schedule is
40608 +                        * processed.
40609 +                        */
40610 +                       DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
40611 +                                          &hc->qh->qh_list_entry);
40612 +
40613 +                       /*
40614 +                        * Make sure the Periodic Tx FIFO Empty interrupt is
40615 +                        * enabled so that the periodic schedule will be
40616 +                        * processed.
40617 +                        */
40618 +                       gintmsk.b.ptxfempty = 1;
40619 +                       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
40620 +               }
40621 +       }
40622 +}
40623 +
40624 +/**
40625 + * Performs common cleanup for non-periodic transfers after a Transfer
40626 + * Complete interrupt. This function should be called after any endpoint type
40627 + * specific handling is finished to release the host channel.
40628 + */
40629 +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
40630 +                                      dwc_hc_t * hc,
40631 +                                      dwc_otg_hc_regs_t * hc_regs,
40632 +                                      dwc_otg_qtd_t * qtd,
40633 +                                      dwc_otg_halt_status_e halt_status)
40634 +{
40635 +       hcint_data_t hcint;
40636 +
40637 +       qtd->error_count = 0;
40638 +
40639 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
40640 +       if (hcint.b.nyet) {
40641 +               /*
40642 +                * Got a NYET on the last transaction of the transfer. This
40643 +                * means that the endpoint should be in the PING state at the
40644 +                * beginning of the next transfer.
40645 +                */
40646 +               hc->qh->ping_state = 1;
40647 +               clear_hc_int(hc_regs, nyet);
40648 +       }
40649 +
40650 +       /*
40651 +        * Always halt and release the host channel to make it available for
40652 +        * more transfers. There may still be more phases for a control
40653 +        * transfer or more data packets for a bulk transfer at this point,
40654 +        * but the host channel is still halted. A channel will be reassigned
40655 +        * to the transfer when the non-periodic schedule is processed after
40656 +        * the channel is released. This allows transactions to be queued
40657 +        * properly via dwc_otg_hcd_queue_transactions, which also enables the
40658 +        * Tx FIFO Empty interrupt if necessary.
40659 +        */
40660 +       if (hc->ep_is_in) {
40661 +               /*
40662 +                * IN transfers in Slave mode require an explicit disable to
40663 +                * halt the channel. (In DMA mode, this call simply releases
40664 +                * the channel.)
40665 +                */
40666 +               halt_channel(hcd, hc, qtd, halt_status);
40667 +       } else {
40668 +               /*
40669 +                * The channel is automatically disabled by the core for OUT
40670 +                * transfers in Slave mode.
40671 +                */
40672 +               release_channel(hcd, hc, qtd, halt_status);
40673 +       }
40674 +}
40675 +
40676 +/**
40677 + * Performs common cleanup for periodic transfers after a Transfer Complete
40678 + * interrupt. This function should be called after any endpoint type specific
40679 + * handling is finished to release the host channel.
40680 + */
40681 +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
40682 +                                  dwc_hc_t * hc,
40683 +                                  dwc_otg_hc_regs_t * hc_regs,
40684 +                                  dwc_otg_qtd_t * qtd,
40685 +                                  dwc_otg_halt_status_e halt_status)
40686 +{
40687 +       hctsiz_data_t hctsiz;
40688 +       qtd->error_count = 0;
40689 +
40690 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40691 +       if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
40692 +               /* Core halts channel in these cases. */
40693 +               release_channel(hcd, hc, qtd, halt_status);
40694 +       } else {
40695 +               /* Flush any outstanding requests from the Tx queue. */
40696 +               halt_channel(hcd, hc, qtd, halt_status);
40697 +       }
40698 +}
40699 +
40700 +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
40701 +                                            dwc_hc_t * hc,
40702 +                                            dwc_otg_hc_regs_t * hc_regs,
40703 +                                            dwc_otg_qtd_t * qtd)
40704 +{
40705 +       uint32_t len;
40706 +       struct dwc_otg_hcd_iso_packet_desc *frame_desc;
40707 +       frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
40708 +
40709 +       len = get_actual_xfer_length(hc, hc_regs, qtd,
40710 +                                    DWC_OTG_HC_XFER_COMPLETE, NULL);
40711 +
40712 +       if (!len) {
40713 +               qtd->complete_split = 0;
40714 +               qtd->isoc_split_offset = 0;
40715 +               return 0;
40716 +       }
40717 +       frame_desc->actual_length += len;
40718 +
40719 +       if (hc->align_buff && len)
40720 +               dwc_memcpy(qtd->urb->buf + frame_desc->offset +
40721 +                          qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
40722 +       qtd->isoc_split_offset += len;
40723 +
40724 +       if (frame_desc->length == frame_desc->actual_length) {
40725 +               frame_desc->status = 0;
40726 +               qtd->isoc_frame_index++;
40727 +               qtd->complete_split = 0;
40728 +               qtd->isoc_split_offset = 0;
40729 +       }
40730 +
40731 +       if (qtd->isoc_frame_index == qtd->urb->packet_count) {
40732 +               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
40733 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
40734 +       } else {
40735 +               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
40736 +       }
40737 +
40738 +       return 1;               /* Indicates that channel released */
40739 +}
40740 +
40741 +/**
40742 + * Handles a host channel Transfer Complete interrupt. This handler may be
40743 + * called in either DMA mode or Slave mode.
40744 + */
40745 +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
40746 +                                      dwc_hc_t * hc,
40747 +                                      dwc_otg_hc_regs_t * hc_regs,
40748 +                                      dwc_otg_qtd_t * qtd)
40749 +{
40750 +       int urb_xfer_done;
40751 +       dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
40752 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40753 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40754 +
40755 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40756 +                   "Transfer Complete--\n", hc->hc_num);
40757 +
40758 +       if (hcd->core_if->dma_desc_enable) {
40759 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
40760 +               if (pipe_type == UE_ISOCHRONOUS) {
40761 +                       /* Do not disable the interrupt, just clear it */
40762 +                       clear_hc_int(hc_regs, xfercomp);
40763 +                       return 1;
40764 +               }
40765 +               goto handle_xfercomp_done;
40766 +       }
40767 +
40768 +       /*
40769 +        * Handle xfer complete on CSPLIT.
40770 +        */
40771 +
40772 +       if (hc->qh->do_split) {
40773 +               if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
40774 +                   && hcd->core_if->dma_enable) {
40775 +                       if (qtd->complete_split
40776 +                           && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
40777 +                                                            qtd))
40778 +                               goto handle_xfercomp_done;
40779 +               } else {
40780 +                       qtd->complete_split = 0;
40781 +               }
40782 +       }
40783 +
40784 +       /* Update the QTD and URB states. */
40785 +       switch (pipe_type) {
40786 +       case UE_CONTROL:
40787 +               switch (qtd->control_phase) {
40788 +               case DWC_OTG_CONTROL_SETUP:
40789 +                       if (urb->length > 0) {
40790 +                               qtd->control_phase = DWC_OTG_CONTROL_DATA;
40791 +                       } else {
40792 +                               qtd->control_phase = DWC_OTG_CONTROL_STATUS;
40793 +                       }
40794 +                       DWC_DEBUGPL(DBG_HCDV,
40795 +                                   "  Control setup transaction done\n");
40796 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40797 +                       break;
40798 +               case DWC_OTG_CONTROL_DATA:{
40799 +                               urb_xfer_done =
40800 +                                   update_urb_state_xfer_comp(hc, hc_regs, urb,
40801 +                                                              qtd);
40802 +                               if (urb_xfer_done) {
40803 +                                       qtd->control_phase =
40804 +                                           DWC_OTG_CONTROL_STATUS;
40805 +                                       DWC_DEBUGPL(DBG_HCDV,
40806 +                                                   "  Control data transfer done\n");
40807 +                               } else {
40808 +                                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40809 +                               }
40810 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40811 +                               break;
40812 +                       }
40813 +               case DWC_OTG_CONTROL_STATUS:
40814 +                       DWC_DEBUGPL(DBG_HCDV, "  Control transfer complete\n");
40815 +                       if (urb->status == -DWC_E_IN_PROGRESS) {
40816 +                               urb->status = 0;
40817 +                       }
40818 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40819 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40820 +                       break;
40821 +               }
40822 +
40823 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40824 +               break;
40825 +       case UE_BULK:
40826 +               DWC_DEBUGPL(DBG_HCDV, "  Bulk transfer complete\n");
40827 +               urb_xfer_done =
40828 +                   update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40829 +               if (urb_xfer_done) {
40830 +                       hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40831 +                       halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40832 +               } else {
40833 +                       halt_status = DWC_OTG_HC_XFER_COMPLETE;
40834 +               }
40835 +
40836 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40837 +               complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40838 +               break;
40839 +       case UE_INTERRUPT:
40840 +               DWC_DEBUGPL(DBG_HCDV, "  Interrupt transfer complete\n");
40841 +               urb_xfer_done =
40842 +                       update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
40843 +
40844 +               /*
40845 +                * Interrupt URB is done on the first transfer complete
40846 +                * interrupt.
40847 +                */
40848 +               if (urb_xfer_done) {
40849 +                               hcd->fops->complete(hcd, urb->priv, urb, urb->status);
40850 +                               halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
40851 +               } else {
40852 +                               halt_status = DWC_OTG_HC_XFER_COMPLETE;
40853 +               }
40854 +
40855 +               dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
40856 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40857 +               break;
40858 +       case UE_ISOCHRONOUS:
40859 +               DWC_DEBUGPL(DBG_HCDV, "  Isochronous transfer complete\n");
40860 +               if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
40861 +                       halt_status =
40862 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
40863 +                                                 DWC_OTG_HC_XFER_COMPLETE);
40864 +               }
40865 +               complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
40866 +               break;
40867 +       }
40868 +
40869 +handle_xfercomp_done:
40870 +       disable_hc_int(hc_regs, xfercompl);
40871 +
40872 +       return 1;
40873 +}
40874 +
40875 +/**
40876 + * Handles a host channel STALL interrupt. This handler may be called in
40877 + * either DMA mode or Slave mode.
40878 + */
40879 +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
40880 +                                   dwc_hc_t * hc,
40881 +                                   dwc_otg_hc_regs_t * hc_regs,
40882 +                                   dwc_otg_qtd_t * qtd)
40883 +{
40884 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
40885 +       int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
40886 +
40887 +       DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
40888 +                   "STALL Received--\n", hc->hc_num);
40889 +
40890 +       if (hcd->core_if->dma_desc_enable) {
40891 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
40892 +               goto handle_stall_done;
40893 +       }
40894 +
40895 +       if (pipe_type == UE_CONTROL) {
40896 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
40897 +       }
40898 +
40899 +       if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
40900 +               hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
40901 +               /*
40902 +                * USB protocol requires resetting the data toggle for bulk
40903 +                * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
40904 +                * setup command is issued to the endpoint. Anticipate the
40905 +                * CLEAR_FEATURE command since a STALL has occurred and reset
40906 +                * the data toggle now.
40907 +                */
40908 +               hc->qh->data_toggle = 0;
40909 +       }
40910 +
40911 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
40912 +
40913 +handle_stall_done:
40914 +       disable_hc_int(hc_regs, stall);
40915 +
40916 +       return 1;
40917 +}
40918 +
40919 +/*
40920 + * Updates the state of the URB when a transfer has been stopped due to an
40921 + * abnormal condition before the transfer completes. Modifies the
40922 + * actual_length field of the URB to reflect the number of bytes that have
40923 + * actually been transferred via the host channel.
40924 + */
40925 +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
40926 +                                      dwc_otg_hc_regs_t * hc_regs,
40927 +                                      dwc_otg_hcd_urb_t * urb,
40928 +                                      dwc_otg_qtd_t * qtd,
40929 +                                      dwc_otg_halt_status_e halt_status)
40930 +{
40931 +       uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
40932 +                                                           halt_status, NULL);
40933 +       /* non DWORD-aligned buffer case handling. */
40934 +       if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
40935 +               dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
40936 +                          bytes_transferred);
40937 +       }
40938 +
40939 +       urb->actual_length += bytes_transferred;
40940 +
40941 +#ifdef DEBUG
40942 +       {
40943 +               hctsiz_data_t hctsiz;
40944 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
40945 +               DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
40946 +                           __func__, (hc->ep_is_in ? "IN" : "OUT"),
40947 +                           hc->hc_num);
40948 +               DWC_DEBUGPL(DBG_HCDV, "  hc->start_pkt_count %d\n",
40949 +                           hc->start_pkt_count);
40950 +               DWC_DEBUGPL(DBG_HCDV, "  hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
40951 +               DWC_DEBUGPL(DBG_HCDV, "  hc->max_packet %d\n", hc->max_packet);
40952 +               DWC_DEBUGPL(DBG_HCDV, "  bytes_transferred %d\n",
40953 +                           bytes_transferred);
40954 +               DWC_DEBUGPL(DBG_HCDV, "  urb->actual_length %d\n",
40955 +                           urb->actual_length);
40956 +               DWC_DEBUGPL(DBG_HCDV, "  urb->transfer_buffer_length %d\n",
40957 +                           urb->length);
40958 +       }
40959 +#endif
40960 +}
40961 +
40962 +/**
40963 + * Handles a host channel NAK interrupt. This handler may be called in either
40964 + * DMA mode or Slave mode.
40965 + */
40966 +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
40967 +                                 dwc_hc_t * hc,
40968 +                                 dwc_otg_hc_regs_t * hc_regs,
40969 +                                 dwc_otg_qtd_t * qtd)
40970 +{
40971 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
40972 +                   "NAK Received--\n", hc->hc_num);
40973 +
40974 +       /*
40975 +        * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
40976 +        * interrupt.  Re-start the SSPLIT transfer.
40977 +        */
40978 +       if (hc->do_split) {
40979 +               if (hc->complete_split) {
40980 +                       qtd->error_count = 0;
40981 +               }
40982 +               qtd->complete_split = 0;
40983 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
40984 +               goto handle_nak_done;
40985 +       }
40986 +
40987 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
40988 +       case UE_CONTROL:
40989 +       case UE_BULK:
40990 +               if (hcd->core_if->dma_enable && hc->ep_is_in) {
40991 +                       /*
40992 +                        * NAK interrupts are enabled on bulk/control IN
40993 +                        * transfers in DMA mode for the sole purpose of
40994 +                        * resetting the error count after a transaction error
40995 +                        * occurs. The core will continue transferring data.
40996 +                        */
40997 +                       qtd->error_count = 0;
40998 +                       goto handle_nak_done;
40999 +               }
41000 +
41001 +               /*
41002 +                * NAK interrupts normally occur during OUT transfers in DMA
41003 +                * or Slave mode. For IN transfers, more requests will be
41004 +                * queued as request queue space is available.
41005 +                */
41006 +               qtd->error_count = 0;
41007 +
41008 +               if (!hc->qh->ping_state) {
41009 +                       update_urb_state_xfer_intr(hc, hc_regs,
41010 +                                                  qtd->urb, qtd,
41011 +                                                  DWC_OTG_HC_XFER_NAK);
41012 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41013 +
41014 +                       if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
41015 +                               hc->qh->ping_state = 1;
41016 +               }
41017 +
41018 +               /*
41019 +                * Halt the channel so the transfer can be re-started from
41020 +                * the appropriate point or the PING protocol will
41021 +                * start/continue.
41022 +                */
41023 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41024 +               break;
41025 +       case UE_INTERRUPT:
41026 +               qtd->error_count = 0;
41027 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
41028 +               break;
41029 +       case UE_ISOCHRONOUS:
41030 +               /* Should never get called for isochronous transfers. */
41031 +               DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
41032 +               break;
41033 +       }
41034 +
41035 +handle_nak_done:
41036 +       disable_hc_int(hc_regs, nak);
41037 +
41038 +       return 1;
41039 +}
41040 +
41041 +/**
41042 + * Handles a host channel ACK interrupt. This interrupt is enabled when
41043 + * performing the PING protocol in Slave mode, when errors occur during
41044 + * either Slave mode or DMA mode, and during Start Split transactions.
41045 + */
41046 +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
41047 +                                 dwc_hc_t * hc,
41048 +                                 dwc_otg_hc_regs_t * hc_regs,
41049 +                                 dwc_otg_qtd_t * qtd)
41050 +{
41051 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41052 +                   "ACK Received--\n", hc->hc_num);
41053 +
41054 +       if (hc->do_split) {
41055 +               /*
41056 +                * Handle ACK on SSPLIT.
41057 +                * ACK should not occur in CSPLIT.
41058 +                */
41059 +               if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
41060 +                       qtd->ssplit_out_xfer_count = hc->xfer_len;
41061 +               }
41062 +               if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
41063 +                       /* Don't need complete for isochronous out transfers. */
41064 +                       qtd->complete_split = 1;
41065 +               }
41066 +
41067 +               /* ISOC OUT */
41068 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41069 +                       switch (hc->xact_pos) {
41070 +                       case DWC_HCSPLIT_XACTPOS_ALL:
41071 +                               break;
41072 +                       case DWC_HCSPLIT_XACTPOS_END:
41073 +                               qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
41074 +                               qtd->isoc_split_offset = 0;
41075 +                               break;
41076 +                       case DWC_HCSPLIT_XACTPOS_BEGIN:
41077 +                       case DWC_HCSPLIT_XACTPOS_MID:
41078 +                               /*
41079 +                                * For BEGIN or MID, calculate the length for
41080 +                                * the next microframe to determine the correct
41081 +                                * SSPLIT token, either MID or END.
41082 +                                */
41083 +                               {
41084 +                                       struct dwc_otg_hcd_iso_packet_desc
41085 +                                       *frame_desc;
41086 +
41087 +                                       frame_desc =
41088 +                                           &qtd->urb->
41089 +                                           iso_descs[qtd->isoc_frame_index];
41090 +                                       qtd->isoc_split_offset += 188;
41091 +
41092 +                                       if ((frame_desc->length -
41093 +                                            qtd->isoc_split_offset) <= 188) {
41094 +                                               qtd->isoc_split_pos =
41095 +                                                   DWC_HCSPLIT_XACTPOS_END;
41096 +                                       } else {
41097 +                                               qtd->isoc_split_pos =
41098 +                                                   DWC_HCSPLIT_XACTPOS_MID;
41099 +                                       }
41100 +
41101 +                               }
41102 +                               break;
41103 +                       }
41104 +               } else {
41105 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41106 +               }
41107 +       } else {
41108 +               qtd->error_count = 0;
41109 +
41110 +               if (hc->qh->ping_state) {
41111 +                       hc->qh->ping_state = 0;
41112 +                       /*
41113 +                        * Halt the channel so the transfer can be re-started
41114 +                        * from the appropriate point. This only happens in
41115 +                        * Slave mode. In DMA mode, the ping_state is cleared
41116 +                        * when the transfer is started because the core
41117 +                        * automatically executes the PING, then the transfer.
41118 +                        */
41119 +                       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
41120 +               }
41121 +       }
41122 +
41123 +       /*
41124 +        * If the ACK occurred when _not_ in the PING state, let the channel
41125 +        * continue transferring data after clearing the error count.
41126 +        */
41127 +
41128 +       disable_hc_int(hc_regs, ack);
41129 +
41130 +       return 1;
41131 +}
41132 +
41133 +/**
41134 + * Handles a host channel NYET interrupt. This interrupt should only occur on
41135 + * Bulk and Control OUT endpoints and for complete split transactions. If a
41136 + * NYET occurs at the same time as a Transfer Complete interrupt, it is
41137 + * handled in the xfercomp interrupt handler, not here. This handler may be
41138 + * called in either DMA mode or Slave mode.
41139 + */
41140 +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
41141 +                                  dwc_hc_t * hc,
41142 +                                  dwc_otg_hc_regs_t * hc_regs,
41143 +                                  dwc_otg_qtd_t * qtd)
41144 +{
41145 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41146 +                   "NYET Received--\n", hc->hc_num);
41147 +
41148 +       /*
41149 +        * NYET on CSPLIT
41150 +        * re-do the CSPLIT immediately on non-periodic
41151 +        */
41152 +       if (hc->do_split && hc->complete_split) {
41153 +               if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
41154 +                   && hcd->core_if->dma_enable) {
41155 +                       qtd->complete_split = 0;
41156 +                       qtd->isoc_split_offset = 0;
41157 +                       if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
41158 +                               hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
41159 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
41160 +                       }
41161 +                       else
41162 +                               release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
41163 +                       goto handle_nyet_done;
41164 +               }
41165 +
41166 +               if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41167 +                   hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41168 +                       int frnum = dwc_otg_hcd_get_frame_number(hcd);
41169 +
41170 +                       if (dwc_full_frame_num(frnum) !=
41171 +                           dwc_full_frame_num(hc->qh->sched_frame)) {
41172 +                               /*
41173 +                                * No longer in the same full speed frame.
41174 +                                * Treat this as a transaction error.
41175 +                                */
41176 +#if 0
41177 +                               /** @todo Fix system performance so this can
41178 +                                * be treated as an error. Right now complete
41179 +                                * splits cannot be scheduled precisely enough
41180 +                                * due to other system activity, so this error
41181 +                                * occurs regularly in Slave mode.
41182 +                                */
41183 +                               qtd->error_count++;
41184 +#endif
41185 +                               qtd->complete_split = 0;
41186 +                               halt_channel(hcd, hc, qtd,
41187 +                                            DWC_OTG_HC_XFER_XACT_ERR);
41188 +                               /** @todo add support for isoc release */
41189 +                               goto handle_nyet_done;
41190 +                       }
41191 +               }
41192 +
41193 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41194 +               goto handle_nyet_done;
41195 +       }
41196 +
41197 +       hc->qh->ping_state = 1;
41198 +       qtd->error_count = 0;
41199 +
41200 +       update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
41201 +                                  DWC_OTG_HC_XFER_NYET);
41202 +       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41203 +
41204 +       /*
41205 +        * Halt the channel and re-start the transfer so the PING
41206 +        * protocol will start.
41207 +        */
41208 +       halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
41209 +
41210 +handle_nyet_done:
41211 +       disable_hc_int(hc_regs, nyet);
41212 +       return 1;
41213 +}
41214 +
41215 +/**
41216 + * Handles a host channel babble interrupt. This handler may be called in
41217 + * either DMA mode or Slave mode.
41218 + */
41219 +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
41220 +                                    dwc_hc_t * hc,
41221 +                                    dwc_otg_hc_regs_t * hc_regs,
41222 +                                    dwc_otg_qtd_t * qtd)
41223 +{
41224 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41225 +                   "Babble Error--\n", hc->hc_num);
41226 +
41227 +       if (hcd->core_if->dma_desc_enable) {
41228 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41229 +                                              DWC_OTG_HC_XFER_BABBLE_ERR);
41230 +               goto handle_babble_done;
41231 +       }
41232 +
41233 +       if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
41234 +               hcd->fops->complete(hcd, qtd->urb->priv,
41235 +                                   qtd->urb, -DWC_E_OVERFLOW);
41236 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
41237 +       } else {
41238 +               dwc_otg_halt_status_e halt_status;
41239 +               halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41240 +                                                   DWC_OTG_HC_XFER_BABBLE_ERR);
41241 +               halt_channel(hcd, hc, qtd, halt_status);
41242 +       }
41243 +
41244 +handle_babble_done:
41245 +       disable_hc_int(hc_regs, bblerr);
41246 +       return 1;
41247 +}
41248 +
41249 +/**
41250 + * Handles a host channel AHB error interrupt. This handler is only called in
41251 + * DMA mode.
41252 + */
41253 +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
41254 +                                    dwc_hc_t * hc,
41255 +                                    dwc_otg_hc_regs_t * hc_regs,
41256 +                                    dwc_otg_qtd_t * qtd)
41257 +{
41258 +       hcchar_data_t hcchar;
41259 +       hcsplt_data_t hcsplt;
41260 +       hctsiz_data_t hctsiz;
41261 +       uint32_t hcdma;
41262 +       char *pipetype, *speed;
41263 +
41264 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
41265 +
41266 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41267 +                   "AHB Error--\n", hc->hc_num);
41268 +
41269 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41270 +       hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41271 +       hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41272 +       hcdma = DWC_READ_REG32(&hc_regs->hcdma);
41273 +
41274 +       DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
41275 +       DWC_ERROR("  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
41276 +       DWC_ERROR("  hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
41277 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
41278 +       DWC_ERROR("  Device address: %d\n",
41279 +                 dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
41280 +       DWC_ERROR("  Endpoint: %d, %s\n",
41281 +                 dwc_otg_hcd_get_ep_num(&urb->pipe_info),
41282 +                 (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
41283 +
41284 +       switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
41285 +       case UE_CONTROL:
41286 +               pipetype = "CONTROL";
41287 +               break;
41288 +       case UE_BULK:
41289 +               pipetype = "BULK";
41290 +               break;
41291 +       case UE_INTERRUPT:
41292 +               pipetype = "INTERRUPT";
41293 +               break;
41294 +       case UE_ISOCHRONOUS:
41295 +               pipetype = "ISOCHRONOUS";
41296 +               break;
41297 +       default:
41298 +               pipetype = "UNKNOWN";
41299 +               break;
41300 +       }
41301 +
41302 +       DWC_ERROR("  Endpoint type: %s\n", pipetype);
41303 +
41304 +       switch (hc->speed) {
41305 +       case DWC_OTG_EP_SPEED_HIGH:
41306 +               speed = "HIGH";
41307 +               break;
41308 +       case DWC_OTG_EP_SPEED_FULL:
41309 +               speed = "FULL";
41310 +               break;
41311 +       case DWC_OTG_EP_SPEED_LOW:
41312 +               speed = "LOW";
41313 +               break;
41314 +       default:
41315 +               speed = "UNKNOWN";
41316 +               break;
41317 +       };
41318 +
41319 +       DWC_ERROR("  Speed: %s\n", speed);
41320 +
41321 +       DWC_ERROR("  Max packet size: %d\n",
41322 +                 dwc_otg_hcd_get_mps(&urb->pipe_info));
41323 +       DWC_ERROR("  Data buffer length: %d\n", urb->length);
41324 +       DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",
41325 +                 urb->buf, (void *)urb->dma);
41326 +       DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",
41327 +                 urb->setup_packet, (void *)urb->setup_dma);
41328 +       DWC_ERROR("  Interval: %d\n", urb->interval);
41329 +
41330 +       /* Core haltes the channel for Descriptor DMA mode */
41331 +       if (hcd->core_if->dma_desc_enable) {
41332 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41333 +                                              DWC_OTG_HC_XFER_AHB_ERR);
41334 +               goto handle_ahberr_done;
41335 +       }
41336 +
41337 +       hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
41338 +
41339 +       /*
41340 +        * Force a channel halt. Don't call halt_channel because that won't
41341 +        * write to the HCCHARn register in DMA mode to force the halt.
41342 +        */
41343 +       dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
41344 +handle_ahberr_done:
41345 +       disable_hc_int(hc_regs, ahberr);
41346 +       return 1;
41347 +}
41348 +
41349 +/**
41350 + * Handles a host channel transaction error interrupt. This handler may be
41351 + * called in either DMA mode or Slave mode.
41352 + */
41353 +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
41354 +                                     dwc_hc_t * hc,
41355 +                                     dwc_otg_hc_regs_t * hc_regs,
41356 +                                     dwc_otg_qtd_t * qtd)
41357 +{
41358 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41359 +                   "Transaction Error--\n", hc->hc_num);
41360 +
41361 +       if (hcd->core_if->dma_desc_enable) {
41362 +               dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41363 +                                              DWC_OTG_HC_XFER_XACT_ERR);
41364 +               goto handle_xacterr_done;
41365 +       }
41366 +
41367 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41368 +       case UE_CONTROL:
41369 +       case UE_BULK:
41370 +               qtd->error_count++;
41371 +               if (!hc->qh->ping_state) {
41372 +
41373 +                       update_urb_state_xfer_intr(hc, hc_regs,
41374 +                                                  qtd->urb, qtd,
41375 +                                                  DWC_OTG_HC_XFER_XACT_ERR);
41376 +                       dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
41377 +                       if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
41378 +                               hc->qh->ping_state = 1;
41379 +                       }
41380 +               }
41381 +
41382 +               /*
41383 +                * Halt the channel so the transfer can be re-started from
41384 +                * the appropriate point or the PING protocol will start.
41385 +                */
41386 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41387 +               break;
41388 +       case UE_INTERRUPT:
41389 +               qtd->error_count++;
41390 +               if (hc->do_split && hc->complete_split) {
41391 +                       qtd->complete_split = 0;
41392 +               }
41393 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
41394 +               break;
41395 +       case UE_ISOCHRONOUS:
41396 +               {
41397 +                       dwc_otg_halt_status_e halt_status;
41398 +                       halt_status =
41399 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41400 +                                                 DWC_OTG_HC_XFER_XACT_ERR);
41401 +
41402 +                       halt_channel(hcd, hc, qtd, halt_status);
41403 +               }
41404 +               break;
41405 +       }
41406 +handle_xacterr_done:
41407 +       disable_hc_int(hc_regs, xacterr);
41408 +
41409 +       return 1;
41410 +}
41411 +
41412 +/**
41413 + * Handles a host channel frame overrun interrupt. This handler may be called
41414 + * in either DMA mode or Slave mode.
41415 + */
41416 +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
41417 +                                      dwc_hc_t * hc,
41418 +                                      dwc_otg_hc_regs_t * hc_regs,
41419 +                                      dwc_otg_qtd_t * qtd)
41420 +{
41421 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41422 +                   "Frame Overrun--\n", hc->hc_num);
41423 +
41424 +       switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
41425 +       case UE_CONTROL:
41426 +       case UE_BULK:
41427 +               break;
41428 +       case UE_INTERRUPT:
41429 +               halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
41430 +               break;
41431 +       case UE_ISOCHRONOUS:
41432 +               {
41433 +                       dwc_otg_halt_status_e halt_status;
41434 +                       halt_status =
41435 +                           update_isoc_urb_state(hcd, hc, hc_regs, qtd,
41436 +                                                 DWC_OTG_HC_XFER_FRAME_OVERRUN);
41437 +
41438 +                       halt_channel(hcd, hc, qtd, halt_status);
41439 +               }
41440 +               break;
41441 +       }
41442 +
41443 +       disable_hc_int(hc_regs, frmovrun);
41444 +
41445 +       return 1;
41446 +}
41447 +
41448 +/**
41449 + * Handles a host channel data toggle error interrupt. This handler may be
41450 + * called in either DMA mode or Slave mode.
41451 + */
41452 +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
41453 +                                        dwc_hc_t * hc,
41454 +                                        dwc_otg_hc_regs_t * hc_regs,
41455 +                                        dwc_otg_qtd_t * qtd)
41456 +{
41457 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41458 +                   "Data Toggle Error--\n", hc->hc_num);
41459 +
41460 +       if (hc->ep_is_in) {
41461 +               qtd->error_count = 0;
41462 +       } else {
41463 +               DWC_ERROR("Data Toggle Error on OUT transfer,"
41464 +                         "channel %d\n", hc->hc_num);
41465 +       }
41466 +
41467 +       disable_hc_int(hc_regs, datatglerr);
41468 +
41469 +       return 1;
41470 +}
41471 +
41472 +#ifdef DEBUG
41473 +/**
41474 + * This function is for debug only. It checks that a valid halt status is set
41475 + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
41476 + * taken and a warning is issued.
41477 + * @return 1 if halt status is ok, 0 otherwise.
41478 + */
41479 +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
41480 +                                dwc_hc_t * hc,
41481 +                                dwc_otg_hc_regs_t * hc_regs,
41482 +                                dwc_otg_qtd_t * qtd)
41483 +{
41484 +       hcchar_data_t hcchar;
41485 +       hctsiz_data_t hctsiz;
41486 +       hcint_data_t hcint;
41487 +       hcintmsk_data_t hcintmsk;
41488 +       hcsplt_data_t hcsplt;
41489 +
41490 +       if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
41491 +               /*
41492 +                * This code is here only as a check. This condition should
41493 +                * never happen. Ignore the halt if it does occur.
41494 +                */
41495 +               hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41496 +               hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
41497 +               hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41498 +               hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41499 +               hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
41500 +               DWC_WARN
41501 +                   ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
41502 +                    "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
41503 +                    "hcint 0x%08x, hcintmsk 0x%08x, "
41504 +                    "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
41505 +                    hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
41506 +                    hcintmsk.d32, hcsplt.d32, qtd->complete_split);
41507 +
41508 +               DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
41509 +                        __func__, hc->hc_num);
41510 +               DWC_WARN("\n");
41511 +               clear_hc_int(hc_regs, chhltd);
41512 +               return 0;
41513 +       }
41514 +
41515 +       /*
41516 +        * This code is here only as a check. hcchar.chdis should
41517 +        * never be set when the halt interrupt occurs. Halt the
41518 +        * channel again if it does occur.
41519 +        */
41520 +       hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
41521 +       if (hcchar.b.chdis) {
41522 +               DWC_WARN("%s: hcchar.chdis set unexpectedly, "
41523 +                        "hcchar 0x%08x, trying to halt again\n",
41524 +                        __func__, hcchar.d32);
41525 +               clear_hc_int(hc_regs, chhltd);
41526 +               hc->halt_pending = 0;
41527 +               halt_channel(hcd, hc, qtd, hc->halt_status);
41528 +               return 0;
41529 +       }
41530 +
41531 +       return 1;
41532 +}
41533 +#endif
41534 +
41535 +/**
41536 + * Handles a host Channel Halted interrupt in DMA mode. This handler
41537 + * determines the reason the channel halted and proceeds accordingly.
41538 + */
41539 +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
41540 +                                     dwc_hc_t * hc,
41541 +                                     dwc_otg_hc_regs_t * hc_regs,
41542 +                                     dwc_otg_qtd_t * qtd)
41543 +{
41544 +       hcint_data_t hcint;
41545 +       hcintmsk_data_t hcintmsk;
41546 +       int out_nak_enh = 0;
41547 +
41548 +       /* For core with OUT NAK enhancement, the flow for high-
41549 +        * speed CONTROL/BULK OUT is handled a little differently.
41550 +        */
41551 +       if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
41552 +               if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
41553 +                   (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
41554 +                    hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
41555 +                       out_nak_enh = 1;
41556 +               }
41557 +       }
41558 +
41559 +       if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
41560 +           (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
41561 +            && !hcd->core_if->dma_desc_enable)) {
41562 +               /*
41563 +                * Just release the channel. A dequeue can happen on a
41564 +                * transfer timeout. In the case of an AHB Error, the channel
41565 +                * was forced to halt because there's no way to gracefully
41566 +                * recover.
41567 +                */
41568 +               if (hcd->core_if->dma_desc_enable)
41569 +                       dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
41570 +                                                      hc->halt_status);
41571 +               else
41572 +                       release_channel(hcd, hc, qtd, hc->halt_status);
41573 +               return;
41574 +       }
41575 +
41576 +       /* Read the HCINTn register to determine the cause for the halt. */
41577 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41578 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41579 +
41580 +       if (hcint.b.xfercomp) {
41581 +               /** @todo This is here because of a possible hardware bug.  Spec
41582 +                * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
41583 +                * interrupt w/ACK bit set should occur, but I only see the
41584 +                * XFERCOMP bit, even with it masked out.  This is a workaround
41585 +                * for that behavior.  Should fix this when hardware is fixed.
41586 +                */
41587 +               if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
41588 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41589 +               }
41590 +               handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
41591 +       } else if (hcint.b.stall) {
41592 +               handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
41593 +       } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
41594 +               if (out_nak_enh) {
41595 +                       if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
41596 +                               DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
41597 +                               qtd->error_count = 0;
41598 +                       } else {
41599 +                               DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
41600 +                       }
41601 +               }
41602 +
41603 +               /*
41604 +                * Must handle xacterr before nak or ack. Could get a xacterr
41605 +                * at the same time as either of these on a BULK/CONTROL OUT
41606 +                * that started with a PING. The xacterr takes precedence.
41607 +                */
41608 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41609 +       } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
41610 +               handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
41611 +       } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
41612 +               handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
41613 +       } else if (hcint.b.bblerr) {
41614 +               handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
41615 +       } else if (hcint.b.frmovrun) {
41616 +               handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
41617 +       } else if (!out_nak_enh) {
41618 +               if (hcint.b.nyet) {
41619 +                       /*
41620 +                        * Must handle nyet before nak or ack. Could get a nyet at the
41621 +                        * same time as either of those on a BULK/CONTROL OUT that
41622 +                        * started with a PING. The nyet takes precedence.
41623 +                        */
41624 +                       handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
41625 +               } else if (hcint.b.nak && !hcintmsk.b.nak) {
41626 +                       /*
41627 +                        * If nak is not masked, it's because a non-split IN transfer
41628 +                        * is in an error state. In that case, the nak is handled by
41629 +                        * the nak interrupt handler, not here. Handle nak here for
41630 +                        * BULK/CONTROL OUT transfers, which halt on a NAK to allow
41631 +                        * rewinding the buffer pointer.
41632 +                        */
41633 +                       handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
41634 +               } else if (hcint.b.ack && !hcintmsk.b.ack) {
41635 +                       /*
41636 +                        * If ack is not masked, it's because a non-split IN transfer
41637 +                        * is in an error state. In that case, the ack is handled by
41638 +                        * the ack interrupt handler, not here. Handle ack here for
41639 +                        * split transfers. Start splits halt on ACK.
41640 +                        */
41641 +                       handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
41642 +               } else {
41643 +                       if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
41644 +                           hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
41645 +                               /*
41646 +                                * A periodic transfer halted with no other channel
41647 +                                * interrupts set. Assume it was halted by the core
41648 +                                * because it could not be completed in its scheduled
41649 +                                * (micro)frame.
41650 +                                */
41651 +#ifdef DEBUG
41652 +                               DWC_PRINTF
41653 +                                   ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
41654 +                                    __func__, hc->hc_num);
41655 +#endif
41656 +                               halt_channel(hcd, hc, qtd,
41657 +                                            DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
41658 +                       } else {
41659 +                               DWC_ERROR
41660 +                                   ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
41661 +                                    "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
41662 +                                    __func__, hc->hc_num, hcint.d32,
41663 +                                    DWC_READ_REG32(&hcd->
41664 +                                                   core_if->core_global_regs->
41665 +                                                   gintsts));
41666 +                       }
41667 +
41668 +               }
41669 +       } else {
41670 +               DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
41671 +                          hcint.d32);
41672 +       }
41673 +}
41674 +
41675 +/**
41676 + * Handles a host channel Channel Halted interrupt.
41677 + *
41678 + * In slave mode, this handler is called only when the driver specifically
41679 + * requests a halt. This occurs during handling other host channel interrupts
41680 + * (e.g. nak, xacterr, stall, nyet, etc.).
41681 + *
41682 + * In DMA mode, this is the interrupt that occurs when the core has finished
41683 + * processing a transfer on a channel. Other host channel interrupts (except
41684 + * ahberr) are disabled in DMA mode.
41685 + */
41686 +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
41687 +                                    dwc_hc_t * hc,
41688 +                                    dwc_otg_hc_regs_t * hc_regs,
41689 +                                    dwc_otg_qtd_t * qtd)
41690 +{
41691 +       DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
41692 +                   "Channel Halted--\n", hc->hc_num);
41693 +
41694 +       if (hcd->core_if->dma_enable) {
41695 +               handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
41696 +       } else {
41697 +#ifdef DEBUG
41698 +               if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
41699 +                       return 1;
41700 +               }
41701 +#endif
41702 +               release_channel(hcd, hc, qtd, hc->halt_status);
41703 +       }
41704 +
41705 +       return 1;
41706 +}
41707 +
41708 +/** Handles interrupt for a specific Host Channel */
41709 +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
41710 +{
41711 +       int retval = 0;
41712 +       hcint_data_t hcint;
41713 +       hcintmsk_data_t hcintmsk;
41714 +       dwc_hc_t *hc;
41715 +       dwc_otg_hc_regs_t *hc_regs;
41716 +       dwc_otg_qtd_t *qtd;
41717 +
41718 +       DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
41719 +
41720 +       hc = dwc_otg_hcd->hc_ptr_array[num];
41721 +       hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
41722 +       qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
41723 +
41724 +       hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
41725 +       hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
41726 +       DWC_DEBUGPL(DBG_HCDV,
41727 +                   "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
41728 +                   hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
41729 +       hcint.d32 = hcint.d32 & hcintmsk.d32;
41730 +
41731 +       if (!dwc_otg_hcd->core_if->dma_enable) {
41732 +               if (hcint.b.chhltd && hcint.d32 != 0x2) {
41733 +                       hcint.b.chhltd = 0;
41734 +               }
41735 +       }
41736 +
41737 +       if (hcint.b.xfercomp) {
41738 +               retval |=
41739 +                   handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41740 +               /*
41741 +                * If NYET occurred at same time as Xfer Complete, the NYET is
41742 +                * handled by the Xfer Complete interrupt handler. Don't want
41743 +                * to call the NYET interrupt handler in this case.
41744 +                */
41745 +               hcint.b.nyet = 0;
41746 +       }
41747 +       if (hcint.b.chhltd) {
41748 +               retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41749 +       }
41750 +       if (hcint.b.ahberr) {
41751 +               retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41752 +       }
41753 +       if (hcint.b.stall) {
41754 +               retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41755 +       }
41756 +       if (hcint.b.nak) {
41757 +               retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41758 +       }
41759 +       if (hcint.b.ack) {
41760 +               retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41761 +       }
41762 +       if (hcint.b.nyet) {
41763 +               retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41764 +       }
41765 +       if (hcint.b.xacterr) {
41766 +               retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41767 +       }
41768 +       if (hcint.b.bblerr) {
41769 +               retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41770 +       }
41771 +       if (hcint.b.frmovrun) {
41772 +               retval |=
41773 +                   handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41774 +       }
41775 +       if (hcint.b.datatglerr) {
41776 +               retval |=
41777 +                   handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
41778 +       }
41779 +
41780 +       return retval;
41781 +}
41782 +
41783 +#endif /* DWC_DEVICE_ONLY */
41784 --- /dev/null
41785 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
41786 @@ -0,0 +1,893 @@
41787 +/* ==========================================================================
41788 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
41789 + * $Revision: #20 $
41790 + * $Date: 2011/10/26 $
41791 + * $Change: 1872981 $
41792 + *
41793 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
41794 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
41795 + * otherwise expressly agreed to in writing between Synopsys and you.
41796 + *
41797 + * The Software IS NOT an item of Licensed Software or Licensed Product under
41798 + * any End User Software License Agreement or Agreement for Licensed Product
41799 + * with Synopsys or any supplement thereto. You are permitted to use and
41800 + * redistribute this Software in source and binary forms, with or without
41801 + * modification, provided that redistributions of source code must retain this
41802 + * notice. You may not view, use, disclose, copy or distribute this file or
41803 + * any information contained herein except pursuant to this license grant from
41804 + * Synopsys. If you do not agree with this notice, including the disclaimer
41805 + * below, then you are not authorized to use the Software.
41806 + *
41807 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
41808 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41809 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41810 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
41811 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41812 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41813 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41814 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41815 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41816 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
41817 + * DAMAGE.
41818 + * ========================================================================== */
41819 +#ifndef DWC_DEVICE_ONLY
41820 +
41821 +/**
41822 + * @file
41823 + *
41824 + * This file contains the implementation of the HCD. In Linux, the HCD
41825 + * implements the hc_driver API.
41826 + */
41827 +#include <linux/kernel.h>
41828 +#include <linux/module.h>
41829 +#include <linux/moduleparam.h>
41830 +#include <linux/init.h>
41831 +#include <linux/device.h>
41832 +#include <linux/errno.h>
41833 +#include <linux/list.h>
41834 +#include <linux/interrupt.h>
41835 +#include <linux/string.h>
41836 +#include <linux/dma-mapping.h>
41837 +#include <linux/version.h>
41838 +#include <asm/io.h>
41839 +#include <linux/usb.h>
41840 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
41841 +#include <../drivers/usb/core/hcd.h>
41842 +#else
41843 +#include <linux/usb/hcd.h>
41844 +#endif
41845 +
41846 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
41847 +#define USB_URB_EP_LINKING 1
41848 +#else
41849 +#define USB_URB_EP_LINKING 0
41850 +#endif
41851 +
41852 +#include "dwc_otg_hcd_if.h"
41853 +#include "dwc_otg_dbg.h"
41854 +#include "dwc_otg_driver.h"
41855 +#include "dwc_otg_hcd.h"
41856 +/**
41857 + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
41858 + * qualified with its direction (possible 32 endpoints per device).
41859 + */
41860 +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
41861 +                                                    ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
41862 +
41863 +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
41864 +
41865 +/** @name Linux HC Driver API Functions */
41866 +/** @{ */
41867 +/* manage i/o requests, device state */
41868 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
41869 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41870 +                      struct usb_host_endpoint *ep,
41871 +#endif
41872 +                      struct urb *urb, gfp_t mem_flags);
41873 +
41874 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
41875 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
41876 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
41877 +#endif
41878 +#else /* kernels at or post 2.6.30 */
41879 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,
41880 +                               struct urb *urb, int status);
41881 +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
41882 +
41883 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
41884 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
41885 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
41886 +#endif
41887 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
41888 +extern int hcd_start(struct usb_hcd *hcd);
41889 +extern void hcd_stop(struct usb_hcd *hcd);
41890 +static int get_frame_number(struct usb_hcd *hcd);
41891 +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
41892 +extern int hub_control(struct usb_hcd *hcd,
41893 +                      u16 typeReq,
41894 +                      u16 wValue, u16 wIndex, char *buf, u16 wLength);
41895 +
41896 +struct wrapper_priv_data {
41897 +       dwc_otg_hcd_t *dwc_otg_hcd;
41898 +};
41899 +
41900 +/** @} */
41901 +
41902 +static struct hc_driver dwc_otg_hc_driver = {
41903 +
41904 +       .description = dwc_otg_hcd_name,
41905 +       .product_desc = "DWC OTG Controller",
41906 +       .hcd_priv_size = sizeof(struct wrapper_priv_data),
41907 +
41908 +       .irq = dwc_otg_hcd_irq,
41909 +
41910 +       .flags = HCD_MEMORY | HCD_USB2,
41911 +
41912 +       //.reset =
41913 +       .start = hcd_start,
41914 +       //.suspend =
41915 +       //.resume =
41916 +       .stop = hcd_stop,
41917 +
41918 +       .urb_enqueue = dwc_otg_urb_enqueue,
41919 +       .urb_dequeue = dwc_otg_urb_dequeue,
41920 +       .endpoint_disable = endpoint_disable,
41921 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
41922 +       .endpoint_reset = endpoint_reset,
41923 +#endif
41924 +       .get_frame_number = get_frame_number,
41925 +
41926 +       .hub_status_data = hub_status_data,
41927 +       .hub_control = hub_control,
41928 +       //.bus_suspend =
41929 +       //.bus_resume =
41930 +};
41931 +
41932 +/** Gets the dwc_otg_hcd from a struct usb_hcd */
41933 +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
41934 +{
41935 +       struct wrapper_priv_data *p;
41936 +       p = (struct wrapper_priv_data *)(hcd->hcd_priv);
41937 +       return p->dwc_otg_hcd;
41938 +}
41939 +
41940 +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
41941 +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
41942 +{
41943 +       return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
41944 +}
41945 +
41946 +/** Gets the usb_host_endpoint associated with an URB. */
41947 +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
41948 +{
41949 +       struct usb_device *dev = urb->dev;
41950 +       int ep_num = usb_pipeendpoint(urb->pipe);
41951 +
41952 +       if (usb_pipein(urb->pipe))
41953 +               return dev->ep_in[ep_num];
41954 +       else
41955 +               return dev->ep_out[ep_num];
41956 +}
41957 +
41958 +static int _disconnect(dwc_otg_hcd_t * hcd)
41959 +{
41960 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
41961 +
41962 +       usb_hcd->self.is_b_host = 0;
41963 +       return 0;
41964 +}
41965 +
41966 +static int _start(dwc_otg_hcd_t * hcd)
41967 +{
41968 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
41969 +
41970 +       usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
41971 +       hcd_start(usb_hcd);
41972 +
41973 +       return 0;
41974 +}
41975 +
41976 +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
41977 +                    uint32_t * port_addr)
41978 +{
41979 +   struct urb *urb = (struct urb *)urb_handle;
41980 +   struct usb_bus *bus;
41981 +#if 1 //GRAYG - temporary
41982 +   if (NULL == urb_handle)
41983 +      DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
41984 +   if (NULL == urb->dev)
41985 +      DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
41986 +   if (NULL == port_addr)
41987 +      DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
41988 +#endif
41989 +   if (urb->dev->tt) {
41990 +        if (NULL == urb->dev->tt->hub) {
41991 +                DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
41992 +                           __func__); //GRAYG
41993 +                //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
41994 +                *hub_addr = 0; //GRAYG
41995 +                // we probably shouldn't have a transaction translator if
41996 +                // there's no associated hub?
41997 +        } else {
41998 +               bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
41999 +               if (urb->dev->tt->hub == bus->root_hub)
42000 +                       *hub_addr = 0;
42001 +               else
42002 +                       *hub_addr = urb->dev->tt->hub->devnum;
42003 +       }
42004 +       *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
42005 +   } else {
42006 +        *hub_addr = 0;
42007 +       *port_addr = urb->dev->ttport;
42008 +   }
42009 +   return 0;
42010 +}
42011 +
42012 +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
42013 +{
42014 +       struct urb *urb = (struct urb *)urb_handle;
42015 +       return urb->dev->speed;
42016 +}
42017 +
42018 +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
42019 +{
42020 +       struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
42021 +       return usb_hcd->self.b_hnp_enable;
42022 +}
42023 +
42024 +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42025 +                                  struct urb *urb)
42026 +{
42027 +       hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
42028 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42029 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
42030 +       } else {
42031 +               hcd_to_bus(hcd)->bandwidth_int_reqs++;
42032 +       }
42033 +}
42034 +
42035 +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
42036 +                              struct urb *urb)
42037 +{
42038 +       hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
42039 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42040 +               hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
42041 +       } else {
42042 +               hcd_to_bus(hcd)->bandwidth_int_reqs--;
42043 +       }
42044 +}
42045 +
42046 +/**
42047 + * Sets the final status of an URB and returns it to the device driver. Any
42048 + * required cleanup of the URB is performed.
42049 + */
42050 +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
42051 +                    dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
42052 +{
42053 +       struct urb *urb = (struct urb *)urb_handle;
42054 +
42055 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42056 +               DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
42057 +                          __func__, urb, usb_pipedevice(urb->pipe),
42058 +                          usb_pipeendpoint(urb->pipe),
42059 +                          usb_pipein(urb->pipe) ? "IN" : "OUT", status);
42060 +               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42061 +                       int i;
42062 +                       for (i = 0; i < urb->number_of_packets; i++) {
42063 +                               DWC_PRINTF("  ISO Desc %d status: %d\n",
42064 +                                          i, urb->iso_frame_desc[i].status);
42065 +                       }
42066 +               }
42067 +       }
42068 +
42069 +       urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
42070 +       /* Convert status value. */
42071 +       switch (status) {
42072 +       case -DWC_E_PROTOCOL:
42073 +               status = -EPROTO;
42074 +               break;
42075 +       case -DWC_E_IN_PROGRESS:
42076 +               status = -EINPROGRESS;
42077 +               break;
42078 +       case -DWC_E_PIPE:
42079 +               status = -EPIPE;
42080 +               break;
42081 +       case -DWC_E_IO:
42082 +               status = -EIO;
42083 +               break;
42084 +       case -DWC_E_TIMEOUT:
42085 +               status = -ETIMEDOUT;
42086 +               break;
42087 +       case -DWC_E_OVERFLOW:
42088 +               status = -EOVERFLOW;
42089 +               break;
42090 +       default:
42091 +               if (status) {
42092 +                       DWC_PRINTF("Uknown urb status %d\n", status);
42093 +
42094 +               }
42095 +       }
42096 +
42097 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42098 +               int i;
42099 +
42100 +               urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
42101 +               for (i = 0; i < urb->number_of_packets; ++i) {
42102 +                       urb->iso_frame_desc[i].actual_length =
42103 +                           dwc_otg_hcd_urb_get_iso_desc_actual_length
42104 +                           (dwc_otg_urb, i);
42105 +                       urb->iso_frame_desc[i].status =
42106 +                           dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
42107 +               }
42108 +       }
42109 +
42110 +       urb->status = status;
42111 +       urb->hcpriv = NULL;
42112 +       if (!status) {
42113 +               if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
42114 +                   (urb->actual_length < urb->transfer_buffer_length)) {
42115 +                       urb->status = -EREMOTEIO;
42116 +               }
42117 +       }
42118 +
42119 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
42120 +           (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42121 +               struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
42122 +               if (ep) {
42123 +                       free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
42124 +                                          dwc_otg_hcd_get_ep_bandwidth(hcd,
42125 +                                                                       ep->hcpriv),
42126 +                                          urb);
42127 +               }
42128 +       }
42129 +
42130 +       DWC_FREE(dwc_otg_urb);
42131 +
42132 +#if USB_URB_EP_LINKING
42133 +        usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
42134 +#endif
42135 +       DWC_SPINUNLOCK(hcd->lock);
42136 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42137 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
42138 +#else
42139 +       usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
42140 +#endif
42141 +       DWC_SPINLOCK(hcd->lock);
42142 +
42143 +       return 0;
42144 +}
42145 +
42146 +static struct dwc_otg_hcd_function_ops hcd_fops = {
42147 +       .start = _start,
42148 +       .disconnect = _disconnect,
42149 +       .hub_info = _hub_info,
42150 +       .speed = _speed,
42151 +       .complete = _complete,
42152 +       .get_b_hnp_enable = _get_b_hnp_enable,
42153 +};
42154 +
42155 +/**
42156 + * Initializes the HCD. This function allocates memory for and initializes the
42157 + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
42158 + * USB bus with the core and calls the hc_driver->start() function. It returns
42159 + * a negative error on failure.
42160 + */
42161 +int hcd_init(dwc_bus_dev_t *_dev)
42162 +{
42163 +       struct usb_hcd *hcd = NULL;
42164 +       dwc_otg_hcd_t *dwc_otg_hcd = NULL;
42165 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42166 +       int retval = 0;
42167 +        u64 dmamask;
42168 +
42169 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
42170 +
42171 +       /* Set device flags indicating whether the HCD supports DMA. */
42172 +       if (dwc_otg_is_dma_enable(otg_dev->core_if))
42173 +                dmamask = DMA_BIT_MASK(32);
42174 +        else
42175 +                dmamask = 0;
42176 +
42177 +#if    defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
42178 +        dma_set_mask(&_dev->dev, dmamask);
42179 +        dma_set_coherent_mask(&_dev->dev, dmamask);
42180 +#elif  defined(PCI_INTERFACE)
42181 +        pci_set_dma_mask(_dev, dmamask);
42182 +        pci_set_consistent_dma_mask(_dev, dmamask);
42183 +#endif
42184 +
42185 +       /*
42186 +        * Allocate memory for the base HCD plus the DWC OTG HCD.
42187 +        * Initialize the base HCD.
42188 +        */
42189 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
42190 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
42191 +#else
42192 +       hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
42193 +       hcd->has_tt = 1;
42194 +//      hcd->uses_new_polling = 1;
42195 +//      hcd->poll_rh = 0;
42196 +#endif
42197 +       if (!hcd) {
42198 +               retval = -ENOMEM;
42199 +               goto error1;
42200 +       }
42201 +
42202 +       hcd->regs = otg_dev->os_dep.base;
42203 +
42204 +       /* Initialize the DWC OTG HCD. */
42205 +       dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
42206 +       if (!dwc_otg_hcd) {
42207 +               goto error2;
42208 +       }
42209 +       ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
42210 +           dwc_otg_hcd;
42211 +       otg_dev->hcd = dwc_otg_hcd;
42212 +
42213 +       if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
42214 +               goto error2;
42215 +       }
42216 +
42217 +       otg_dev->hcd->otg_dev = otg_dev;
42218 +       hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
42219 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
42220 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later
42221 +       hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
42222 +#endif
42223 +       /* Don't support SG list at this point */
42224 +       hcd->self.sg_tablesize = 0;
42225 +#endif
42226 +       /*
42227 +        * Finish generic HCD initialization and start the HCD. This function
42228 +        * allocates the DMA buffer pool, registers the USB bus, requests the
42229 +        * IRQ line, and calls hcd_start method.
42230 +        */
42231 +#ifdef PLATFORM_INTERFACE
42232 +        retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
42233 +#else
42234 +        retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
42235 +#endif
42236 +       if (retval < 0) {
42237 +               goto error2;
42238 +       }
42239 +
42240 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
42241 +       return 0;
42242 +
42243 +error2:
42244 +       usb_put_hcd(hcd);
42245 +error1:
42246 +       return retval;
42247 +}
42248 +
42249 +/**
42250 + * Removes the HCD.
42251 + * Frees memory and resources associated with the HCD and deregisters the bus.
42252 + */
42253 +void hcd_remove(dwc_bus_dev_t *_dev)
42254 +{
42255 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
42256 +       dwc_otg_hcd_t *dwc_otg_hcd;
42257 +       struct usb_hcd *hcd;
42258 +
42259 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
42260 +
42261 +       if (!otg_dev) {
42262 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
42263 +               return;
42264 +       }
42265 +
42266 +       dwc_otg_hcd = otg_dev->hcd;
42267 +
42268 +       if (!dwc_otg_hcd) {
42269 +               DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
42270 +               return;
42271 +       }
42272 +
42273 +       hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
42274 +
42275 +       if (!hcd) {
42276 +               DWC_DEBUGPL(DBG_ANY,
42277 +                           "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
42278 +                           __func__);
42279 +               return;
42280 +       }
42281 +       usb_remove_hcd(hcd);
42282 +       dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
42283 +       dwc_otg_hcd_remove(dwc_otg_hcd);
42284 +       usb_put_hcd(hcd);
42285 +}
42286 +
42287 +/* =========================================================================
42288 + *  Linux HC Driver Functions
42289 + * ========================================================================= */
42290 +
42291 +/** Initializes the DWC_otg controller and its root hub and prepares it for host
42292 + * mode operation. Activates the root port. Returns 0 on success and a negative
42293 + * error code on failure. */
42294 +int hcd_start(struct usb_hcd *hcd)
42295 +{
42296 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42297 +       struct usb_bus *bus;
42298 +
42299 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
42300 +       bus = hcd_to_bus(hcd);
42301 +
42302 +       hcd->state = HC_STATE_RUNNING;
42303 +       if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
42304 +               return 0;
42305 +       }
42306 +
42307 +       /* Initialize and connect root hub if one is not already attached */
42308 +       if (bus->root_hub) {
42309 +               DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
42310 +               /* Inform the HUB driver to resume. */
42311 +               usb_hcd_resume_root_hub(hcd);
42312 +       }
42313 +
42314 +       return 0;
42315 +}
42316 +
42317 +/**
42318 + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
42319 + * stopped.
42320 + */
42321 +void hcd_stop(struct usb_hcd *hcd)
42322 +{
42323 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42324 +
42325 +       dwc_otg_hcd_stop(dwc_otg_hcd);
42326 +}
42327 +
42328 +/** Returns the current frame number. */
42329 +static int get_frame_number(struct usb_hcd *hcd)
42330 +{
42331 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42332 +
42333 +       return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
42334 +}
42335 +
42336 +#ifdef DEBUG
42337 +static void dump_urb_info(struct urb *urb, char *fn_name)
42338 +{
42339 +       DWC_PRINTF("%s, urb %p\n", fn_name, urb);
42340 +       DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));
42341 +       DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
42342 +                  (usb_pipein(urb->pipe) ? "IN" : "OUT"));
42343 +       DWC_PRINTF("  Endpoint type: %s\n", ( {
42344 +                                            char *pipetype;
42345 +                                            switch (usb_pipetype(urb->pipe)) {
42346 +case PIPE_CONTROL:
42347 +pipetype = "CONTROL"; break; case PIPE_BULK:
42348 +pipetype = "BULK"; break; case PIPE_INTERRUPT:
42349 +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
42350 +pipetype = "ISOCHRONOUS"; break; default:
42351 +                                            pipetype = "UNKNOWN"; break;};
42352 +                                            pipetype;}
42353 +                  )) ;
42354 +       DWC_PRINTF("  Speed: %s\n", ( {
42355 +                                    char *speed; switch (urb->dev->speed) {
42356 +case USB_SPEED_HIGH:
42357 +speed = "HIGH"; break; case USB_SPEED_FULL:
42358 +speed = "FULL"; break; case USB_SPEED_LOW:
42359 +speed = "LOW"; break; default:
42360 +                                    speed = "UNKNOWN"; break;};
42361 +                                    speed;}
42362 +                  )) ;
42363 +       DWC_PRINTF("  Max packet size: %d\n",
42364 +                  usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
42365 +       DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);
42366 +       DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",
42367 +                  urb->transfer_buffer, (void *)urb->transfer_dma);
42368 +       DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",
42369 +                  urb->setup_packet, (void *)urb->setup_dma);
42370 +       DWC_PRINTF("  Interval: %d\n", urb->interval);
42371 +       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
42372 +               int i;
42373 +               for (i = 0; i < urb->number_of_packets; i++) {
42374 +                       DWC_PRINTF("  ISO Desc %d:\n", i);
42375 +                       DWC_PRINTF("    offset: %d, length %d\n",
42376 +                                  urb->iso_frame_desc[i].offset,
42377 +                                  urb->iso_frame_desc[i].length);
42378 +               }
42379 +       }
42380 +}
42381 +#endif
42382 +
42383 +/** Starts processing a USB transfer request specified by a USB Request Block
42384 + * (URB). mem_flags indicates the type of memory allocation to use while
42385 + * processing this URB. */
42386 +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
42387 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42388 +                      struct usb_host_endpoint *ep,
42389 +#endif
42390 +                      struct urb *urb, gfp_t mem_flags)
42391 +{
42392 +       int retval = 0;
42393 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
42394 +       struct usb_host_endpoint *ep = urb->ep;
42395 +#endif
42396 +#if USB_URB_EP_LINKING
42397 +       dwc_irqflags_t irqflags;
42398 +#endif
42399 +        void **ref_ep_hcpriv = &ep->hcpriv;
42400 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42401 +       dwc_otg_hcd_urb_t *dwc_otg_urb;
42402 +       int i;
42403 +       int alloc_bandwidth = 0;
42404 +       uint8_t ep_type = 0;
42405 +       uint32_t flags = 0;
42406 +       void *buf;
42407 +
42408 +#ifdef DEBUG
42409 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42410 +               dump_urb_info(urb, "dwc_otg_urb_enqueue");
42411 +       }
42412 +#endif
42413 +
42414 +       if (!urb->transfer_buffer && urb->transfer_buffer_length)
42415 +               return -EINVAL;
42416 +
42417 +       if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
42418 +           || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
42419 +               if (!dwc_otg_hcd_is_bandwidth_allocated
42420 +                   (dwc_otg_hcd, ref_ep_hcpriv)) {
42421 +                       alloc_bandwidth = 1;
42422 +               }
42423 +       }
42424 +
42425 +       switch (usb_pipetype(urb->pipe)) {
42426 +       case PIPE_CONTROL:
42427 +               ep_type = USB_ENDPOINT_XFER_CONTROL;
42428 +               break;
42429 +       case PIPE_ISOCHRONOUS:
42430 +               ep_type = USB_ENDPOINT_XFER_ISOC;
42431 +               break;
42432 +       case PIPE_BULK:
42433 +               ep_type = USB_ENDPOINT_XFER_BULK;
42434 +               break;
42435 +       case PIPE_INTERRUPT:
42436 +               ep_type = USB_ENDPOINT_XFER_INT;
42437 +               break;
42438 +       default:
42439 +                DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));
42440 +       }
42441 +
42442 +        /* # of packets is often 0 - do we really need to call this then? */
42443 +       dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
42444 +                                           urb->number_of_packets,
42445 +                                           mem_flags == GFP_ATOMIC ? 1 : 0);
42446 +
42447 +       if(dwc_otg_urb == NULL)
42448 +               return -ENOMEM;
42449 +
42450 +        urb->hcpriv = dwc_otg_urb;
42451 +        if (!dwc_otg_urb && urb->number_of_packets)
42452 +                return -ENOMEM;
42453 +
42454 +       dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
42455 +                                    usb_pipeendpoint(urb->pipe), ep_type,
42456 +                                    usb_pipein(urb->pipe),
42457 +                                    usb_maxpacket(urb->dev, urb->pipe,
42458 +                                                  !(usb_pipein(urb->pipe))));
42459 +
42460 +       buf = urb->transfer_buffer;
42461 +       if (hcd->self.uses_dma) {
42462 +               /*
42463 +                * Calculate virtual address from physical address,
42464 +                * because some class driver may not fill transfer_buffer.
42465 +                * In Buffer DMA mode virual address is used,
42466 +                * when handling non DWORD aligned buffers.
42467 +                */
42468 +               //buf = phys_to_virt(urb->transfer_dma);
42469 +                // DMA addresses are bus addresses not physical addresses!
42470 +                buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
42471 +       }
42472 +
42473 +       if (!(urb->transfer_flags & URB_NO_INTERRUPT))
42474 +               flags |= URB_GIVEBACK_ASAP;
42475 +       if (urb->transfer_flags & URB_ZERO_PACKET)
42476 +               flags |= URB_SEND_ZERO_PACKET;
42477 +
42478 +       dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
42479 +                                  urb->transfer_dma,
42480 +                                  urb->transfer_buffer_length,
42481 +                                  urb->setup_packet,
42482 +                                  urb->setup_dma, flags, urb->interval);
42483 +
42484 +       for (i = 0; i < urb->number_of_packets; ++i) {
42485 +               dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
42486 +                                                   urb->
42487 +                                                   iso_frame_desc[i].offset,
42488 +                                                   urb->
42489 +                                                   iso_frame_desc[i].length);
42490 +       }
42491 +
42492 +#if USB_URB_EP_LINKING
42493 +        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42494 +       retval = usb_hcd_link_urb_to_ep(hcd, urb);
42495 +        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42496 +       if (0 == retval)
42497 +#endif
42498 +        {
42499 +                retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
42500 +                                                 /*(dwc_otg_qh_t **)*/
42501 +                                                 ref_ep_hcpriv,
42502 +                                                 mem_flags == GFP_ATOMIC ? 1 : 0);
42503 +                if (0 == retval) {
42504 +                        if (alloc_bandwidth) {
42505 +                                allocate_bus_bandwidth(hcd,
42506 +                                        dwc_otg_hcd_get_ep_bandwidth(
42507 +                                                dwc_otg_hcd, *ref_ep_hcpriv),
42508 +                                                       urb);
42509 +                        }
42510 +                } else {
42511 +#if USB_URB_EP_LINKING
42512 +                       dwc_irqflags_t irqflags;
42513 +                        DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
42514 +                        DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
42515 +                        usb_hcd_unlink_urb_from_ep(hcd, urb);
42516 +                        DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
42517 +#endif
42518 +                        if (retval == -DWC_E_NO_DEVICE) {
42519 +                                retval = -ENODEV;
42520 +                        }
42521 +                }
42522 +        }
42523 +       return retval;
42524 +}
42525 +
42526 +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
42527 + * success.  */
42528 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42529 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
42530 +#else
42531 +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
42532 +#endif
42533 +{
42534 +       dwc_irqflags_t flags;
42535 +       dwc_otg_hcd_t *dwc_otg_hcd;
42536 +        int rc;
42537 +
42538 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
42539 +
42540 +       dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42541 +
42542 +#ifdef DEBUG
42543 +       if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42544 +               dump_urb_info(urb, "dwc_otg_urb_dequeue");
42545 +       }
42546 +#endif
42547 +
42548 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42549 +       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
42550 +       if (0 == rc) {
42551 +               if(urb->hcpriv != NULL) {
42552 +                       dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,
42553 +                                           (dwc_otg_hcd_urb_t *)urb->hcpriv);
42554 +
42555 +                       DWC_FREE(urb->hcpriv);
42556 +                       urb->hcpriv = NULL;
42557 +               }
42558 +        }
42559 +
42560 +        if (0 == rc) {
42561 +               /* Higher layer software sets URB status. */
42562 +#if USB_URB_EP_LINKING
42563 +                usb_hcd_unlink_urb_from_ep(hcd, urb);
42564 +#endif
42565 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42566 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
42567 +                usb_hcd_giveback_urb(hcd, urb);
42568 +#else
42569 +                usb_hcd_giveback_urb(hcd, urb, status);
42570 +#endif
42571 +                if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
42572 +                        DWC_PRINTF("Called usb_hcd_giveback_urb() \n");
42573 +                        DWC_PRINTF("  1urb->status = %d\n", urb->status);
42574 +                }
42575 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");
42576 +        } else {
42577 +               DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42578 +                DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",
42579 +                            rc);
42580 +        }
42581 +
42582 +       return rc;
42583 +}
42584 +
42585 +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
42586 + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
42587 + * must already be dequeued. */
42588 +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42589 +{
42590 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42591 +
42592 +       DWC_DEBUGPL(DBG_HCD,
42593 +                   "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
42594 +                   "endpoint=%d\n", ep->desc.bEndpointAddress,
42595 +                   dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
42596 +       dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
42597 +       ep->hcpriv = NULL;
42598 +}
42599 +
42600 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
42601 +/* Resets endpoint specific parameter values, in current version used to reset
42602 + * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
42603 +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
42604 +{
42605 +       dwc_irqflags_t flags;
42606 +       struct usb_device *udev = NULL;
42607 +       int epnum = usb_endpoint_num(&ep->desc);
42608 +       int is_out = usb_endpoint_dir_out(&ep->desc);
42609 +       int is_control = usb_endpoint_xfer_control(&ep->desc);
42610 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42611 +        struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);
42612 +
42613 +       if (dev)
42614 +               udev = to_usb_device(dev);
42615 +       else
42616 +               return;
42617 +
42618 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
42619 +
42620 +       DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
42621 +       usb_settoggle(udev, epnum, is_out, 0);
42622 +       if (is_control)
42623 +               usb_settoggle(udev, epnum, !is_out, 0);
42624 +
42625 +       if (ep->hcpriv) {
42626 +               dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
42627 +       }
42628 +       DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
42629 +}
42630 +#endif
42631 +
42632 +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
42633 + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
42634 + * interrupt.
42635 + *
42636 + * This function is called by the USB core when an interrupt occurs */
42637 +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
42638 +{
42639 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42640 +       int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
42641 +       if (retval != 0) {
42642 +               S3C2410X_CLEAR_EINTPEND();
42643 +       }
42644 +       return IRQ_RETVAL(retval);
42645 +}
42646 +
42647 +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
42648 + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
42649 + * is the status change indicator for the single root port. Returns 1 if either
42650 + * change indicator is 1, otherwise returns 0. */
42651 +int hub_status_data(struct usb_hcd *hcd, char *buf)
42652 +{
42653 +       dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
42654 +
42655 +       buf[0] = 0;
42656 +       buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
42657 +
42658 +       return (buf[0] != 0);
42659 +}
42660 +
42661 +/** Handles hub class-specific requests. */
42662 +int hub_control(struct usb_hcd *hcd,
42663 +               u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
42664 +{
42665 +       int retval;
42666 +
42667 +       retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
42668 +                                        typeReq, wValue, wIndex, buf, wLength);
42669 +
42670 +       switch (retval) {
42671 +       case -DWC_E_INVALID:
42672 +               retval = -EINVAL;
42673 +               break;
42674 +       }
42675 +
42676 +       return retval;
42677 +}
42678 +
42679 +#endif /* DWC_DEVICE_ONLY */
42680 --- /dev/null
42681 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
42682 @@ -0,0 +1,922 @@
42683 +/* ==========================================================================
42684 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
42685 + * $Revision: #44 $
42686 + * $Date: 2011/10/26 $
42687 + * $Change: 1873028 $
42688 + *
42689 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42690 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
42691 + * otherwise expressly agreed to in writing between Synopsys and you.
42692 + *
42693 + * The Software IS NOT an item of Licensed Software or Licensed Product under
42694 + * any End User Software License Agreement or Agreement for Licensed Product
42695 + * with Synopsys or any supplement thereto. You are permitted to use and
42696 + * redistribute this Software in source and binary forms, with or without
42697 + * modification, provided that redistributions of source code must retain this
42698 + * notice. You may not view, use, disclose, copy or distribute this file or
42699 + * any information contained herein except pursuant to this license grant from
42700 + * Synopsys. If you do not agree with this notice, including the disclaimer
42701 + * below, then you are not authorized to use the Software.
42702 + *
42703 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
42704 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42705 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42706 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
42707 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42708 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42709 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42710 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42711 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42712 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
42713 + * DAMAGE.
42714 + * ========================================================================== */
42715 +#ifndef DWC_DEVICE_ONLY
42716 +
42717 +/**
42718 + * @file
42719 + *
42720 + * This file contains the functions to manage Queue Heads and Queue
42721 + * Transfer Descriptors.
42722 + */
42723 +
42724 +#include "dwc_otg_hcd.h"
42725 +#include "dwc_otg_regs.h"
42726 +
42727 +extern bool microframe_schedule;
42728 +
42729 +/**
42730 + * Free each QTD in the QH's QTD-list then free the QH.  QH should already be
42731 + * removed from a list.  QTD list should already be empty if called from URB
42732 + * Dequeue.
42733 + *
42734 + * @param hcd HCD instance.
42735 + * @param qh The QH to free.
42736 + */
42737 +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
42738 +{
42739 +       dwc_otg_qtd_t *qtd, *qtd_tmp;
42740 +
42741 +       /* Free each QTD in the QTD list */
42742 +       DWC_SPINLOCK(hcd->lock);
42743 +       DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
42744 +               DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
42745 +               dwc_otg_hcd_qtd_free(qtd);
42746 +       }
42747 +
42748 +       if (hcd->core_if->dma_desc_enable) {
42749 +               dwc_otg_hcd_qh_free_ddma(hcd, qh);
42750 +       } else if (qh->dw_align_buf) {
42751 +               uint32_t buf_size;
42752 +               if (qh->ep_type == UE_ISOCHRONOUS) {
42753 +                       buf_size = 4096;
42754 +               } else {
42755 +                       buf_size = hcd->core_if->core_params->max_transfer_size;
42756 +               }
42757 +               DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
42758 +       }
42759 +
42760 +       DWC_FREE(qh);
42761 +       DWC_SPINUNLOCK(hcd->lock);
42762 +       return;
42763 +}
42764 +
42765 +#define BitStuffTime(bytecount)  ((8 * 7* bytecount) / 6)
42766 +#define HS_HOST_DELAY          5       /* nanoseconds */
42767 +#define FS_LS_HOST_DELAY       1000    /* nanoseconds */
42768 +#define HUB_LS_SETUP           333     /* nanoseconds */
42769 +#define NS_TO_US(ns)           ((ns + 500) / 1000)
42770 +                               /* convert & round nanoseconds to microseconds */
42771 +
42772 +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)
42773 +{
42774 +       unsigned long retval;
42775 +
42776 +       switch (speed) {
42777 +       case USB_SPEED_HIGH:
42778 +               if (is_isoc) {
42779 +                       retval =
42780 +                           ((38 * 8 * 2083) +
42781 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42782 +                           HS_HOST_DELAY;
42783 +               } else {
42784 +                       retval =
42785 +                           ((55 * 8 * 2083) +
42786 +                            (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
42787 +                           HS_HOST_DELAY;
42788 +               }
42789 +               break;
42790 +       case USB_SPEED_FULL:
42791 +               if (is_isoc) {
42792 +                       retval =
42793 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42794 +                       if (is_in) {
42795 +                               retval = 7268 + FS_LS_HOST_DELAY + retval;
42796 +                       } else {
42797 +                               retval = 6265 + FS_LS_HOST_DELAY + retval;
42798 +                       }
42799 +               } else {
42800 +                       retval =
42801 +                           (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
42802 +                       retval = 9107 + FS_LS_HOST_DELAY + retval;
42803 +               }
42804 +               break;
42805 +       case USB_SPEED_LOW:
42806 +               if (is_in) {
42807 +                       retval =
42808 +                           (67667 * (31 + 10 * BitStuffTime(bytecount))) /
42809 +                           1000;
42810 +                       retval =
42811 +                           64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42812 +                           retval;
42813 +               } else {
42814 +                       retval =
42815 +                           (66700 * (31 + 10 * BitStuffTime(bytecount))) /
42816 +                           1000;
42817 +                       retval =
42818 +                           64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
42819 +                           retval;
42820 +               }
42821 +               break;
42822 +       default:
42823 +               DWC_WARN("Unknown device speed\n");
42824 +               retval = -1;
42825 +       }
42826 +
42827 +       return NS_TO_US(retval);
42828 +}
42829 +
42830 +/**
42831 + * Initializes a QH structure.
42832 + *
42833 + * @param hcd The HCD state structure for the DWC OTG controller.
42834 + * @param qh  The QH to init.
42835 + * @param urb Holds the information about the device/endpoint that we need
42836 + *           to initialize the QH.
42837 + */
42838 +#define SCHEDULE_SLOP 10
42839 +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
42840 +{
42841 +       char *speed, *type;
42842 +       int dev_speed;
42843 +       uint32_t hub_addr, hub_port;
42844 +
42845 +       dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
42846 +
42847 +       /* Initialize QH */
42848 +       qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
42849 +       qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
42850 +
42851 +       qh->data_toggle = DWC_OTG_HC_PID_DATA0;
42852 +       qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
42853 +       DWC_CIRCLEQ_INIT(&qh->qtd_list);
42854 +       DWC_LIST_INIT(&qh->qh_list_entry);
42855 +       qh->channel = NULL;
42856 +
42857 +       /* FS/LS Enpoint on HS Hub
42858 +        * NOT virtual root hub */
42859 +       dev_speed = hcd->fops->speed(hcd, urb->priv);
42860 +
42861 +       hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
42862 +       qh->do_split = 0;
42863 +       if (microframe_schedule)
42864 +               qh->speed = dev_speed;
42865 +
42866 +
42867 +       if (((dev_speed == USB_SPEED_LOW) ||
42868 +            (dev_speed == USB_SPEED_FULL)) &&
42869 +           (hub_addr != 0 && hub_addr != 1)) {
42870 +               DWC_DEBUGPL(DBG_HCD,
42871 +                           "QH init: EP %d: TT found at hub addr %d, for port %d\n",
42872 +                           dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
42873 +                           hub_port);
42874 +               qh->do_split = 1;
42875 +       }
42876 +
42877 +       if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
42878 +               /* Compute scheduling parameters once and save them. */
42879 +               hprt0_data_t hprt;
42880 +
42881 +               /** @todo Account for split transfers in the bus time. */
42882 +               int bytecount =
42883 +                   dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
42884 +
42885 +               qh->usecs =
42886 +                   calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
42887 +                                 qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),
42888 +                                 bytecount);
42889 +               /* Start in a slightly future (micro)frame. */
42890 +               qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
42891 +                                                   SCHEDULE_SLOP);
42892 +               qh->interval = urb->interval;
42893 +
42894 +#if 0
42895 +               /* Increase interrupt polling rate for debugging. */
42896 +               if (qh->ep_type == UE_INTERRUPT) {
42897 +                       qh->interval = 8;
42898 +               }
42899 +#endif
42900 +               hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
42901 +               if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
42902 +                   ((dev_speed == USB_SPEED_LOW) ||
42903 +                    (dev_speed == USB_SPEED_FULL))) {
42904 +                       qh->interval *= 8;
42905 +                       qh->sched_frame |= 0x7;
42906 +                       qh->start_split_frame = qh->sched_frame;
42907 +               }
42908 +
42909 +       }
42910 +
42911 +       DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
42912 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - qh = %p\n", qh);
42913 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Device Address = %d\n",
42914 +                   dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
42915 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Endpoint %d, %s\n",
42916 +                   dwc_otg_hcd_get_ep_num(&urb->pipe_info),
42917 +                   dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
42918 +       switch (dev_speed) {
42919 +       case USB_SPEED_LOW:
42920 +               qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
42921 +               speed = "low";
42922 +               break;
42923 +       case USB_SPEED_FULL:
42924 +               qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
42925 +               speed = "full";
42926 +               break;
42927 +       case USB_SPEED_HIGH:
42928 +               qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
42929 +               speed = "high";
42930 +               break;
42931 +       default:
42932 +               speed = "?";
42933 +               break;
42934 +       }
42935 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Speed = %s\n", speed);
42936 +
42937 +       switch (qh->ep_type) {
42938 +       case UE_ISOCHRONOUS:
42939 +               type = "isochronous";
42940 +               break;
42941 +       case UE_INTERRUPT:
42942 +               type = "interrupt";
42943 +               break;
42944 +       case UE_CONTROL:
42945 +               type = "control";
42946 +               break;
42947 +       case UE_BULK:
42948 +               type = "bulk";
42949 +               break;
42950 +       default:
42951 +               type = "?";
42952 +               break;
42953 +       }
42954 +
42955 +       DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH  - Type = %s\n", type);
42956 +
42957 +#ifdef DEBUG
42958 +       if (qh->ep_type == UE_INTERRUPT) {
42959 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
42960 +                           qh->usecs);
42961 +               DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
42962 +                           qh->interval);
42963 +       }
42964 +#endif
42965 +
42966 +}
42967 +
42968 +/**
42969 + * This function allocates and initializes a QH.
42970 + *
42971 + * @param hcd The HCD state structure for the DWC OTG controller.
42972 + * @param urb Holds the information about the device/endpoint that we need
42973 + *           to initialize the QH.
42974 + * @param atomic_alloc Flag to do atomic allocation if needed
42975 + *
42976 + * @return Returns pointer to the newly allocated QH, or NULL on error. */
42977 +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
42978 +                                   dwc_otg_hcd_urb_t * urb, int atomic_alloc)
42979 +{
42980 +       dwc_otg_qh_t *qh;
42981 +
42982 +       /* Allocate memory */
42983 +       /** @todo add memflags argument */
42984 +       qh = dwc_otg_hcd_qh_alloc(atomic_alloc);
42985 +       if (qh == NULL) {
42986 +               DWC_ERROR("qh allocation failed");
42987 +               return NULL;
42988 +       }
42989 +
42990 +       qh_init(hcd, qh, urb);
42991 +
42992 +       if (hcd->core_if->dma_desc_enable
42993 +           && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
42994 +               dwc_otg_hcd_qh_free(hcd, qh);
42995 +               return NULL;
42996 +       }
42997 +
42998 +       return qh;
42999 +}
43000 +
43001 +/* microframe_schedule=0 start */
43002 +
43003 +/**
43004 + * Checks that a channel is available for a periodic transfer.
43005 + *
43006 + * @return 0 if successful, negative error code otherise.
43007 + */
43008 +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
43009 +{
43010 +       /*
43011 +        * Currently assuming that there is a dedicated host channnel for each
43012 +        * periodic transaction plus at least one host channel for
43013 +        * non-periodic transactions.
43014 +        */
43015 +       int status;
43016 +       int num_channels;
43017 +
43018 +       num_channels = hcd->core_if->core_params->host_channels;
43019 +       if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)
43020 +           && (hcd->periodic_channels < num_channels - 1)) {
43021 +               status = 0;
43022 +       } else {
43023 +               DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
43024 +                       __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels);    //NOTICE
43025 +               status = -DWC_E_NO_SPACE;
43026 +       }
43027 +
43028 +       return status;
43029 +}
43030 +
43031 +/**
43032 + * Checks that there is sufficient bandwidth for the specified QH in the
43033 + * periodic schedule. For simplicity, this calculation assumes that all the
43034 + * transfers in the periodic schedule may occur in the same (micro)frame.
43035 + *
43036 + * @param hcd The HCD state structure for the DWC OTG controller.
43037 + * @param qh QH containing periodic bandwidth required.
43038 + *
43039 + * @return 0 if successful, negative error code otherwise.
43040 + */
43041 +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43042 +{
43043 +       int status;
43044 +       int16_t max_claimed_usecs;
43045 +
43046 +       status = 0;
43047 +
43048 +       if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
43049 +               /*
43050 +                * High speed mode.
43051 +                * Max periodic usecs is 80% x 125 usec = 100 usec.
43052 +                */
43053 +
43054 +               max_claimed_usecs = 100 - qh->usecs;
43055 +       } else {
43056 +               /*
43057 +                * Full speed mode.
43058 +                * Max periodic usecs is 90% x 1000 usec = 900 usec.
43059 +                */
43060 +               max_claimed_usecs = 900 - qh->usecs;
43061 +       }
43062 +
43063 +       if (hcd->periodic_usecs > max_claimed_usecs) {
43064 +               DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs);        //NOTICE
43065 +               status = -DWC_E_NO_SPACE;
43066 +       }
43067 +
43068 +       return status;
43069 +}
43070 +
43071 +/* microframe_schedule=0 end */
43072 +
43073 +/**
43074 + * Microframe scheduler
43075 + * track the total use in hcd->frame_usecs
43076 + * keep each qh use in qh->frame_usecs
43077 + * when surrendering the qh then donate the time back
43078 + */
43079 +const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
43080 +
43081 +/*
43082 + * called from dwc_otg_hcd.c:dwc_otg_hcd_init
43083 + */
43084 +int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
43085 +{
43086 +       int i;
43087 +       for (i=0; i<8; i++) {
43088 +               _hcd->frame_usecs[i] = max_uframe_usecs[i];
43089 +       }
43090 +       return 0;
43091 +}
43092 +
43093 +static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43094 +{
43095 +       int i;
43096 +       unsigned short utime;
43097 +       int t_left;
43098 +       int ret;
43099 +       int done;
43100 +
43101 +       ret = -1;
43102 +       utime = _qh->usecs;
43103 +       t_left = utime;
43104 +       i = 0;
43105 +       done = 0;
43106 +       while (done == 0) {
43107 +               /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
43108 +               if (utime <= _hcd->frame_usecs[i]) {
43109 +                       _hcd->frame_usecs[i] -= utime;
43110 +                       _qh->frame_usecs[i] += utime;
43111 +                       t_left -= utime;
43112 +                       ret = i;
43113 +                       done = 1;
43114 +                       return ret;
43115 +               } else {
43116 +                       i++;
43117 +                       if (i == 8) {
43118 +                               done = 1;
43119 +                               ret = -1;
43120 +                       }
43121 +               }
43122 +       }
43123 +       return ret;
43124 + }
43125 +
43126 +/*
43127 + * use this for FS apps that can span multiple uframes
43128 +  */
43129 +static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43130 +{
43131 +       int i;
43132 +       int j;
43133 +       unsigned short utime;
43134 +       int t_left;
43135 +       int ret;
43136 +       int done;
43137 +       unsigned short xtime;
43138 +
43139 +       ret = -1;
43140 +       utime = _qh->usecs;
43141 +       t_left = utime;
43142 +       i = 0;
43143 +       done = 0;
43144 +loop:
43145 +       while (done == 0) {
43146 +               if(_hcd->frame_usecs[i] <= 0) {
43147 +                       i++;
43148 +                       if (i == 8) {
43149 +                               done = 1;
43150 +                               ret = -1;
43151 +                       }
43152 +                       goto loop;
43153 +               }
43154 +
43155 +               /*
43156 +                * we need n consecutive slots
43157 +                * so use j as a start slot j plus j+1 must be enough time (for now)
43158 +                */
43159 +               xtime= _hcd->frame_usecs[i];
43160 +               for (j = i+1 ; j < 8 ; j++ ) {
43161 +                       /*
43162 +                        * if we add this frame remaining time to xtime we may
43163 +                        * be OK, if not we need to test j for a complete frame
43164 +                        */
43165 +                       if ((xtime+_hcd->frame_usecs[j]) < utime) {
43166 +                               if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
43167 +                                       j = 8;
43168 +                                       ret = -1;
43169 +                                       continue;
43170 +                               }
43171 +                       }
43172 +                       if (xtime >= utime) {
43173 +                               ret = i;
43174 +                               j = 8;  /* stop loop with a good value ret */
43175 +                               continue;
43176 +                       }
43177 +                       /* add the frame time to x time */
43178 +                       xtime += _hcd->frame_usecs[j];
43179 +                      /* we must have a fully available next frame or break */
43180 +                      if ((xtime < utime)
43181 +                                      && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
43182 +                              ret = -1;
43183 +                              j = 8;  /* stop loop with a bad value ret */
43184 +                              continue;
43185 +                      }
43186 +               }
43187 +               if (ret >= 0) {
43188 +                       t_left = utime;
43189 +                       for (j = i; (t_left>0) && (j < 8); j++ ) {
43190 +                               t_left -= _hcd->frame_usecs[j];
43191 +                               if ( t_left <= 0 ) {
43192 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
43193 +                                       _hcd->frame_usecs[j]= -t_left;
43194 +                                       ret = i;
43195 +                                       done = 1;
43196 +                               } else {
43197 +                                       _qh->frame_usecs[j] += _hcd->frame_usecs[j];
43198 +                                       _hcd->frame_usecs[j] = 0;
43199 +                               }
43200 +                       }
43201 +               } else {
43202 +                       i++;
43203 +                       if (i == 8) {
43204 +                               done = 1;
43205 +                               ret = -1;
43206 +                       }
43207 +               }
43208 +       }
43209 +       return ret;
43210 +}
43211 +
43212 +static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
43213 +{
43214 +       int ret;
43215 +       ret = -1;
43216 +
43217 +       if (_qh->speed == USB_SPEED_HIGH) {
43218 +               /* if this is a hs transaction we need a full frame */
43219 +               ret = find_single_uframe(_hcd, _qh);
43220 +       } else {
43221 +               /* if this is a fs transaction we may need a sequence of frames */
43222 +               ret = find_multi_uframe(_hcd, _qh);
43223 +       }
43224 +       return ret;
43225 +}
43226 +
43227 +/**
43228 + * Checks that the max transfer size allowed in a host channel is large enough
43229 + * to handle the maximum data transfer in a single (micro)frame for a periodic
43230 + * transfer.
43231 + *
43232 + * @param hcd The HCD state structure for the DWC OTG controller.
43233 + * @param qh QH for a periodic endpoint.
43234 + *
43235 + * @return 0 if successful, negative error code otherwise.
43236 + */
43237 +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43238 +{
43239 +       int status;
43240 +       uint32_t max_xfer_size;
43241 +       uint32_t max_channel_xfer_size;
43242 +
43243 +       status = 0;
43244 +
43245 +       max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
43246 +       max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
43247 +
43248 +       if (max_xfer_size > max_channel_xfer_size) {
43249 +               DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
43250 +                               __func__, max_xfer_size, max_channel_xfer_size);        //NOTICE
43251 +               status = -DWC_E_NO_SPACE;
43252 +       }
43253 +
43254 +       return status;
43255 +}
43256 +
43257 +/**
43258 + * Schedules an interrupt or isochronous transfer in the periodic schedule.
43259 + *
43260 + * @param hcd The HCD state structure for the DWC OTG controller.
43261 + * @param qh QH for the periodic transfer. The QH should already contain the
43262 + * scheduling information.
43263 + *
43264 + * @return 0 if successful, negative error code otherwise.
43265 + */
43266 +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43267 +{
43268 +       int status = 0;
43269 +
43270 +       if (microframe_schedule) {
43271 +               int frame;
43272 +               status = find_uframe(hcd, qh);
43273 +               frame = -1;
43274 +               if (status == 0) {
43275 +                       frame = 7;
43276 +               } else {
43277 +                       if (status > 0 )
43278 +                               frame = status-1;
43279 +               }
43280 +
43281 +               /* Set the new frame up */
43282 +               if (frame > -1) {
43283 +                       qh->sched_frame &= ~0x7;
43284 +                       qh->sched_frame |= (frame & 7);
43285 +               }
43286 +
43287 +               if (status != -1)
43288 +                       status = 0;
43289 +       } else {
43290 +               status = periodic_channel_available(hcd);
43291 +               if (status) {
43292 +                       DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__);        //NOTICE
43293 +                       return status;
43294 +               }
43295 +
43296 +               status = check_periodic_bandwidth(hcd, qh);
43297 +       }
43298 +       if (status) {
43299 +               DWC_INFO("%s: Insufficient periodic bandwidth for "
43300 +                           "periodic transfer.\n", __func__);
43301 +               return status;
43302 +       }
43303 +       status = check_max_xfer_size(hcd, qh);
43304 +       if (status) {
43305 +               DWC_INFO("%s: Channel max transfer size too small "
43306 +                           "for periodic transfer.\n", __func__);
43307 +               return status;
43308 +       }
43309 +
43310 +       if (hcd->core_if->dma_desc_enable) {
43311 +               /* Don't rely on SOF and start in ready schedule */
43312 +               DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
43313 +       }
43314 +       else {
43315 +       /* Always start in the inactive schedule. */
43316 +       DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
43317 +       }
43318 +
43319 +       if (!microframe_schedule) {
43320 +               /* Reserve the periodic channel. */
43321 +               hcd->periodic_channels++;
43322 +       }
43323 +
43324 +       /* Update claimed usecs per (micro)frame. */
43325 +       hcd->periodic_usecs += qh->usecs;
43326 +
43327 +       return status;
43328 +}
43329 +
43330 +/**
43331 + * This function adds a QH to either the non periodic or periodic schedule if
43332 + * it is not already in the schedule. If the QH is already in the schedule, no
43333 + * action is taken.
43334 + *
43335 + * @return 0 if successful, negative error code otherwise.
43336 + */
43337 +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43338 +{
43339 +       int status = 0;
43340 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43341 +
43342 +       if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43343 +               /* QH already in a schedule. */
43344 +               return status;
43345 +       }
43346 +
43347 +       /* Add the new QH to the appropriate schedule */
43348 +       if (dwc_qh_is_non_per(qh)) {
43349 +               /* Always start in the inactive schedule. */
43350 +               DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
43351 +                                    &qh->qh_list_entry);
43352 +       } else {
43353 +               status = schedule_periodic(hcd, qh);
43354 +               if ( !hcd->periodic_qh_count ) {
43355 +                       intr_mask.b.sofintr = 1;
43356 +                       DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43357 +                                                               intr_mask.d32, intr_mask.d32);
43358 +               }
43359 +               hcd->periodic_qh_count++;
43360 +       }
43361 +
43362 +       return status;
43363 +}
43364 +
43365 +/**
43366 + * Removes an interrupt or isochronous transfer from the periodic schedule.
43367 + *
43368 + * @param hcd The HCD state structure for the DWC OTG controller.
43369 + * @param qh QH for the periodic transfer.
43370 + */
43371 +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43372 +{
43373 +       int i;
43374 +       DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43375 +
43376 +       /* Update claimed usecs per (micro)frame. */
43377 +       hcd->periodic_usecs -= qh->usecs;
43378 +
43379 +       if (!microframe_schedule) {
43380 +               /* Release the periodic channel reservation. */
43381 +               hcd->periodic_channels--;
43382 +       } else {
43383 +               for (i = 0; i < 8; i++) {
43384 +                       hcd->frame_usecs[i] += qh->frame_usecs[i];
43385 +                       qh->frame_usecs[i] = 0;
43386 +               }
43387 +       }
43388 +}
43389 +
43390 +/**
43391 + * Removes a QH from either the non-periodic or periodic schedule.  Memory is
43392 + * not freed.
43393 + *
43394 + * @param hcd The HCD state structure.
43395 + * @param qh QH to remove from schedule. */
43396 +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
43397 +{
43398 +       gintmsk_data_t intr_mask = {.d32 = 0 };
43399 +
43400 +       if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
43401 +               /* QH is not in a schedule. */
43402 +               return;
43403 +       }
43404 +
43405 +       if (dwc_qh_is_non_per(qh)) {
43406 +               if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
43407 +                       hcd->non_periodic_qh_ptr =
43408 +                           hcd->non_periodic_qh_ptr->next;
43409 +               }
43410 +               DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
43411 +       } else {
43412 +               deschedule_periodic(hcd, qh);
43413 +               hcd->periodic_qh_count--;
43414 +               if( !hcd->periodic_qh_count ) {
43415 +                       intr_mask.b.sofintr = 1;
43416 +                               DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
43417 +                                                                       intr_mask.d32, 0);
43418 +               }
43419 +       }
43420 +}
43421 +
43422 +/**
43423 + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
43424 + * non-periodic schedule. The QH is added to the inactive non-periodic
43425 + * schedule if any QTDs are still attached to the QH.
43426 + *
43427 + * For periodic QHs, the QH is removed from the periodic queued schedule. If
43428 + * there are any QTDs still attached to the QH, the QH is added to either the
43429 + * periodic inactive schedule or the periodic ready schedule and its next
43430 + * scheduled frame is calculated. The QH is placed in the ready schedule if
43431 + * the scheduled frame has been reached already. Otherwise it's placed in the
43432 + * inactive schedule. If there are no QTDs attached to the QH, the QH is
43433 + * completely removed from the periodic schedule.
43434 + */
43435 +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
43436 +                              int sched_next_periodic_split)
43437 +{
43438 +       if (dwc_qh_is_non_per(qh)) {
43439 +               dwc_otg_hcd_qh_remove(hcd, qh);
43440 +               if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43441 +                       /* Add back to inactive non-periodic schedule. */
43442 +                       dwc_otg_hcd_qh_add(hcd, qh);
43443 +               }
43444 +       } else {
43445 +               uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
43446 +
43447 +               if (qh->do_split) {
43448 +                       /* Schedule the next continuing periodic split transfer */
43449 +                       if (sched_next_periodic_split) {
43450 +
43451 +                               qh->sched_frame = frame_number;
43452 +                               if (dwc_frame_num_le(frame_number,
43453 +                                                    dwc_frame_num_inc
43454 +                                                    (qh->start_split_frame,
43455 +                                                     1))) {
43456 +                                       /*
43457 +                                        * Allow one frame to elapse after start
43458 +                                        * split microframe before scheduling
43459 +                                        * complete split, but DONT if we are
43460 +                                        * doing the next start split in the
43461 +                                        * same frame for an ISOC out.
43462 +                                        */
43463 +                                       if ((qh->ep_type != UE_ISOCHRONOUS) ||
43464 +                                           (qh->ep_is_in != 0)) {
43465 +                                               qh->sched_frame =
43466 +                                                   dwc_frame_num_inc(qh->sched_frame, 1);
43467 +                                       }
43468 +                               }
43469 +                       } else {
43470 +                               qh->sched_frame =
43471 +                                   dwc_frame_num_inc(qh->start_split_frame,
43472 +                                                     qh->interval);
43473 +                               if (dwc_frame_num_le
43474 +                                   (qh->sched_frame, frame_number)) {
43475 +                                       qh->sched_frame = frame_number;
43476 +                               }
43477 +                               qh->sched_frame |= 0x7;
43478 +                               qh->start_split_frame = qh->sched_frame;
43479 +                       }
43480 +               } else {
43481 +                       qh->sched_frame =
43482 +                           dwc_frame_num_inc(qh->sched_frame, qh->interval);
43483 +                       if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
43484 +                               qh->sched_frame = frame_number;
43485 +                       }
43486 +               }
43487 +
43488 +               if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
43489 +                       dwc_otg_hcd_qh_remove(hcd, qh);
43490 +               } else {
43491 +                       /*
43492 +                        * Remove from periodic_sched_queued and move to
43493 +                        * appropriate queue.
43494 +                        */
43495 +                       if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||
43496 +                       (!microframe_schedule && qh->sched_frame == frame_number)) {
43497 +                               DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
43498 +                                                  &qh->qh_list_entry);
43499 +                       } else {
43500 +                               DWC_LIST_MOVE_HEAD
43501 +                                   (&hcd->periodic_sched_inactive,
43502 +                                    &qh->qh_list_entry);
43503 +                       }
43504 +               }
43505 +       }
43506 +}
43507 +
43508 +/**
43509 + * This function allocates and initializes a QTD.
43510 + *
43511 + * @param urb The URB to create a QTD from.  Each URB-QTD pair will end up
43512 + *           pointing to each other so each pair should have a unique correlation.
43513 + * @param atomic_alloc Flag to do atomic alloc if needed
43514 + *
43515 + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
43516 +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
43517 +{
43518 +       dwc_otg_qtd_t *qtd;
43519 +
43520 +       qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);
43521 +       if (qtd == NULL) {
43522 +               return NULL;
43523 +       }
43524 +
43525 +       dwc_otg_hcd_qtd_init(qtd, urb);
43526 +       return qtd;
43527 +}
43528 +
43529 +/**
43530 + * Initializes a QTD structure.
43531 + *
43532 + * @param qtd The QTD to initialize.
43533 + * @param urb The URB to use for initialization.  */
43534 +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
43535 +{
43536 +       dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
43537 +       qtd->urb = urb;
43538 +       if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
43539 +               /*
43540 +                * The only time the QTD data toggle is used is on the data
43541 +                * phase of control transfers. This phase always starts with
43542 +                * DATA1.
43543 +                */
43544 +               qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
43545 +               qtd->control_phase = DWC_OTG_CONTROL_SETUP;
43546 +       }
43547 +
43548 +       /* start split */
43549 +       qtd->complete_split = 0;
43550 +       qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
43551 +       qtd->isoc_split_offset = 0;
43552 +       qtd->in_process = 0;
43553 +
43554 +       /* Store the qtd ptr in the urb to reference what QTD. */
43555 +       urb->qtd = qtd;
43556 +       return;
43557 +}
43558 +
43559 +/**
43560 + * This function adds a QTD to the QTD-list of a QH.  It will find the correct
43561 + * QH to place the QTD into.  If it does not find a QH, then it will create a
43562 + * new QH. If the QH to which the QTD is added is not currently scheduled, it
43563 + * is placed into the proper schedule based on its EP type.
43564 + *
43565 + * @param[in] qtd The QTD to add
43566 + * @param[in] hcd The DWC HCD structure
43567 + * @param[out] qh out parameter to return queue head
43568 + * @param atomic_alloc Flag to do atomic alloc if needed
43569 + *
43570 + * @return 0 if successful, negative error code otherwise.
43571 + */
43572 +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
43573 +                       dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
43574 +{
43575 +       int retval = 0;
43576 +       dwc_irqflags_t flags;
43577 +
43578 +       dwc_otg_hcd_urb_t *urb = qtd->urb;
43579 +
43580 +       /*
43581 +        * Get the QH which holds the QTD-list to insert to. Create QH if it
43582 +        * doesn't exist.
43583 +        */
43584 +       if (*qh == NULL) {
43585 +               *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
43586 +               if (*qh == NULL) {
43587 +                       retval = -1;
43588 +                       goto done;
43589 +               }
43590 +       }
43591 +       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
43592 +       retval = dwc_otg_hcd_qh_add(hcd, *qh);
43593 +       if (retval == 0) {
43594 +               DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
43595 +                                       qtd_list_entry);
43596 +       }
43597 +       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
43598 +
43599 +done:
43600 +
43601 +       return retval;
43602 +}
43603 +
43604 +#endif /* DWC_DEVICE_ONLY */
43605 --- /dev/null
43606 +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
43607 @@ -0,0 +1,185 @@
43608 +#ifndef _DWC_OS_DEP_H_
43609 +#define _DWC_OS_DEP_H_
43610 +
43611 +/**
43612 + * @file
43613 + *
43614 + * This file contains OS dependent structures.
43615 + *
43616 + */
43617 +
43618 +#include <linux/kernel.h>
43619 +#include <linux/module.h>
43620 +#include <linux/moduleparam.h>
43621 +#include <linux/init.h>
43622 +#include <linux/device.h>
43623 +#include <linux/errno.h>
43624 +#include <linux/types.h>
43625 +#include <linux/slab.h>
43626 +#include <linux/list.h>
43627 +#include <linux/interrupt.h>
43628 +#include <linux/ctype.h>
43629 +#include <linux/string.h>
43630 +#include <linux/dma-mapping.h>
43631 +#include <linux/jiffies.h>
43632 +#include <linux/delay.h>
43633 +#include <linux/timer.h>
43634 +#include <linux/workqueue.h>
43635 +#include <linux/stat.h>
43636 +#include <linux/pci.h>
43637 +
43638 +#include <linux/version.h>
43639 +
43640 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
43641 +# include <linux/irq.h>
43642 +#endif
43643 +
43644 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
43645 +# include <linux/usb/ch9.h>
43646 +#else
43647 +# include <linux/usb_ch9.h>
43648 +#endif
43649 +
43650 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
43651 +# include <linux/usb/gadget.h>
43652 +#else
43653 +# include <linux/usb_gadget.h>
43654 +#endif
43655 +
43656 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
43657 +# include <asm/irq.h>
43658 +#endif
43659 +
43660 +#ifdef PCI_INTERFACE
43661 +# include <asm/io.h>
43662 +#endif
43663 +
43664 +#ifdef LM_INTERFACE
43665 +# include <asm/unaligned.h>
43666 +# include <asm/sizes.h>
43667 +# include <asm/param.h>
43668 +# include <asm/io.h>
43669 +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
43670 +#  include <asm/arch/hardware.h>
43671 +#  include <asm/arch/lm.h>
43672 +#  include <asm/arch/irqs.h>
43673 +#  include <asm/arch/regs-irq.h>
43674 +# else
43675 +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
43676 +   here we assume that the machine architecture provides definitions
43677 +   in its own header
43678 +*/
43679 +#  include <mach/lm.h>
43680 +#  include <mach/hardware.h>
43681 +# endif
43682 +#endif
43683 +
43684 +#ifdef PLATFORM_INTERFACE
43685 +#include <linux/platform_device.h>
43686 +#include <asm/mach/map.h>
43687 +#endif
43688 +
43689 +/** The OS page size */
43690 +#define DWC_OS_PAGE_SIZE       PAGE_SIZE
43691 +
43692 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
43693 +typedef int gfp_t;
43694 +#endif
43695 +
43696 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
43697 +# define IRQF_SHARED SA_SHIRQ
43698 +#endif
43699 +
43700 +typedef struct os_dependent {
43701 +       /** Base address returned from ioremap() */
43702 +       void *base;
43703 +
43704 +       /** Register offset for Diagnostic API */
43705 +       uint32_t reg_offset;
43706 +
43707 +#ifdef LM_INTERFACE
43708 +       struct lm_device *lmdev;
43709 +#elif  defined(PCI_INTERFACE)
43710 +       struct pci_dev *pcidev;
43711 +
43712 +       /** Start address of a PCI region */
43713 +       resource_size_t rsrc_start;
43714 +
43715 +       /** Length address of a PCI region */
43716 +       resource_size_t rsrc_len;
43717 +#elif  defined(PLATFORM_INTERFACE)
43718 +       struct platform_device *platformdev;
43719 +#endif
43720 +
43721 +} os_dependent_t;
43722 +
43723 +#ifdef __cplusplus
43724 +}
43725 +#endif
43726 +
43727 +
43728 +
43729 +/* Type for the our device on the chosen bus */
43730 +#if   defined(LM_INTERFACE)
43731 +typedef struct lm_device       dwc_bus_dev_t;
43732 +#elif defined(PCI_INTERFACE)
43733 +typedef struct pci_dev         dwc_bus_dev_t;
43734 +#elif defined(PLATFORM_INTERFACE)
43735 +typedef struct platform_device dwc_bus_dev_t;
43736 +#endif
43737 +
43738 +/* Helper macro to retrieve drvdata from the device on the chosen bus */
43739 +#if    defined(LM_INTERFACE)
43740 +#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)
43741 +#elif  defined(PCI_INTERFACE)
43742 +#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)
43743 +#elif  defined(PLATFORM_INTERFACE)
43744 +#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)
43745 +#endif
43746 +
43747 +/**
43748 + * Helper macro returning the otg_device structure of a given struct device
43749 + *
43750 + * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
43751 + */
43752 +#ifdef LM_INTERFACE
43753 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43754 +                struct lm_device *lm_dev = \
43755 +                        container_of(_dev, struct lm_device, dev); \
43756 +                _var = lm_get_drvdata(lm_dev); \
43757 +        } while (0)
43758 +
43759 +#elif defined(PCI_INTERFACE)
43760 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43761 +                _var = dev_get_drvdata(_dev); \
43762 +        } while (0)
43763 +
43764 +#elif defined(PLATFORM_INTERFACE)
43765 +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
43766 +                struct platform_device *platform_dev = \
43767 +                        container_of(_dev, struct platform_device, dev); \
43768 +                _var = platform_get_drvdata(platform_dev); \
43769 +        } while (0)
43770 +#endif
43771 +
43772 +
43773 +/**
43774 + * Helper macro returning the struct dev of the given struct os_dependent
43775 + *
43776 + * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)
43777 + */
43778 +#ifdef LM_INTERFACE
43779 +#define DWC_OTG_OS_GETDEV(_osdep) \
43780 +        ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)
43781 +#elif defined(PCI_INTERFACE)
43782 +#define DWC_OTG_OS_GETDEV(_osdep) \
43783 +        ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)
43784 +#elif defined(PLATFORM_INTERFACE)
43785 +#define DWC_OTG_OS_GETDEV(_osdep) \
43786 +        ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)
43787 +#endif
43788 +
43789 +
43790 +
43791 +
43792 +#endif /* _DWC_OS_DEP_H_ */
43793 --- /dev/null
43794 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
43795 @@ -0,0 +1,2708 @@
43796 +/* ==========================================================================
43797 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
43798 + * $Revision: #101 $
43799 + * $Date: 2012/08/10 $
43800 + * $Change: 2047372 $
43801 + *
43802 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
43803 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
43804 + * otherwise expressly agreed to in writing between Synopsys and you.
43805 + *
43806 + * The Software IS NOT an item of Licensed Software or Licensed Product under
43807 + * any End User Software License Agreement or Agreement for Licensed Product
43808 + * with Synopsys or any supplement thereto. You are permitted to use and
43809 + * redistribute this Software in source and binary forms, with or without
43810 + * modification, provided that redistributions of source code must retain this
43811 + * notice. You may not view, use, disclose, copy or distribute this file or
43812 + * any information contained herein except pursuant to this license grant from
43813 + * Synopsys. If you do not agree with this notice, including the disclaimer
43814 + * below, then you are not authorized to use the Software.
43815 + *
43816 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
43817 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43818 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43819 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
43820 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43821 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43822 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
43823 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43824 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43825 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
43826 + * DAMAGE.
43827 + * ========================================================================== */
43828 +#ifndef DWC_HOST_ONLY
43829 +
43830 +/** @file
43831 + * This file implements PCD Core. All code in this file is portable and doesn't
43832 + * use any OS specific functions.
43833 + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
43834 + * header file, which can be used to implement OS specific PCD interface.
43835 + *
43836 + * An important function of the PCD is managing interrupts generated
43837 + * by the DWC_otg controller. The implementation of the DWC_otg device
43838 + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
43839 + *
43840 + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
43841 + * @todo Does it work when the request size is greater than DEPTSIZ
43842 + * transfer size
43843 + *
43844 + */
43845 +
43846 +#include "dwc_otg_pcd.h"
43847 +
43848 +#ifdef DWC_UTE_CFI
43849 +#include "dwc_otg_cfi.h"
43850 +
43851 +extern int init_cfi(cfiobject_t * cfiobj);
43852 +#endif
43853 +
43854 +/**
43855 + * Choose endpoint from ep arrays using usb_ep structure.
43856 + */
43857 +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
43858 +{
43859 +       int i;
43860 +       if (pcd->ep0.priv == handle) {
43861 +               return &pcd->ep0;
43862 +       }
43863 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
43864 +               if (pcd->in_ep[i].priv == handle)
43865 +                       return &pcd->in_ep[i];
43866 +               if (pcd->out_ep[i].priv == handle)
43867 +                       return &pcd->out_ep[i];
43868 +       }
43869 +
43870 +       return NULL;
43871 +}
43872 +
43873 +/**
43874 + * This function completes a request.  It call's the request call back.
43875 + */
43876 +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
43877 +                         int32_t status)
43878 +{
43879 +       unsigned stopped = ep->stopped;
43880 +
43881 +       DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
43882 +       DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
43883 +
43884 +       /* don't modify queue heads during completion callback */
43885 +       ep->stopped = 1;
43886 +       /* spin_unlock/spin_lock now done in fops->complete() */
43887 +       ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
43888 +                               req->actual);
43889 +
43890 +       if (ep->pcd->request_pending > 0) {
43891 +               --ep->pcd->request_pending;
43892 +       }
43893 +
43894 +       ep->stopped = stopped;
43895 +       DWC_FREE(req);
43896 +}
43897 +
43898 +/**
43899 + * This function terminates all the requsts in the EP request queue.
43900 + */
43901 +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
43902 +{
43903 +       dwc_otg_pcd_request_t *req;
43904 +
43905 +       ep->stopped = 1;
43906 +
43907 +       /* called with irqs blocked?? */
43908 +       while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
43909 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
43910 +               dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
43911 +       }
43912 +}
43913 +
43914 +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
43915 +                      const struct dwc_otg_pcd_function_ops *fops)
43916 +{
43917 +       pcd->fops = fops;
43918 +}
43919 +
43920 +/**
43921 + * PCD Callback function for initializing the PCD when switching to
43922 + * device mode.
43923 + *
43924 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43925 + */
43926 +static int32_t dwc_otg_pcd_start_cb(void *p)
43927 +{
43928 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43929 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
43930 +
43931 +       /*
43932 +        * Initialized the Core for Device mode.
43933 +        */
43934 +       if (dwc_otg_is_device_mode(core_if)) {
43935 +               dwc_otg_core_dev_init(core_if);
43936 +               /* Set core_if's lock pointer to the pcd->lock */
43937 +               core_if->lock = pcd->lock;
43938 +       }
43939 +       return 1;
43940 +}
43941 +
43942 +/** CFI-specific buffer allocation function for EP */
43943 +#ifdef DWC_UTE_CFI
43944 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
43945 +                             size_t buflen, int flags)
43946 +{
43947 +       dwc_otg_pcd_ep_t *ep;
43948 +       ep = get_ep_from_handle(pcd, pep);
43949 +       if (!ep) {
43950 +               DWC_WARN("bad ep\n");
43951 +               return -DWC_E_INVALID;
43952 +       }
43953 +
43954 +       return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
43955 +                                         flags);
43956 +}
43957 +#else
43958 +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
43959 +                             size_t buflen, int flags);
43960 +#endif
43961 +
43962 +/**
43963 + * PCD Callback function for notifying the PCD when resuming from
43964 + * suspend.
43965 + *
43966 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43967 + */
43968 +static int32_t dwc_otg_pcd_resume_cb(void *p)
43969 +{
43970 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43971 +
43972 +       if (pcd->fops->resume) {
43973 +               pcd->fops->resume(pcd);
43974 +       }
43975 +
43976 +       /* Stop the SRP timeout timer. */
43977 +       if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
43978 +           || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
43979 +               if (GET_CORE_IF(pcd)->srp_timer_started) {
43980 +                       GET_CORE_IF(pcd)->srp_timer_started = 0;
43981 +                       DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
43982 +               }
43983 +       }
43984 +       return 1;
43985 +}
43986 +
43987 +/**
43988 + * PCD Callback function for notifying the PCD device is suspended.
43989 + *
43990 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
43991 + */
43992 +static int32_t dwc_otg_pcd_suspend_cb(void *p)
43993 +{
43994 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
43995 +
43996 +       if (pcd->fops->suspend) {
43997 +               DWC_SPINUNLOCK(pcd->lock);
43998 +               pcd->fops->suspend(pcd);
43999 +               DWC_SPINLOCK(pcd->lock);
44000 +       }
44001 +
44002 +       return 1;
44003 +}
44004 +
44005 +/**
44006 + * PCD Callback function for stopping the PCD when switching to Host
44007 + * mode.
44008 + *
44009 + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
44010 + */
44011 +static int32_t dwc_otg_pcd_stop_cb(void *p)
44012 +{
44013 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
44014 +       extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
44015 +
44016 +       dwc_otg_pcd_stop(pcd);
44017 +       return 1;
44018 +}
44019 +
44020 +/**
44021 + * PCD Callback structure for handling mode switching.
44022 + */
44023 +static dwc_otg_cil_callbacks_t pcd_callbacks = {
44024 +       .start = dwc_otg_pcd_start_cb,
44025 +       .stop = dwc_otg_pcd_stop_cb,
44026 +       .suspend = dwc_otg_pcd_suspend_cb,
44027 +       .resume_wakeup = dwc_otg_pcd_resume_cb,
44028 +       .p = 0,                 /* Set at registration */
44029 +};
44030 +
44031 +/**
44032 + * This function allocates a DMA Descriptor chain for the Endpoint
44033 + * buffer to be used for a transfer to/from the specified endpoint.
44034 + */
44035 +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
44036 +                                                   uint32_t count)
44037 +{
44038 +       return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t),
44039 +                                                       dma_desc_addr);
44040 +}
44041 +
44042 +/**
44043 + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
44044 + */
44045 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
44046 +                               uint32_t dma_desc_addr, uint32_t count)
44047 +{
44048 +       DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
44049 +                    dma_desc_addr);
44050 +}
44051 +
44052 +#ifdef DWC_EN_ISOC
44053 +
44054 +/**
44055 + * This function initializes a descriptor chain for Isochronous transfer
44056 + *
44057 + * @param core_if Programming view of DWC_otg controller.
44058 + * @param dwc_ep The EP to start the transfer on.
44059 + *
44060 + */
44061 +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
44062 +                                       dwc_ep_t * dwc_ep)
44063 +{
44064 +
44065 +       dsts_data_t dsts = {.d32 = 0 };
44066 +       depctl_data_t depctl = {.d32 = 0 };
44067 +       volatile uint32_t *addr;
44068 +       int i, j;
44069 +       uint32_t len;
44070 +
44071 +       if (dwc_ep->is_in)
44072 +               dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
44073 +       else
44074 +               dwc_ep->desc_cnt =
44075 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44076 +                   dwc_ep->bInterval;
44077 +
44078 +       /** Allocate descriptors for double buffering */
44079 +       dwc_ep->iso_desc_addr =
44080 +           dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
44081 +                                       dwc_ep->desc_cnt * 2);
44082 +       if (dwc_ep->desc_addr) {
44083 +               DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
44084 +               return;
44085 +       }
44086 +
44087 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44088 +
44089 +       /** ISO OUT EP */
44090 +       if (dwc_ep->is_in == 0) {
44091 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44092 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44093 +               dma_addr_t dma_ad;
44094 +               uint32_t data_per_desc;
44095 +               dwc_otg_dev_out_ep_regs_t *out_regs =
44096 +                   core_if->dev_if->out_ep_regs[dwc_ep->num];
44097 +               int offset;
44098 +
44099 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
44100 +               dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
44101 +
44102 +               /** Buffer 0 descriptors setup */
44103 +               dma_ad = dwc_ep->dma_addr0;
44104 +
44105 +               sts.b_iso_out.bs = BS_HOST_READY;
44106 +               sts.b_iso_out.rxsts = 0;
44107 +               sts.b_iso_out.l = 0;
44108 +               sts.b_iso_out.sp = 0;
44109 +               sts.b_iso_out.ioc = 0;
44110 +               sts.b_iso_out.pid = 0;
44111 +               sts.b_iso_out.framenum = 0;
44112 +
44113 +               offset = 0;
44114 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44115 +                    i += dwc_ep->pkt_per_frm) {
44116 +
44117 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44118 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44119 +                               if (len > dwc_ep->data_per_frame)
44120 +                                       data_per_desc =
44121 +                                           dwc_ep->data_per_frame -
44122 +                                           j * dwc_ep->maxpacket;
44123 +                               else
44124 +                                       data_per_desc = dwc_ep->maxpacket;
44125 +                               len = data_per_desc % 4;
44126 +                               if (len)
44127 +                                       data_per_desc += 4 - len;
44128 +
44129 +                               sts.b_iso_out.rxbytes = data_per_desc;
44130 +                               dma_desc->buf = dma_ad;
44131 +                               dma_desc->status.d32 = sts.d32;
44132 +
44133 +                               offset += data_per_desc;
44134 +                               dma_desc++;
44135 +                               dma_ad += data_per_desc;
44136 +                       }
44137 +               }
44138 +
44139 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44140 +                       uint32_t len = (j + 1) * dwc_ep->maxpacket;
44141 +                       if (len > dwc_ep->data_per_frame)
44142 +                               data_per_desc =
44143 +                                   dwc_ep->data_per_frame -
44144 +                                   j * dwc_ep->maxpacket;
44145 +                       else
44146 +                               data_per_desc = dwc_ep->maxpacket;
44147 +                       len = data_per_desc % 4;
44148 +                       if (len)
44149 +                               data_per_desc += 4 - len;
44150 +                       sts.b_iso_out.rxbytes = data_per_desc;
44151 +                       dma_desc->buf = dma_ad;
44152 +                       dma_desc->status.d32 = sts.d32;
44153 +
44154 +                       offset += data_per_desc;
44155 +                       dma_desc++;
44156 +                       dma_ad += data_per_desc;
44157 +               }
44158 +
44159 +               sts.b_iso_out.ioc = 1;
44160 +               len = (j + 1) * dwc_ep->maxpacket;
44161 +               if (len > dwc_ep->data_per_frame)
44162 +                       data_per_desc =
44163 +                           dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
44164 +               else
44165 +                       data_per_desc = dwc_ep->maxpacket;
44166 +               len = data_per_desc % 4;
44167 +               if (len)
44168 +                       data_per_desc += 4 - len;
44169 +               sts.b_iso_out.rxbytes = data_per_desc;
44170 +
44171 +               dma_desc->buf = dma_ad;
44172 +               dma_desc->status.d32 = sts.d32;
44173 +               dma_desc++;
44174 +
44175 +               /** Buffer 1 descriptors setup */
44176 +               sts.b_iso_out.ioc = 0;
44177 +               dma_ad = dwc_ep->dma_addr1;
44178 +
44179 +               offset = 0;
44180 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44181 +                    i += dwc_ep->pkt_per_frm) {
44182 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
44183 +                               uint32_t len = (j + 1) * dwc_ep->maxpacket;
44184 +                               if (len > dwc_ep->data_per_frame)
44185 +                                       data_per_desc =
44186 +                                           dwc_ep->data_per_frame -
44187 +                                           j * dwc_ep->maxpacket;
44188 +                               else
44189 +                                       data_per_desc = dwc_ep->maxpacket;
44190 +                               len = data_per_desc % 4;
44191 +                               if (len)
44192 +                                       data_per_desc += 4 - len;
44193 +
44194 +                               data_per_desc =
44195 +                                   sts.b_iso_out.rxbytes = data_per_desc;
44196 +                               dma_desc->buf = dma_ad;
44197 +                               dma_desc->status.d32 = sts.d32;
44198 +
44199 +                               offset += data_per_desc;
44200 +                               dma_desc++;
44201 +                               dma_ad += data_per_desc;
44202 +                       }
44203 +               }
44204 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
44205 +                       data_per_desc =
44206 +                           ((j + 1) * dwc_ep->maxpacket >
44207 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44208 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44209 +                       data_per_desc +=
44210 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44211 +                       sts.b_iso_out.rxbytes = data_per_desc;
44212 +                       dma_desc->buf = dma_ad;
44213 +                       dma_desc->status.d32 = sts.d32;
44214 +
44215 +                       offset += data_per_desc;
44216 +                       dma_desc++;
44217 +                       dma_ad += data_per_desc;
44218 +               }
44219 +
44220 +               sts.b_iso_out.ioc = 1;
44221 +               sts.b_iso_out.l = 1;
44222 +               data_per_desc =
44223 +                   ((j + 1) * dwc_ep->maxpacket >
44224 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
44225 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
44226 +               data_per_desc +=
44227 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
44228 +               sts.b_iso_out.rxbytes = data_per_desc;
44229 +
44230 +               dma_desc->buf = dma_ad;
44231 +               dma_desc->status.d32 = sts.d32;
44232 +
44233 +               dwc_ep->next_frame = 0;
44234 +
44235 +               /** Write dma_ad into DOEPDMA register */
44236 +               DWC_WRITE_REG32(&(out_regs->doepdma),
44237 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44238 +
44239 +       }
44240 +       /** ISO IN EP */
44241 +       else {
44242 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
44243 +               dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
44244 +               dma_addr_t dma_ad;
44245 +               dwc_otg_dev_in_ep_regs_t *in_regs =
44246 +                   core_if->dev_if->in_ep_regs[dwc_ep->num];
44247 +               unsigned int frmnumber;
44248 +               fifosize_data_t txfifosize, rxfifosize;
44249 +
44250 +               txfifosize.d32 =
44251 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
44252 +                                  dtxfsts);
44253 +               rxfifosize.d32 =
44254 +                   DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
44255 +
44256 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
44257 +
44258 +               dma_ad = dwc_ep->dma_addr0;
44259 +
44260 +               dsts.d32 =
44261 +                   DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44262 +
44263 +               sts.b_iso_in.bs = BS_HOST_READY;
44264 +               sts.b_iso_in.txsts = 0;
44265 +               sts.b_iso_in.sp =
44266 +                   (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
44267 +               sts.b_iso_in.ioc = 0;
44268 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
44269 +
44270 +               frmnumber = dwc_ep->next_frame;
44271 +
44272 +               sts.b_iso_in.framenum = frmnumber;
44273 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
44274 +               sts.b_iso_in.l = 0;
44275 +
44276 +               /** Buffer 0 descriptors setup */
44277 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
44278 +                       dma_desc->buf = dma_ad;
44279 +                       dma_desc->status.d32 = sts.d32;
44280 +                       dma_desc++;
44281 +
44282 +                       dma_ad += dwc_ep->data_per_frame;
44283 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44284 +               }
44285 +
44286 +               sts.b_iso_in.ioc = 1;
44287 +               dma_desc->buf = dma_ad;
44288 +               dma_desc->status.d32 = sts.d32;
44289 +               ++dma_desc;
44290 +
44291 +               /** Buffer 1 descriptors setup */
44292 +               sts.b_iso_in.ioc = 0;
44293 +               dma_ad = dwc_ep->dma_addr1;
44294 +
44295 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
44296 +                    i += dwc_ep->pkt_per_frm) {
44297 +                       dma_desc->buf = dma_ad;
44298 +                       dma_desc->status.d32 = sts.d32;
44299 +                       dma_desc++;
44300 +
44301 +                       dma_ad += dwc_ep->data_per_frame;
44302 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
44303 +
44304 +                       sts.b_iso_in.ioc = 0;
44305 +               }
44306 +               sts.b_iso_in.ioc = 1;
44307 +               sts.b_iso_in.l = 1;
44308 +
44309 +               dma_desc->buf = dma_ad;
44310 +               dma_desc->status.d32 = sts.d32;
44311 +
44312 +               dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
44313 +
44314 +               /** Write dma_ad into diepdma register */
44315 +               DWC_WRITE_REG32(&(in_regs->diepdma),
44316 +                               (uint32_t) dwc_ep->iso_dma_desc_addr);
44317 +       }
44318 +       /** Enable endpoint, clear nak  */
44319 +       depctl.d32 = 0;
44320 +       depctl.b.epena = 1;
44321 +       depctl.b.usbactep = 1;
44322 +       depctl.b.cnak = 1;
44323 +
44324 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44325 +       depctl.d32 = DWC_READ_REG32(addr);
44326 +}
44327 +
44328 +/**
44329 + * This function initializes a descriptor chain for Isochronous transfer
44330 + *
44331 + * @param core_if Programming view of DWC_otg controller.
44332 + * @param ep The EP to start the transfer on.
44333 + *
44334 + */
44335 +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
44336 +                                      dwc_ep_t * ep)
44337 +{
44338 +       depctl_data_t depctl = {.d32 = 0 };
44339 +       volatile uint32_t *addr;
44340 +
44341 +       if (ep->is_in) {
44342 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44343 +       } else {
44344 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44345 +       }
44346 +
44347 +       if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
44348 +               return;
44349 +       } else {
44350 +               deptsiz_data_t deptsiz = {.d32 = 0 };
44351 +
44352 +               ep->xfer_len =
44353 +                   ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
44354 +               ep->pkt_cnt =
44355 +                   (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44356 +               ep->xfer_count = 0;
44357 +               ep->xfer_buff =
44358 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44359 +               ep->dma_addr =
44360 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44361 +
44362 +               if (ep->is_in) {
44363 +                       /* Program the transfer size and packet count
44364 +                        *      as follows: xfersize = N * maxpacket +
44365 +                        *      short_packet pktcnt = N + (short_packet
44366 +                        *      exist ? 1 : 0)
44367 +                        */
44368 +                       deptsiz.b.mc = ep->pkt_per_frm;
44369 +                       deptsiz.b.xfersize = ep->xfer_len;
44370 +                       deptsiz.b.pktcnt =
44371 +                           (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
44372 +                       DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
44373 +                                       dieptsiz, deptsiz.d32);
44374 +
44375 +                       /* Write the DMA register */
44376 +                       DWC_WRITE_REG32(&
44377 +                                       (core_if->dev_if->in_ep_regs[ep->num]->
44378 +                                        diepdma), (uint32_t) ep->dma_addr);
44379 +
44380 +               } else {
44381 +                       deptsiz.b.pktcnt =
44382 +                           (ep->xfer_len + (ep->maxpacket - 1)) /
44383 +                           ep->maxpacket;
44384 +                       deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
44385 +
44386 +                       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
44387 +                                       doeptsiz, deptsiz.d32);
44388 +
44389 +                       /* Write the DMA register */
44390 +                       DWC_WRITE_REG32(&
44391 +                                       (core_if->dev_if->out_ep_regs[ep->num]->
44392 +                                        doepdma), (uint32_t) ep->dma_addr);
44393 +
44394 +               }
44395 +               /** Enable endpoint, clear nak  */
44396 +               depctl.d32 = 0;
44397 +               depctl.b.epena = 1;
44398 +               depctl.b.cnak = 1;
44399 +
44400 +               DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
44401 +       }
44402 +}
44403 +
44404 +/**
44405 + * This function does the setup for a data transfer for an EP and
44406 + * starts the transfer. For an IN transfer, the packets will be
44407 + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
44408 + * the packets are unloaded from the Rx FIFO in the ISR.
44409 + *
44410 + * @param core_if Programming view of DWC_otg controller.
44411 + * @param ep The EP to start the transfer on.
44412 + */
44413 +
44414 +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
44415 +                                         dwc_ep_t * ep)
44416 +{
44417 +       if (core_if->dma_enable) {
44418 +               if (core_if->dma_desc_enable) {
44419 +                       if (ep->is_in) {
44420 +                               ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
44421 +                       } else {
44422 +                               ep->desc_cnt = ep->pkt_cnt;
44423 +                       }
44424 +                       dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
44425 +               } else {
44426 +                       if (core_if->pti_enh_enable) {
44427 +                               dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
44428 +                       } else {
44429 +                               ep->cur_pkt_addr =
44430 +                                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
44431 +                                   xfer_buff0;
44432 +                               ep->cur_pkt_dma_addr =
44433 +                                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->
44434 +                                   dma_addr0;
44435 +                               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44436 +                       }
44437 +               }
44438 +       } else {
44439 +               ep->cur_pkt_addr =
44440 +                   (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
44441 +               ep->cur_pkt_dma_addr =
44442 +                   (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
44443 +               dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
44444 +       }
44445 +}
44446 +
44447 +/**
44448 + * This function stops transfer for an EP and
44449 + * resets the ep's variables.
44450 + *
44451 + * @param core_if Programming view of DWC_otg controller.
44452 + * @param ep The EP to start the transfer on.
44453 + */
44454 +
44455 +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
44456 +{
44457 +       depctl_data_t depctl = {.d32 = 0 };
44458 +       volatile uint32_t *addr;
44459 +
44460 +       if (ep->is_in == 1) {
44461 +               addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
44462 +       } else {
44463 +               addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
44464 +       }
44465 +
44466 +       /* disable the ep */
44467 +       depctl.d32 = DWC_READ_REG32(addr);
44468 +
44469 +       depctl.b.epdis = 1;
44470 +       depctl.b.snak = 1;
44471 +
44472 +       DWC_WRITE_REG32(addr, depctl.d32);
44473 +
44474 +       if (core_if->dma_desc_enable &&
44475 +           ep->iso_desc_addr && ep->iso_dma_desc_addr) {
44476 +               dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
44477 +                                          ep->iso_dma_desc_addr,
44478 +                                          ep->desc_cnt * 2);
44479 +       }
44480 +
44481 +       /* reset varibales */
44482 +       ep->dma_addr0 = 0;
44483 +       ep->dma_addr1 = 0;
44484 +       ep->xfer_buff0 = 0;
44485 +       ep->xfer_buff1 = 0;
44486 +       ep->data_per_frame = 0;
44487 +       ep->data_pattern_frame = 0;
44488 +       ep->sync_frame = 0;
44489 +       ep->buf_proc_intrvl = 0;
44490 +       ep->bInterval = 0;
44491 +       ep->proc_buf_num = 0;
44492 +       ep->pkt_per_frm = 0;
44493 +       ep->pkt_per_frm = 0;
44494 +       ep->desc_cnt = 0;
44495 +       ep->iso_desc_addr = 0;
44496 +       ep->iso_dma_desc_addr = 0;
44497 +}
44498 +
44499 +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
44500 +                            uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
44501 +                            dwc_dma_t dma1, int sync_frame, int dp_frame,
44502 +                            int data_per_frame, int start_frame,
44503 +                            int buf_proc_intrvl, void *req_handle,
44504 +                            int atomic_alloc)
44505 +{
44506 +       dwc_otg_pcd_ep_t *ep;
44507 +       dwc_irqflags_t flags = 0;
44508 +       dwc_ep_t *dwc_ep;
44509 +       int32_t frm_data;
44510 +       dsts_data_t dsts;
44511 +       dwc_otg_core_if_t *core_if;
44512 +
44513 +       ep = get_ep_from_handle(pcd, ep_handle);
44514 +
44515 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44516 +               DWC_WARN("bad ep\n");
44517 +               return -DWC_E_INVALID;
44518 +       }
44519 +
44520 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44521 +       core_if = GET_CORE_IF(pcd);
44522 +       dwc_ep = &ep->dwc_ep;
44523 +
44524 +       if (ep->iso_req_handle) {
44525 +               DWC_WARN("ISO request in progress\n");
44526 +       }
44527 +
44528 +       dwc_ep->dma_addr0 = dma0;
44529 +       dwc_ep->dma_addr1 = dma1;
44530 +
44531 +       dwc_ep->xfer_buff0 = buf0;
44532 +       dwc_ep->xfer_buff1 = buf1;
44533 +
44534 +       dwc_ep->data_per_frame = data_per_frame;
44535 +
44536 +       /** @todo - pattern data support is to be implemented in the future */
44537 +       dwc_ep->data_pattern_frame = dp_frame;
44538 +       dwc_ep->sync_frame = sync_frame;
44539 +
44540 +       dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
44541 +
44542 +       dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
44543 +
44544 +       dwc_ep->proc_buf_num = 0;
44545 +
44546 +       dwc_ep->pkt_per_frm = 0;
44547 +       frm_data = ep->dwc_ep.data_per_frame;
44548 +       while (frm_data > 0) {
44549 +               dwc_ep->pkt_per_frm++;
44550 +               frm_data -= ep->dwc_ep.maxpacket;
44551 +       }
44552 +
44553 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
44554 +
44555 +       if (start_frame == -1) {
44556 +               dwc_ep->next_frame = dsts.b.soffn + 1;
44557 +               if (dwc_ep->bInterval != 1) {
44558 +                       dwc_ep->next_frame =
44559 +                           dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
44560 +                                                 dwc_ep->next_frame %
44561 +                                                 dwc_ep->bInterval);
44562 +               }
44563 +       } else {
44564 +               dwc_ep->next_frame = start_frame;
44565 +       }
44566 +
44567 +       if (!core_if->pti_enh_enable) {
44568 +               dwc_ep->pkt_cnt =
44569 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44570 +                   dwc_ep->bInterval;
44571 +       } else {
44572 +               dwc_ep->pkt_cnt =
44573 +                   (dwc_ep->data_per_frame *
44574 +                    (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
44575 +                    - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
44576 +       }
44577 +
44578 +       if (core_if->dma_desc_enable) {
44579 +               dwc_ep->desc_cnt =
44580 +                   dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
44581 +                   dwc_ep->bInterval;
44582 +       }
44583 +
44584 +       if (atomic_alloc) {
44585 +               dwc_ep->pkt_info =
44586 +                   DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44587 +       } else {
44588 +               dwc_ep->pkt_info =
44589 +                   DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44590 +       }
44591 +       if (!dwc_ep->pkt_info) {
44592 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44593 +               return -DWC_E_NO_MEMORY;
44594 +       }
44595 +       if (core_if->pti_enh_enable) {
44596 +               dwc_memset(dwc_ep->pkt_info, 0,
44597 +                          sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
44598 +       }
44599 +
44600 +       dwc_ep->cur_pkt = 0;
44601 +       ep->iso_req_handle = req_handle;
44602 +
44603 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44604 +       dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
44605 +       return 0;
44606 +}
44607 +
44608 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
44609 +                           void *req_handle)
44610 +{
44611 +       dwc_irqflags_t flags = 0;
44612 +       dwc_otg_pcd_ep_t *ep;
44613 +       dwc_ep_t *dwc_ep;
44614 +
44615 +       ep = get_ep_from_handle(pcd, ep_handle);
44616 +       if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
44617 +               DWC_WARN("bad ep\n");
44618 +               return -DWC_E_INVALID;
44619 +       }
44620 +       dwc_ep = &ep->dwc_ep;
44621 +
44622 +       dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
44623 +
44624 +       DWC_FREE(dwc_ep->pkt_info);
44625 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
44626 +       if (ep->iso_req_handle != req_handle) {
44627 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44628 +               return -DWC_E_INVALID;
44629 +       }
44630 +
44631 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
44632 +
44633 +       ep->iso_req_handle = 0;
44634 +       return 0;
44635 +}
44636 +
44637 +/**
44638 + * This function is used for perodical data exchnage between PCD and gadget drivers.
44639 + * for Isochronous EPs
44640 + *
44641 + *     - Every time a sync period completes this function is called to
44642 + *       perform data exchange between PCD and gadget
44643 + */
44644 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
44645 +                            void *req_handle)
44646 +{
44647 +       int i;
44648 +       dwc_ep_t *dwc_ep;
44649 +
44650 +       dwc_ep = &ep->dwc_ep;
44651 +
44652 +       DWC_SPINUNLOCK(ep->pcd->lock);
44653 +       pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
44654 +                                dwc_ep->proc_buf_num ^ 0x1);
44655 +       DWC_SPINLOCK(ep->pcd->lock);
44656 +
44657 +       for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
44658 +               dwc_ep->pkt_info[i].status = 0;
44659 +               dwc_ep->pkt_info[i].offset = 0;
44660 +               dwc_ep->pkt_info[i].length = 0;
44661 +       }
44662 +}
44663 +
44664 +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
44665 +                                    void *iso_req_handle)
44666 +{
44667 +       dwc_otg_pcd_ep_t *ep;
44668 +       dwc_ep_t *dwc_ep;
44669 +
44670 +       ep = get_ep_from_handle(pcd, ep_handle);
44671 +       if (!ep->desc || ep->dwc_ep.num == 0) {
44672 +               DWC_WARN("bad ep\n");
44673 +               return -DWC_E_INVALID;
44674 +       }
44675 +       dwc_ep = &ep->dwc_ep;
44676 +
44677 +       return dwc_ep->pkt_cnt;
44678 +}
44679 +
44680 +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
44681 +                                      void *iso_req_handle, int packet,
44682 +                                      int *status, int *actual, int *offset)
44683 +{
44684 +       dwc_otg_pcd_ep_t *ep;
44685 +       dwc_ep_t *dwc_ep;
44686 +
44687 +       ep = get_ep_from_handle(pcd, ep_handle);
44688 +       if (!ep)
44689 +               DWC_WARN("bad ep\n");
44690 +
44691 +       dwc_ep = &ep->dwc_ep;
44692 +
44693 +       *status = dwc_ep->pkt_info[packet].status;
44694 +       *actual = dwc_ep->pkt_info[packet].length;
44695 +       *offset = dwc_ep->pkt_info[packet].offset;
44696 +}
44697 +
44698 +#endif /* DWC_EN_ISOC */
44699 +
44700 +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
44701 +                               uint32_t is_in, uint32_t ep_num)
44702 +{
44703 +       /* Init EP structure */
44704 +       pcd_ep->desc = 0;
44705 +       pcd_ep->pcd = pcd;
44706 +       pcd_ep->stopped = 1;
44707 +       pcd_ep->queue_sof = 0;
44708 +
44709 +       /* Init DWC ep structure */
44710 +       pcd_ep->dwc_ep.is_in = is_in;
44711 +       pcd_ep->dwc_ep.num = ep_num;
44712 +       pcd_ep->dwc_ep.active = 0;
44713 +       pcd_ep->dwc_ep.tx_fifo_num = 0;
44714 +       /* Control until ep is actvated */
44715 +       pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44716 +       pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
44717 +       pcd_ep->dwc_ep.dma_addr = 0;
44718 +       pcd_ep->dwc_ep.start_xfer_buff = 0;
44719 +       pcd_ep->dwc_ep.xfer_buff = 0;
44720 +       pcd_ep->dwc_ep.xfer_len = 0;
44721 +       pcd_ep->dwc_ep.xfer_count = 0;
44722 +       pcd_ep->dwc_ep.sent_zlp = 0;
44723 +       pcd_ep->dwc_ep.total_len = 0;
44724 +       pcd_ep->dwc_ep.desc_addr = 0;
44725 +       pcd_ep->dwc_ep.dma_desc_addr = 0;
44726 +       DWC_CIRCLEQ_INIT(&pcd_ep->queue);
44727 +}
44728 +
44729 +/**
44730 + * Initialize ep's
44731 + */
44732 +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
44733 +{
44734 +       int i;
44735 +       uint32_t hwcfg1;
44736 +       dwc_otg_pcd_ep_t *ep;
44737 +       int in_ep_cntr, out_ep_cntr;
44738 +       uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
44739 +       uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
44740 +
44741 +       /**
44742 +        * Initialize the EP0 structure.
44743 +        */
44744 +       ep = &pcd->ep0;
44745 +       dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
44746 +
44747 +       in_ep_cntr = 0;
44748 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
44749 +       for (i = 1; in_ep_cntr < num_in_eps; i++) {
44750 +               if ((hwcfg1 & 0x1) == 0) {
44751 +                       dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
44752 +                       in_ep_cntr++;
44753 +                       /**
44754 +                        * @todo NGS: Add direction to EP, based on contents
44755 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44756 +                        * sprintf(";r
44757 +                        */
44758 +                       dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
44759 +
44760 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44761 +               }
44762 +               hwcfg1 >>= 2;
44763 +       }
44764 +
44765 +       out_ep_cntr = 0;
44766 +       hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
44767 +       for (i = 1; out_ep_cntr < num_out_eps; i++) {
44768 +               if ((hwcfg1 & 0x1) == 0) {
44769 +                       dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
44770 +                       out_ep_cntr++;
44771 +                       /**
44772 +                        * @todo NGS: Add direction to EP, based on contents
44773 +                        * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
44774 +                        * sprintf(";r
44775 +                        */
44776 +                       dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
44777 +                       DWC_CIRCLEQ_INIT(&ep->queue);
44778 +               }
44779 +               hwcfg1 >>= 2;
44780 +       }
44781 +
44782 +       pcd->ep0state = EP0_DISCONNECT;
44783 +       pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
44784 +       pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
44785 +}
44786 +
44787 +/**
44788 + * This function is called when the SRP timer expires. The SRP should
44789 + * complete within 6 seconds.
44790 + */
44791 +static void srp_timeout(void *ptr)
44792 +{
44793 +       gotgctl_data_t gotgctl;
44794 +       dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
44795 +       volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
44796 +
44797 +       gotgctl.d32 = DWC_READ_REG32(addr);
44798 +
44799 +       core_if->srp_timer_started = 0;
44800 +
44801 +       if (core_if->adp_enable) {
44802 +               if (gotgctl.b.bsesvld == 0) {
44803 +                       gpwrdn_data_t gpwrdn = {.d32 = 0 };
44804 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
44805 +                       /* Power off the core */
44806 +                       if (core_if->power_down == 2) {
44807 +                               gpwrdn.b.pwrdnswtch = 1;
44808 +                               DWC_MODIFY_REG32(&core_if->
44809 +                                                core_global_regs->gpwrdn,
44810 +                                                gpwrdn.d32, 0);
44811 +                       }
44812 +
44813 +                       gpwrdn.d32 = 0;
44814 +                       gpwrdn.b.pmuintsel = 1;
44815 +                       gpwrdn.b.pmuactv = 1;
44816 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
44817 +                                        gpwrdn.d32);
44818 +                       dwc_otg_adp_probe_start(core_if);
44819 +               } else {
44820 +                       DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
44821 +                       core_if->op_state = B_PERIPHERAL;
44822 +                       dwc_otg_core_init(core_if);
44823 +                       dwc_otg_enable_global_interrupts(core_if);
44824 +                       cil_pcd_start(core_if);
44825 +               }
44826 +       }
44827 +
44828 +       if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
44829 +           (core_if->core_params->i2c_enable)) {
44830 +               DWC_PRINTF("SRP Timeout\n");
44831 +
44832 +               if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
44833 +                       if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
44834 +                               core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
44835 +                       }
44836 +
44837 +                       /* Clear Session Request */
44838 +                       gotgctl.d32 = 0;
44839 +                       gotgctl.b.sesreq = 1;
44840 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
44841 +                                        gotgctl.d32, 0);
44842 +
44843 +                       core_if->srp_success = 0;
44844 +               } else {
44845 +                       __DWC_ERROR("Device not connected/responding\n");
44846 +                       gotgctl.b.sesreq = 0;
44847 +                       DWC_WRITE_REG32(addr, gotgctl.d32);
44848 +               }
44849 +       } else if (gotgctl.b.sesreq) {
44850 +               DWC_PRINTF("SRP Timeout\n");
44851 +
44852 +               __DWC_ERROR("Device not connected/responding\n");
44853 +               gotgctl.b.sesreq = 0;
44854 +               DWC_WRITE_REG32(addr, gotgctl.d32);
44855 +       } else {
44856 +               DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
44857 +       }
44858 +}
44859 +
44860 +/**
44861 + * Tasklet
44862 + *
44863 + */
44864 +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
44865 +
44866 +static void start_xfer_tasklet_func(void *data)
44867 +{
44868 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
44869 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
44870 +
44871 +       int i;
44872 +       depctl_data_t diepctl;
44873 +
44874 +       DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
44875 +
44876 +       diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
44877 +
44878 +       if (pcd->ep0.queue_sof) {
44879 +               pcd->ep0.queue_sof = 0;
44880 +               start_next_request(&pcd->ep0);
44881 +               // break;
44882 +       }
44883 +
44884 +       for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
44885 +               depctl_data_t diepctl;
44886 +               diepctl.d32 =
44887 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
44888 +
44889 +               if (pcd->in_ep[i].queue_sof) {
44890 +                       pcd->in_ep[i].queue_sof = 0;
44891 +                       start_next_request(&pcd->in_ep[i]);
44892 +                       // break;
44893 +               }
44894 +       }
44895 +
44896 +       return;
44897 +}
44898 +
44899 +/**
44900 + * This function initialized the PCD portion of the driver.
44901 + *
44902 + */
44903 +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
44904 +{
44905 +       dwc_otg_pcd_t *pcd = NULL;
44906 +       dwc_otg_dev_if_t *dev_if;
44907 +       int i;
44908 +
44909 +       /*
44910 +        * Allocate PCD structure
44911 +        */
44912 +       pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
44913 +
44914 +       if (pcd == NULL) {
44915 +               return NULL;
44916 +       }
44917 +
44918 +       pcd->lock = DWC_SPINLOCK_ALLOC();
44919 +        DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
44920 +                    pcd, core_if);//GRAYG
44921 +       if (!pcd->lock) {
44922 +               DWC_ERROR("Could not allocate lock for pcd");
44923 +               DWC_FREE(pcd);
44924 +               return NULL;
44925 +       }
44926 +       /* Set core_if's lock pointer to hcd->lock */
44927 +       core_if->lock = pcd->lock;
44928 +       pcd->core_if = core_if;
44929 +
44930 +       dev_if = core_if->dev_if;
44931 +       dev_if->isoc_ep = NULL;
44932 +
44933 +       if (core_if->hwcfg4.b.ded_fifo_en) {
44934 +               DWC_PRINTF("Dedicated Tx FIFOs mode\n");
44935 +       } else {
44936 +               DWC_PRINTF("Shared Tx FIFO mode\n");
44937 +       }
44938 +
44939 +       /*
44940 +        * Initialized the Core for Device mode here if there is nod ADP support.
44941 +        * Otherwise it will be done later in dwc_otg_adp_start routine.
44942 +        */
44943 +       if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
44944 +               dwc_otg_core_dev_init(core_if);
44945 +       }
44946 +
44947 +       /*
44948 +        * Register the PCD Callbacks.
44949 +        */
44950 +       dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
44951 +
44952 +       /*
44953 +        * Initialize the DMA buffer for SETUP packets
44954 +        */
44955 +       if (GET_CORE_IF(pcd)->dma_enable) {
44956 +               pcd->setup_pkt =
44957 +                   DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
44958 +                                 &pcd->setup_pkt_dma_handle);
44959 +               if (pcd->setup_pkt == NULL) {
44960 +                       DWC_FREE(pcd);
44961 +                       return NULL;
44962 +               }
44963 +
44964 +               pcd->status_buf =
44965 +                   DWC_DMA_ALLOC(sizeof(uint16_t),
44966 +                                 &pcd->status_buf_dma_handle);
44967 +               if (pcd->status_buf == NULL) {
44968 +                       DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
44969 +                                    pcd->setup_pkt, pcd->setup_pkt_dma_handle);
44970 +                       DWC_FREE(pcd);
44971 +                       return NULL;
44972 +               }
44973 +
44974 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
44975 +                       dev_if->setup_desc_addr[0] =
44976 +                           dwc_otg_ep_alloc_desc_chain
44977 +                           (&dev_if->dma_setup_desc_addr[0], 1);
44978 +                       dev_if->setup_desc_addr[1] =
44979 +                           dwc_otg_ep_alloc_desc_chain
44980 +                           (&dev_if->dma_setup_desc_addr[1], 1);
44981 +                       dev_if->in_desc_addr =
44982 +                           dwc_otg_ep_alloc_desc_chain
44983 +                           (&dev_if->dma_in_desc_addr, 1);
44984 +                       dev_if->out_desc_addr =
44985 +                           dwc_otg_ep_alloc_desc_chain
44986 +                           (&dev_if->dma_out_desc_addr, 1);
44987 +                       pcd->data_terminated = 0;
44988 +
44989 +                       if (dev_if->setup_desc_addr[0] == 0
44990 +                           || dev_if->setup_desc_addr[1] == 0
44991 +                           || dev_if->in_desc_addr == 0
44992 +                           || dev_if->out_desc_addr == 0) {
44993 +
44994 +                               if (dev_if->out_desc_addr)
44995 +                                       dwc_otg_ep_free_desc_chain
44996 +                                           (dev_if->out_desc_addr,
44997 +                                            dev_if->dma_out_desc_addr, 1);
44998 +                               if (dev_if->in_desc_addr)
44999 +                                       dwc_otg_ep_free_desc_chain
45000 +                                           (dev_if->in_desc_addr,
45001 +                                            dev_if->dma_in_desc_addr, 1);
45002 +                               if (dev_if->setup_desc_addr[1])
45003 +                                       dwc_otg_ep_free_desc_chain
45004 +                                           (dev_if->setup_desc_addr[1],
45005 +                                            dev_if->dma_setup_desc_addr[1], 1);
45006 +                               if (dev_if->setup_desc_addr[0])
45007 +                                       dwc_otg_ep_free_desc_chain
45008 +                                           (dev_if->setup_desc_addr[0],
45009 +                                            dev_if->dma_setup_desc_addr[0], 1);
45010 +
45011 +                               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
45012 +                                            pcd->setup_pkt,
45013 +                                            pcd->setup_pkt_dma_handle);
45014 +                               DWC_DMA_FREE(sizeof(*pcd->status_buf),
45015 +                                            pcd->status_buf,
45016 +                                            pcd->status_buf_dma_handle);
45017 +
45018 +                               DWC_FREE(pcd);
45019 +
45020 +                               return NULL;
45021 +                       }
45022 +               }
45023 +       } else {
45024 +               pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
45025 +               if (pcd->setup_pkt == NULL) {
45026 +                       DWC_FREE(pcd);
45027 +                       return NULL;
45028 +               }
45029 +
45030 +               pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
45031 +               if (pcd->status_buf == NULL) {
45032 +                       DWC_FREE(pcd->setup_pkt);
45033 +                       DWC_FREE(pcd);
45034 +                       return NULL;
45035 +               }
45036 +       }
45037 +
45038 +       dwc_otg_pcd_reinit(pcd);
45039 +
45040 +       /* Allocate the cfi object for the PCD */
45041 +#ifdef DWC_UTE_CFI
45042 +       pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
45043 +       if (NULL == pcd->cfi)
45044 +               goto fail;
45045 +       if (init_cfi(pcd->cfi)) {
45046 +               CFI_INFO("%s: Failed to init the CFI object\n", __func__);
45047 +               goto fail;
45048 +       }
45049 +#endif
45050 +
45051 +       /* Initialize tasklets */
45052 +       pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
45053 +                                                start_xfer_tasklet_func, pcd);
45054 +       pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
45055 +                                               do_test_mode, pcd);
45056 +
45057 +       /* Initialize SRP timer */
45058 +       core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
45059 +
45060 +       if (core_if->core_params->dev_out_nak) {
45061 +               /**
45062 +               * Initialize xfer timeout timer. Implemented for
45063 +               * 2.93a feature "Device DDMA OUT NAK Enhancement"
45064 +               */
45065 +               for(i = 0; i < MAX_EPS_CHANNELS; i++) {
45066 +                       pcd->core_if->ep_xfer_timer[i] =
45067 +                               DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
45068 +                               &pcd->core_if->ep_xfer_info[i]);
45069 +               }
45070 +       }
45071 +
45072 +       return pcd;
45073 +#ifdef DWC_UTE_CFI
45074 +fail:
45075 +#endif
45076 +       if (pcd->setup_pkt)
45077 +               DWC_FREE(pcd->setup_pkt);
45078 +       if (pcd->status_buf)
45079 +               DWC_FREE(pcd->status_buf);
45080 +#ifdef DWC_UTE_CFI
45081 +       if (pcd->cfi)
45082 +               DWC_FREE(pcd->cfi);
45083 +#endif
45084 +       if (pcd)
45085 +               DWC_FREE(pcd);
45086 +       return NULL;
45087 +
45088 +}
45089 +
45090 +/**
45091 + * Remove PCD specific data
45092 + */
45093 +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
45094 +{
45095 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
45096 +       int i;
45097 +       if (pcd->core_if->core_params->dev_out_nak) {
45098 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45099 +                       DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
45100 +                       pcd->core_if->ep_xfer_info[i].state = 0;
45101 +               }
45102 +       }
45103 +
45104 +       if (GET_CORE_IF(pcd)->dma_enable) {
45105 +               DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
45106 +                            pcd->setup_pkt_dma_handle);
45107 +               DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
45108 +                            pcd->status_buf_dma_handle);
45109 +               if (GET_CORE_IF(pcd)->dma_desc_enable) {
45110 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
45111 +                                                  dev_if->dma_setup_desc_addr
45112 +                                                  [0], 1);
45113 +                       dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
45114 +                                                  dev_if->dma_setup_desc_addr
45115 +                                                  [1], 1);
45116 +                       dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
45117 +                                                  dev_if->dma_in_desc_addr, 1);
45118 +                       dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
45119 +                                                  dev_if->dma_out_desc_addr,
45120 +                                                  1);
45121 +               }
45122 +       } else {
45123 +               DWC_FREE(pcd->setup_pkt);
45124 +               DWC_FREE(pcd->status_buf);
45125 +       }
45126 +       DWC_SPINLOCK_FREE(pcd->lock);
45127 +       /* Set core_if's lock pointer to NULL */
45128 +       pcd->core_if->lock = NULL;
45129 +
45130 +       DWC_TASK_FREE(pcd->start_xfer_tasklet);
45131 +       DWC_TASK_FREE(pcd->test_mode_tasklet);
45132 +       if (pcd->core_if->core_params->dev_out_nak) {
45133 +               for (i = 0; i < MAX_EPS_CHANNELS; i++) {
45134 +                       if (pcd->core_if->ep_xfer_timer[i]) {
45135 +                                       DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
45136 +                       }
45137 +               }
45138 +       }
45139 +
45140 +/* Release the CFI object's dynamic memory */
45141 +#ifdef DWC_UTE_CFI
45142 +       if (pcd->cfi->ops.release) {
45143 +               pcd->cfi->ops.release(pcd->cfi);
45144 +       }
45145 +#endif
45146 +
45147 +       DWC_FREE(pcd);
45148 +}
45149 +
45150 +/**
45151 + * Returns whether registered pcd is dual speed or not
45152 + */
45153 +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
45154 +{
45155 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45156 +
45157 +       if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
45158 +           ((core_if->hwcfg2.b.hs_phy_type == 2) &&
45159 +            (core_if->hwcfg2.b.fs_phy_type == 1) &&
45160 +            (core_if->core_params->ulpi_fs_ls))) {
45161 +               return 0;
45162 +       }
45163 +
45164 +       return 1;
45165 +}
45166 +
45167 +/**
45168 + * Returns whether registered pcd is OTG capable or not
45169 + */
45170 +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
45171 +{
45172 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
45173 +       gusbcfg_data_t usbcfg = {.d32 = 0 };
45174 +
45175 +       usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
45176 +       if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
45177 +               return 0;
45178 +       }
45179 +
45180 +       return 1;
45181 +}
45182 +
45183 +/**
45184 + * This function assigns periodic Tx FIFO to an periodic EP
45185 + * in shared Tx FIFO mode
45186 + */
45187 +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
45188 +{
45189 +       uint32_t TxMsk = 1;
45190 +       int i;
45191 +
45192 +       for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
45193 +               if ((TxMsk & core_if->tx_msk) == 0) {
45194 +                       core_if->tx_msk |= TxMsk;
45195 +                       return i + 1;
45196 +               }
45197 +               TxMsk <<= 1;
45198 +       }
45199 +       return 0;
45200 +}
45201 +
45202 +/**
45203 + * This function assigns periodic Tx FIFO to an periodic EP
45204 + * in shared Tx FIFO mode
45205 + */
45206 +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
45207 +{
45208 +       uint32_t PerTxMsk = 1;
45209 +       int i;
45210 +       for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
45211 +               if ((PerTxMsk & core_if->p_tx_msk) == 0) {
45212 +                       core_if->p_tx_msk |= PerTxMsk;
45213 +                       return i + 1;
45214 +               }
45215 +               PerTxMsk <<= 1;
45216 +       }
45217 +       return 0;
45218 +}
45219 +
45220 +/**
45221 + * This function releases periodic Tx FIFO
45222 + * in shared Tx FIFO mode
45223 + */
45224 +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
45225 +                                 uint32_t fifo_num)
45226 +{
45227 +       core_if->p_tx_msk =
45228 +           (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
45229 +}
45230 +
45231 +/**
45232 + * This function releases periodic Tx FIFO
45233 + * in shared Tx FIFO mode
45234 + */
45235 +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
45236 +{
45237 +       core_if->tx_msk =
45238 +           (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
45239 +}
45240 +
45241 +/**
45242 + * This function is being called from gadget
45243 + * to enable PCD endpoint.
45244 + */
45245 +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
45246 +                         const uint8_t * ep_desc, void *usb_ep)
45247 +{
45248 +       int num, dir;
45249 +       dwc_otg_pcd_ep_t *ep = NULL;
45250 +       const usb_endpoint_descriptor_t *desc;
45251 +       dwc_irqflags_t flags;
45252 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45253 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45254 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45255 +       int retval = 0;
45256 +       int i, epcount;
45257 +
45258 +       desc = (const usb_endpoint_descriptor_t *)ep_desc;
45259 +
45260 +       if (!desc) {
45261 +               pcd->ep0.priv = usb_ep;
45262 +               ep = &pcd->ep0;
45263 +               retval = -DWC_E_INVALID;
45264 +               goto out;
45265 +       }
45266 +
45267 +       num = UE_GET_ADDR(desc->bEndpointAddress);
45268 +       dir = UE_GET_DIR(desc->bEndpointAddress);
45269 +
45270 +       if (!desc->wMaxPacketSize) {
45271 +               DWC_WARN("bad maxpacketsize\n");
45272 +               retval = -DWC_E_INVALID;
45273 +               goto out;
45274 +       }
45275 +
45276 +       if (dir == UE_DIR_IN) {
45277 +               epcount = pcd->core_if->dev_if->num_in_eps;
45278 +               for (i = 0; i < epcount; i++) {
45279 +                       if (num == pcd->in_ep[i].dwc_ep.num) {
45280 +                               ep = &pcd->in_ep[i];
45281 +                               break;
45282 +                       }
45283 +               }
45284 +       } else {
45285 +               epcount = pcd->core_if->dev_if->num_out_eps;
45286 +               for (i = 0; i < epcount; i++) {
45287 +                       if (num == pcd->out_ep[i].dwc_ep.num) {
45288 +                               ep = &pcd->out_ep[i];
45289 +                               break;
45290 +                       }
45291 +               }
45292 +       }
45293 +
45294 +       if (!ep) {
45295 +               DWC_WARN("bad address\n");
45296 +               retval = -DWC_E_INVALID;
45297 +               goto out;
45298 +       }
45299 +
45300 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45301 +
45302 +       ep->desc = desc;
45303 +       ep->priv = usb_ep;
45304 +
45305 +       /*
45306 +        * Activate the EP
45307 +        */
45308 +       ep->stopped = 0;
45309 +
45310 +       ep->dwc_ep.is_in = (dir == UE_DIR_IN);
45311 +       ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
45312 +
45313 +       ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
45314 +
45315 +       if (ep->dwc_ep.is_in) {
45316 +               if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45317 +                       ep->dwc_ep.tx_fifo_num = 0;
45318 +
45319 +                       if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
45320 +                               /*
45321 +                                * if ISOC EP then assign a Periodic Tx FIFO.
45322 +                                */
45323 +                               ep->dwc_ep.tx_fifo_num =
45324 +                                   assign_perio_tx_fifo(GET_CORE_IF(pcd));
45325 +                       }
45326 +               } else {
45327 +                       /*
45328 +                        * if Dedicated FIFOs mode is on then assign a Tx FIFO.
45329 +                        */
45330 +                       ep->dwc_ep.tx_fifo_num =
45331 +                           assign_tx_fifo(GET_CORE_IF(pcd));
45332 +               }
45333 +
45334 +               /* Calculating EP info controller base address */
45335 +               if (ep->dwc_ep.tx_fifo_num
45336 +                   && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45337 +                       gdfifocfg.d32 =
45338 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
45339 +                                          core_global_regs->gdfifocfg);
45340 +                       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45341 +                       dptxfsiz.d32 =
45342 +                           (DWC_READ_REG32
45343 +                            (&GET_CORE_IF(pcd)->core_global_regs->
45344 +                             dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);
45345 +                       gdfifocfg.b.epinfobase =
45346 +                           gdfifocfgbase.d32 + dptxfsiz.d32;
45347 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45348 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45349 +                                               core_global_regs->gdfifocfg,
45350 +                                               gdfifocfg.d32);
45351 +                       }
45352 +               }
45353 +       }
45354 +       /* Set initial data PID. */
45355 +       if (ep->dwc_ep.type == UE_BULK) {
45356 +               ep->dwc_ep.data_pid_start = 0;
45357 +       }
45358 +
45359 +       /* Alloc DMA Descriptors */
45360 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45361 +#ifndef DWC_UTE_PER_IO
45362 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45363 +#endif
45364 +                       ep->dwc_ep.desc_addr =
45365 +                           dwc_otg_ep_alloc_desc_chain(&ep->
45366 +                                                       dwc_ep.dma_desc_addr,
45367 +                                                       MAX_DMA_DESC_CNT);
45368 +                       if (!ep->dwc_ep.desc_addr) {
45369 +                               DWC_WARN("%s, can't allocate DMA descriptor\n",
45370 +                                        __func__);
45371 +                               retval = -DWC_E_SHUTDOWN;
45372 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45373 +                               goto out;
45374 +                       }
45375 +#ifndef DWC_UTE_PER_IO
45376 +               }
45377 +#endif
45378 +       }
45379 +
45380 +       DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
45381 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"),
45382 +                   ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
45383 +#ifdef DWC_UTE_PER_IO
45384 +       ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
45385 +#endif
45386 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45387 +               ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
45388 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
45389 +       }
45390 +
45391 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
45392 +
45393 +#ifdef DWC_UTE_CFI
45394 +       if (pcd->cfi->ops.ep_enable) {
45395 +               pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
45396 +       }
45397 +#endif
45398 +
45399 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45400 +
45401 +out:
45402 +       return retval;
45403 +}
45404 +
45405 +/**
45406 + * This function is being called from gadget
45407 + * to disable PCD endpoint.
45408 + */
45409 +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
45410 +{
45411 +       dwc_otg_pcd_ep_t *ep;
45412 +       dwc_irqflags_t flags;
45413 +       dwc_otg_dev_dma_desc_t *desc_addr;
45414 +       dwc_dma_t dma_desc_addr;
45415 +       gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
45416 +       gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
45417 +       fifosize_data_t dptxfsiz = {.d32 = 0 };
45418 +
45419 +       ep = get_ep_from_handle(pcd, ep_handle);
45420 +
45421 +       if (!ep || !ep->desc) {
45422 +               DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
45423 +               return -DWC_E_INVALID;
45424 +       }
45425 +
45426 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45427 +
45428 +       dwc_otg_request_nuke(ep);
45429 +
45430 +       dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
45431 +       if (pcd->core_if->core_params->dev_out_nak) {
45432 +               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
45433 +               pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
45434 +       }
45435 +       ep->desc = NULL;
45436 +       ep->stopped = 1;
45437 +
45438 +       gdfifocfg.d32 =
45439 +           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
45440 +       gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
45441 +
45442 +       if (ep->dwc_ep.is_in) {
45443 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45444 +                       /* Flush the Tx FIFO */
45445 +                       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),
45446 +                                             ep->dwc_ep.tx_fifo_num);
45447 +               }
45448 +               release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45449 +               release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
45450 +               if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
45451 +                       /* Decreasing EPinfo Base Addr */
45452 +                       dptxfsiz.d32 =
45453 +                           (DWC_READ_REG32
45454 +                            (&GET_CORE_IF(pcd)->
45455 +                               core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
45456 +                       gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
45457 +                       if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
45458 +                               DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
45459 +                                       gdfifocfg.d32);
45460 +                       }
45461 +               }
45462 +       }
45463 +
45464 +       /* Free DMA Descriptors */
45465 +       if (GET_CORE_IF(pcd)->dma_desc_enable) {
45466 +               if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
45467 +                       desc_addr = ep->dwc_ep.desc_addr;
45468 +                       dma_desc_addr = ep->dwc_ep.dma_desc_addr;
45469 +
45470 +                       /* Cannot call dma_free_coherent() with IRQs disabled */
45471 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45472 +                       dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
45473 +                                                  MAX_DMA_DESC_CNT);
45474 +
45475 +                       goto out_unlocked;
45476 +               }
45477 +       }
45478 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45479 +
45480 +out_unlocked:
45481 +       DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
45482 +                   ep->dwc_ep.is_in ? "IN" : "OUT");
45483 +       return 0;
45484 +
45485 +}
45486 +
45487 +/******************************************************************************/
45488 +#ifdef DWC_UTE_PER_IO
45489 +
45490 +/**
45491 + * Free the request and its extended parts
45492 + *
45493 + */
45494 +void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
45495 +{
45496 +       DWC_FREE(req->ext_req.per_io_frame_descs);
45497 +       DWC_FREE(req);
45498 +}
45499 +
45500 +/**
45501 + * Start the next request in the endpoint's queue.
45502 + *
45503 + */
45504 +int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
45505 +                                       dwc_otg_pcd_ep_t * ep)
45506 +{
45507 +       int i;
45508 +       dwc_otg_pcd_request_t *req = NULL;
45509 +       dwc_ep_t *dwcep = NULL;
45510 +       struct dwc_iso_xreq_port *ereq = NULL;
45511 +       struct dwc_iso_pkt_desc_port *ddesc_iso;
45512 +       uint16_t nat;
45513 +       depctl_data_t diepctl;
45514 +
45515 +       dwcep = &ep->dwc_ep;
45516 +
45517 +       if (dwcep->xiso_active_xfers > 0) {
45518 +#if 0  //Disable this to decrease s/w overhead that is crucial for Isoc transfers
45519 +               DWC_WARN("There are currently active transfers for EP%d \
45520 +                               (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers,
45521 +                               dwcep->xiso_queued_xfers);
45522 +#endif
45523 +               return 0;
45524 +       }
45525 +
45526 +       nat = UGETW(ep->desc->wMaxPacketSize);
45527 +       nat = (nat >> 11) & 0x03;
45528 +
45529 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45530 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45531 +               ereq = &req->ext_req;
45532 +               ep->stopped = 0;
45533 +
45534 +               /* Get the frame number */
45535 +               dwcep->xiso_frame_num =
45536 +                   dwc_otg_get_frame_number(GET_CORE_IF(pcd));
45537 +               DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
45538 +
45539 +               ddesc_iso = ereq->per_io_frame_descs;
45540 +
45541 +               if (dwcep->is_in) {
45542 +                       /* Setup DMA Descriptor chain for IN Isoc request */
45543 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45544 +                               //if ((i % (nat + 1)) == 0)
45545 +                               if ( i > 0 )
45546 +                                       dwcep->xiso_frame_num =
45547 +                                           (dwcep->xiso_bInterval +
45548 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45549 +                               dwcep->desc_addr[i].buf =
45550 +                                   req->dma + ddesc_iso[i].offset;
45551 +                               dwcep->desc_addr[i].status.b_iso_in.txbytes =
45552 +                                   ddesc_iso[i].length;
45553 +                               dwcep->desc_addr[i].status.b_iso_in.framenum =
45554 +                                   dwcep->xiso_frame_num;
45555 +                               dwcep->desc_addr[i].status.b_iso_in.bs =
45556 +                                   BS_HOST_READY;
45557 +                               dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
45558 +                               dwcep->desc_addr[i].status.b_iso_in.sp =
45559 +                                   (ddesc_iso[i].length %
45560 +                                    dwcep->maxpacket) ? 1 : 0;
45561 +                               dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
45562 +                               dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
45563 +                               dwcep->desc_addr[i].status.b_iso_in.l = 0;
45564 +
45565 +                               /* Process the last descriptor */
45566 +                               if (i == ereq->pio_pkt_count - 1) {
45567 +                                       dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
45568 +                                       dwcep->desc_addr[i].status.b_iso_in.l = 1;
45569 +                               }
45570 +                       }
45571 +
45572 +                       /* Setup and start the transfer for this endpoint */
45573 +                       dwcep->xiso_active_xfers++;
45574 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
45575 +                                       in_ep_regs[dwcep->num]->diepdma,
45576 +                                       dwcep->dma_desc_addr);
45577 +                       diepctl.d32 = 0;
45578 +                       diepctl.b.epena = 1;
45579 +                       diepctl.b.cnak = 1;
45580 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
45581 +                                        in_ep_regs[dwcep->num]->diepctl, 0,
45582 +                                        diepctl.d32);
45583 +               } else {
45584 +                       /* Setup DMA Descriptor chain for OUT Isoc request */
45585 +                       for (i = 0; i < ereq->pio_pkt_count; i++) {
45586 +                               //if ((i % (nat + 1)) == 0)
45587 +                               dwcep->xiso_frame_num = (dwcep->xiso_bInterval +
45588 +                                                                               dwcep->xiso_frame_num) & 0x3FFF;
45589 +                               dwcep->desc_addr[i].buf =
45590 +                                   req->dma + ddesc_iso[i].offset;
45591 +                               dwcep->desc_addr[i].status.b_iso_out.rxbytes =
45592 +                                   ddesc_iso[i].length;
45593 +                               dwcep->desc_addr[i].status.b_iso_out.framenum =
45594 +                                   dwcep->xiso_frame_num;
45595 +                               dwcep->desc_addr[i].status.b_iso_out.bs =
45596 +                                   BS_HOST_READY;
45597 +                               dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
45598 +                               dwcep->desc_addr[i].status.b_iso_out.sp =
45599 +                                   (ddesc_iso[i].length %
45600 +                                    dwcep->maxpacket) ? 1 : 0;
45601 +                               dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
45602 +                               dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
45603 +                               dwcep->desc_addr[i].status.b_iso_out.l = 0;
45604 +
45605 +                               /* Process the last descriptor */
45606 +                               if (i == ereq->pio_pkt_count - 1) {
45607 +                                       dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
45608 +                                       dwcep->desc_addr[i].status.b_iso_out.l = 1;
45609 +                               }
45610 +                       }
45611 +
45612 +                       /* Setup and start the transfer for this endpoint */
45613 +                       dwcep->xiso_active_xfers++;
45614 +                       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
45615 +                                       dev_if->out_ep_regs[dwcep->num]->
45616 +                                       doepdma, dwcep->dma_desc_addr);
45617 +                       diepctl.d32 = 0;
45618 +                       diepctl.b.epena = 1;
45619 +                       diepctl.b.cnak = 1;
45620 +                       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
45621 +                                        dev_if->out_ep_regs[dwcep->num]->
45622 +                                        doepctl, 0, diepctl.d32);
45623 +               }
45624 +
45625 +       } else {
45626 +               ep->stopped = 1;
45627 +       }
45628 +
45629 +       return 0;
45630 +}
45631 +
45632 +/**
45633 + *     - Remove the request from the queue
45634 + */
45635 +void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
45636 +{
45637 +       dwc_otg_pcd_request_t *req = NULL;
45638 +       struct dwc_iso_xreq_port *ereq = NULL;
45639 +       struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
45640 +       dwc_ep_t *dwcep = NULL;
45641 +       int i;
45642 +
45643 +       //DWC_DEBUG();
45644 +       dwcep = &ep->dwc_ep;
45645 +
45646 +       /* Get the first pending request from the queue */
45647 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
45648 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
45649 +               if (!req) {
45650 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
45651 +                       return;
45652 +               }
45653 +               dwcep->xiso_active_xfers--;
45654 +               dwcep->xiso_queued_xfers--;
45655 +               /* Remove this request from the queue */
45656 +               DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
45657 +       } else {
45658 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
45659 +               return;
45660 +       }
45661 +
45662 +       ep->stopped = 1;
45663 +       ereq = &req->ext_req;
45664 +       ddesc_iso = ereq->per_io_frame_descs;
45665 +
45666 +       if (dwcep->xiso_active_xfers < 0) {
45667 +               DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
45668 +                        dwcep->xiso_active_xfers);
45669 +       }
45670 +
45671 +       /* Fill the Isoc descs of portable extended req from dma descriptors */
45672 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45673 +               if (dwcep->is_in) {     /* IN endpoints */
45674 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45675 +                           dwcep->desc_addr[i].status.b_iso_in.txbytes;
45676 +                       ddesc_iso[i].status =
45677 +                           dwcep->desc_addr[i].status.b_iso_in.txsts;
45678 +               } else {        /* OUT endpoints */
45679 +                       ddesc_iso[i].actual_length = ddesc_iso[i].length -
45680 +                           dwcep->desc_addr[i].status.b_iso_out.rxbytes;
45681 +                       ddesc_iso[i].status =
45682 +                           dwcep->desc_addr[i].status.b_iso_out.rxsts;
45683 +               }
45684 +       }
45685 +
45686 +       DWC_SPINUNLOCK(ep->pcd->lock);
45687 +
45688 +       /* Call the completion function in the non-portable logic */
45689 +       ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
45690 +                                     &req->ext_req);
45691 +
45692 +       DWC_SPINLOCK(ep->pcd->lock);
45693 +
45694 +       /* Free the request - specific freeing needed for extended request object */
45695 +       dwc_pcd_xiso_ereq_free(ep, req);
45696 +
45697 +       /* Start the next request */
45698 +       dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
45699 +
45700 +       return;
45701 +}
45702 +
45703 +/**
45704 + * Create and initialize the Isoc pkt descriptors of the extended request.
45705 + *
45706 + */
45707 +static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
45708 +                                            void *ereq_nonport,
45709 +                                            int atomic_alloc)
45710 +{
45711 +       struct dwc_iso_xreq_port *ereq = NULL;
45712 +       struct dwc_iso_xreq_port *req_mapped = NULL;
45713 +       struct dwc_iso_pkt_desc_port *ipds = NULL;      /* To be created in this function */
45714 +       uint32_t pkt_count;
45715 +       int i;
45716 +
45717 +       ereq = &req->ext_req;
45718 +       req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
45719 +       pkt_count = req_mapped->pio_pkt_count;
45720 +
45721 +       /* Create the isoc descs */
45722 +       if (atomic_alloc) {
45723 +               ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
45724 +       } else {
45725 +               ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
45726 +       }
45727 +
45728 +       if (!ipds) {
45729 +               DWC_ERROR("Failed to allocate isoc descriptors");
45730 +               return -DWC_E_NO_MEMORY;
45731 +       }
45732 +
45733 +       /* Initialize the extended request fields */
45734 +       ereq->per_io_frame_descs = ipds;
45735 +       ereq->error_count = 0;
45736 +       ereq->pio_alloc_pkt_count = pkt_count;
45737 +       ereq->pio_pkt_count = pkt_count;
45738 +       ereq->tr_sub_flags = req_mapped->tr_sub_flags;
45739 +
45740 +       /* Init the Isoc descriptors */
45741 +       for (i = 0; i < pkt_count; i++) {
45742 +               ipds[i].length = req_mapped->per_io_frame_descs[i].length;
45743 +               ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
45744 +               ipds[i].status = req_mapped->per_io_frame_descs[i].status;      /* 0 */
45745 +               ipds[i].actual_length =
45746 +                   req_mapped->per_io_frame_descs[i].actual_length;
45747 +       }
45748 +
45749 +       return 0;
45750 +}
45751 +
45752 +static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
45753 +{
45754 +       struct dwc_iso_pkt_desc_port *xfd = NULL;
45755 +       int i;
45756 +
45757 +       DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
45758 +       DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
45759 +       DWC_DEBUG("error_count=%d", ereq->error_count);
45760 +       DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
45761 +       DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
45762 +       DWC_DEBUG("res=%d", ereq->res);
45763 +
45764 +       for (i = 0; i < ereq->pio_pkt_count; i++) {
45765 +               xfd = &ereq->per_io_frame_descs[0];
45766 +               DWC_DEBUG("FD #%d", i);
45767 +
45768 +               DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
45769 +               DWC_DEBUG("xfd->length=%d", xfd->length);
45770 +               DWC_DEBUG("xfd->offset=%d", xfd->offset);
45771 +               DWC_DEBUG("xfd->status=%d", xfd->status);
45772 +       }
45773 +}
45774 +
45775 +/**
45776 + *
45777 + */
45778 +int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
45779 +                             uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
45780 +                             int zero, void *req_handle, int atomic_alloc,
45781 +                             void *ereq_nonport)
45782 +{
45783 +       dwc_otg_pcd_request_t *req = NULL;
45784 +       dwc_otg_pcd_ep_t *ep;
45785 +       dwc_irqflags_t flags;
45786 +       int res;
45787 +
45788 +       ep = get_ep_from_handle(pcd, ep_handle);
45789 +       if (!ep) {
45790 +               DWC_WARN("bad ep\n");
45791 +               return -DWC_E_INVALID;
45792 +       }
45793 +
45794 +       /* We support this extension only for DDMA mode */
45795 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
45796 +               if (!GET_CORE_IF(pcd)->dma_desc_enable)
45797 +                       return -DWC_E_INVALID;
45798 +
45799 +       /* Create a dwc_otg_pcd_request_t object */
45800 +       if (atomic_alloc) {
45801 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
45802 +       } else {
45803 +               req = DWC_ALLOC(sizeof(*req));
45804 +       }
45805 +
45806 +       if (!req) {
45807 +               return -DWC_E_NO_MEMORY;
45808 +       }
45809 +
45810 +       /* Create the Isoc descs for this request which shall be the exact match
45811 +        * of the structure sent to us from the non-portable logic */
45812 +       res =
45813 +           dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
45814 +       if (res) {
45815 +               DWC_WARN("Failed to init the Isoc descriptors");
45816 +               DWC_FREE(req);
45817 +               return res;
45818 +       }
45819 +
45820 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45821 +
45822 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
45823 +       req->buf = buf;
45824 +       req->dma = dma_buf;
45825 +       req->length = buflen;
45826 +       req->sent_zlp = zero;
45827 +       req->priv = req_handle;
45828 +
45829 +       //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45830 +       ep->dwc_ep.dma_addr = dma_buf;
45831 +       ep->dwc_ep.start_xfer_buff = buf;
45832 +       ep->dwc_ep.xfer_buff = buf;
45833 +       ep->dwc_ep.xfer_len = 0;
45834 +       ep->dwc_ep.xfer_count = 0;
45835 +       ep->dwc_ep.sent_zlp = 0;
45836 +       ep->dwc_ep.total_len = buflen;
45837 +
45838 +       /* Add this request to the tail */
45839 +       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
45840 +       ep->dwc_ep.xiso_queued_xfers++;
45841 +
45842 +//DWC_DEBUG("CP_0");
45843 +//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
45844 +//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
45845 +//prn_ext_request(&req->ext_req);
45846 +
45847 +       //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45848 +
45849 +       /* If the req->status == ASAP  then check if there is any active transfer
45850 +        * for this endpoint. If no active transfers, then get the first entry
45851 +        * from the queue and start that transfer
45852 +        */
45853 +       if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
45854 +               res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
45855 +               if (res) {
45856 +                       DWC_WARN("Failed to start the next Isoc transfer");
45857 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45858 +                       DWC_FREE(req);
45859 +                       return res;
45860 +               }
45861 +       }
45862 +
45863 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45864 +       return 0;
45865 +}
45866 +
45867 +#endif
45868 +/* END ifdef DWC_UTE_PER_IO ***************************************************/
45869 +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
45870 +                        uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
45871 +                        int zero, void *req_handle, int atomic_alloc)
45872 +{
45873 +       dwc_irqflags_t flags;
45874 +       dwc_otg_pcd_request_t *req;
45875 +       dwc_otg_pcd_ep_t *ep;
45876 +       uint32_t max_transfer;
45877 +
45878 +       ep = get_ep_from_handle(pcd, ep_handle);
45879 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
45880 +               DWC_WARN("bad ep\n");
45881 +               return -DWC_E_INVALID;
45882 +       }
45883 +
45884 +       if (atomic_alloc) {
45885 +               req = DWC_ALLOC_ATOMIC(sizeof(*req));
45886 +       } else {
45887 +               req = DWC_ALLOC(sizeof(*req));
45888 +       }
45889 +
45890 +       if (!req) {
45891 +               return -DWC_E_NO_MEMORY;
45892 +       }
45893 +       DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
45894 +       if (!GET_CORE_IF(pcd)->core_params->opt) {
45895 +               if (ep->dwc_ep.num != 0) {
45896 +                       DWC_ERROR("queue req %p, len %d buf %p\n",
45897 +                                 req_handle, buflen, buf);
45898 +               }
45899 +       }
45900 +
45901 +       req->buf = buf;
45902 +       req->dma = dma_buf;
45903 +       req->length = buflen;
45904 +       req->sent_zlp = zero;
45905 +       req->priv = req_handle;
45906 +       req->dw_align_buf = NULL;
45907 +       if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
45908 +                       && !GET_CORE_IF(pcd)->dma_desc_enable)
45909 +               req->dw_align_buf = DWC_DMA_ALLOC(buflen,
45910 +                                &req->dw_align_buf_dma);
45911 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
45912 +
45913 +       /*
45914 +        * After adding request to the queue for IN ISOC wait for In Token Received
45915 +        * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token
45916 +        * Received when EP is disabled interrupt to obtain starting microframe
45917 +        * (odd/even) start transfer
45918 +        */
45919 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
45920 +               if (req != 0) {
45921 +                       depctl_data_t depctl = {.d32 =
45922 +                                   DWC_READ_REG32(&pcd->core_if->dev_if->
45923 +                                                  in_ep_regs[ep->dwc_ep.num]->
45924 +                                                  diepctl) };
45925 +                       ++pcd->request_pending;
45926 +
45927 +                       DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
45928 +                       if (ep->dwc_ep.is_in) {
45929 +                               depctl.b.cnak = 1;
45930 +                               DWC_WRITE_REG32(&pcd->core_if->dev_if->
45931 +                                               in_ep_regs[ep->dwc_ep.num]->
45932 +                                               diepctl, depctl.d32);
45933 +                       }
45934 +
45935 +                       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45936 +               }
45937 +               return 0;
45938 +       }
45939 +
45940 +       /*
45941 +        * For EP0 IN without premature status, zlp is required?
45942 +        */
45943 +       if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
45944 +               DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
45945 +               //_req->zero = 1;
45946 +       }
45947 +
45948 +       /* Start the transfer */
45949 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
45950 +               /* EP0 Transfer? */
45951 +               if (ep->dwc_ep.num == 0) {
45952 +                       switch (pcd->ep0state) {
45953 +                       case EP0_IN_DATA_PHASE:
45954 +                               DWC_DEBUGPL(DBG_PCD,
45955 +                                           "%s ep0: EP0_IN_DATA_PHASE\n",
45956 +                                           __func__);
45957 +                               break;
45958 +
45959 +                       case EP0_OUT_DATA_PHASE:
45960 +                               DWC_DEBUGPL(DBG_PCD,
45961 +                                           "%s ep0: EP0_OUT_DATA_PHASE\n",
45962 +                                           __func__);
45963 +                               if (pcd->request_config) {
45964 +                                       /* Complete STATUS PHASE */
45965 +                                       ep->dwc_ep.is_in = 1;
45966 +                                       pcd->ep0state = EP0_IN_STATUS_PHASE;
45967 +                               }
45968 +                               break;
45969 +
45970 +                       case EP0_IN_STATUS_PHASE:
45971 +                               DWC_DEBUGPL(DBG_PCD,
45972 +                                           "%s ep0: EP0_IN_STATUS_PHASE\n",
45973 +                                           __func__);
45974 +                               break;
45975 +
45976 +                       default:
45977 +                               DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
45978 +                                           pcd->ep0state);
45979 +                               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
45980 +                               return -DWC_E_SHUTDOWN;
45981 +                       }
45982 +
45983 +                       ep->dwc_ep.dma_addr = dma_buf;
45984 +                       ep->dwc_ep.start_xfer_buff = buf;
45985 +                       ep->dwc_ep.xfer_buff = buf;
45986 +                       ep->dwc_ep.xfer_len = buflen;
45987 +                       ep->dwc_ep.xfer_count = 0;
45988 +                       ep->dwc_ep.sent_zlp = 0;
45989 +                       ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
45990 +
45991 +                       if (zero) {
45992 +                               if ((ep->dwc_ep.xfer_len %
45993 +                                    ep->dwc_ep.maxpacket == 0)
45994 +                                   && (ep->dwc_ep.xfer_len != 0)) {
45995 +                                       ep->dwc_ep.sent_zlp = 1;
45996 +                               }
45997 +
45998 +                       }
45999 +
46000 +                       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
46001 +                                                  &ep->dwc_ep);
46002 +               }               // non-ep0 endpoints
46003 +               else {
46004 +#ifdef DWC_UTE_CFI
46005 +                       if (ep->dwc_ep.buff_mode != BM_STANDARD) {
46006 +                               /* store the request length */
46007 +                               ep->dwc_ep.cfi_req_len = buflen;
46008 +                               pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
46009 +                                                               ep, req);
46010 +                       } else {
46011 +#endif
46012 +                               max_transfer =
46013 +                                   GET_CORE_IF(ep->pcd)->core_params->
46014 +                                   max_transfer_size;
46015 +
46016 +                               /* Setup and start the Transfer */
46017 +                               if (req->dw_align_buf){
46018 +                                       if (ep->dwc_ep.is_in)
46019 +                                               dwc_memcpy(req->dw_align_buf,
46020 +                                                          buf, buflen);
46021 +                                       ep->dwc_ep.dma_addr =
46022 +                                           req->dw_align_buf_dma;
46023 +                                       ep->dwc_ep.start_xfer_buff =
46024 +                                           req->dw_align_buf;
46025 +                                       ep->dwc_ep.xfer_buff =
46026 +                                           req->dw_align_buf;
46027 +                               } else {
46028 +                                       ep->dwc_ep.dma_addr = dma_buf;
46029 +                                       ep->dwc_ep.start_xfer_buff = buf;
46030 +                                        ep->dwc_ep.xfer_buff = buf;
46031 +                               }
46032 +                               ep->dwc_ep.xfer_len = 0;
46033 +                               ep->dwc_ep.xfer_count = 0;
46034 +                               ep->dwc_ep.sent_zlp = 0;
46035 +                               ep->dwc_ep.total_len = buflen;
46036 +
46037 +                               ep->dwc_ep.maxxfer = max_transfer;
46038 +                               if (GET_CORE_IF(pcd)->dma_desc_enable) {
46039 +                                       uint32_t out_max_xfer =
46040 +                                           DDMA_MAX_TRANSFER_SIZE -
46041 +                                           (DDMA_MAX_TRANSFER_SIZE % 4);
46042 +                                       if (ep->dwc_ep.is_in) {
46043 +                                               if (ep->dwc_ep.maxxfer >
46044 +                                                   DDMA_MAX_TRANSFER_SIZE) {
46045 +                                                       ep->dwc_ep.maxxfer =
46046 +                                                           DDMA_MAX_TRANSFER_SIZE;
46047 +                                               }
46048 +                                       } else {
46049 +                                               if (ep->dwc_ep.maxxfer >
46050 +                                                   out_max_xfer) {
46051 +                                                       ep->dwc_ep.maxxfer =
46052 +                                                           out_max_xfer;
46053 +                                               }
46054 +                                       }
46055 +                               }
46056 +                               if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
46057 +                                       ep->dwc_ep.maxxfer -=
46058 +                                           (ep->dwc_ep.maxxfer %
46059 +                                            ep->dwc_ep.maxpacket);
46060 +                               }
46061 +
46062 +                               if (zero) {
46063 +                                       if ((ep->dwc_ep.total_len %
46064 +                                            ep->dwc_ep.maxpacket == 0)
46065 +                                           && (ep->dwc_ep.total_len != 0)) {
46066 +                                               ep->dwc_ep.sent_zlp = 1;
46067 +                                       }
46068 +                               }
46069 +#ifdef DWC_UTE_CFI
46070 +                       }
46071 +#endif
46072 +                       dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
46073 +                                                 &ep->dwc_ep);
46074 +               }
46075 +       }
46076 +
46077 +       if (req != 0) {
46078 +               ++pcd->request_pending;
46079 +               DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
46080 +               if (ep->dwc_ep.is_in && ep->stopped
46081 +                   && !(GET_CORE_IF(pcd)->dma_enable)) {
46082 +                       /** @todo NGS Create a function for this. */
46083 +                       diepmsk_data_t diepmsk = {.d32 = 0 };
46084 +                       diepmsk.b.intktxfemp = 1;
46085 +                       if (GET_CORE_IF(pcd)->multiproc_int_enable) {
46086 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46087 +                                                dev_if->dev_global_regs->diepeachintmsk
46088 +                                                [ep->dwc_ep.num], 0,
46089 +                                                diepmsk.d32);
46090 +                       } else {
46091 +                               DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
46092 +                                                dev_if->dev_global_regs->
46093 +                                                diepmsk, 0, diepmsk.d32);
46094 +                       }
46095 +
46096 +               }
46097 +       }
46098 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46099 +
46100 +       return 0;
46101 +}
46102 +
46103 +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
46104 +                          void *req_handle)
46105 +{
46106 +       dwc_irqflags_t flags;
46107 +       dwc_otg_pcd_request_t *req;
46108 +       dwc_otg_pcd_ep_t *ep;
46109 +
46110 +       ep = get_ep_from_handle(pcd, ep_handle);
46111 +       if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
46112 +               DWC_WARN("bad argument\n");
46113 +               return -DWC_E_INVALID;
46114 +       }
46115 +
46116 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46117 +
46118 +       /* make sure it's actually queued on this endpoint */
46119 +       DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
46120 +               if (req->priv == (void *)req_handle) {
46121 +                       break;
46122 +               }
46123 +       }
46124 +
46125 +       if (req->priv != (void *)req_handle) {
46126 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46127 +               return -DWC_E_INVALID;
46128 +       }
46129 +
46130 +       if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
46131 +               dwc_otg_request_done(ep, req, -DWC_E_RESTART);
46132 +       } else {
46133 +               req = NULL;
46134 +       }
46135 +
46136 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46137 +
46138 +       return req ? 0 : -DWC_E_SHUTDOWN;
46139 +
46140 +}
46141 +
46142 +/**
46143 + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
46144 + *
46145 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
46146 + * requests. If the gadget driver clears the halt status, it will
46147 + * automatically unwedge the endpoint.
46148 + *
46149 + * Returns zero on success, else negative DWC error code.
46150 + */
46151 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
46152 +{
46153 +       dwc_otg_pcd_ep_t *ep;
46154 +       dwc_irqflags_t flags;
46155 +       int retval = 0;
46156 +
46157 +       ep = get_ep_from_handle(pcd, ep_handle);
46158 +
46159 +       if ((!ep->desc && ep != &pcd->ep0) ||
46160 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46161 +               DWC_WARN("%s, bad ep\n", __func__);
46162 +               return -DWC_E_INVALID;
46163 +       }
46164 +
46165 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46166 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46167 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46168 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46169 +               retval = -DWC_E_AGAIN;
46170 +       } else {
46171 +                /* This code needs to be reviewed */
46172 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46173 +                       dtxfsts_data_t txstatus;
46174 +                       fifosize_data_t txfifosize;
46175 +
46176 +                       txfifosize.d32 =
46177 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46178 +                                          core_global_regs->dtxfsiz[ep->dwc_ep.
46179 +                                                                    tx_fifo_num]);
46180 +                       txstatus.d32 =
46181 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->
46182 +                                          dev_if->in_ep_regs[ep->dwc_ep.num]->
46183 +                                          dtxfsts);
46184 +
46185 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46186 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46187 +                               retval = -DWC_E_AGAIN;
46188 +                       } else {
46189 +                               if (ep->dwc_ep.num == 0) {
46190 +                                       pcd->ep0state = EP0_STALL;
46191 +                               }
46192 +
46193 +                               ep->stopped = 1;
46194 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46195 +                                                    &ep->dwc_ep);
46196 +                       }
46197 +               } else {
46198 +                       if (ep->dwc_ep.num == 0) {
46199 +                               pcd->ep0state = EP0_STALL;
46200 +                       }
46201 +
46202 +                       ep->stopped = 1;
46203 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46204 +               }
46205 +       }
46206 +
46207 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46208 +
46209 +       return retval;
46210 +}
46211 +
46212 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
46213 +{
46214 +       dwc_otg_pcd_ep_t *ep;
46215 +       dwc_irqflags_t flags;
46216 +       int retval = 0;
46217 +
46218 +       ep = get_ep_from_handle(pcd, ep_handle);
46219 +
46220 +       if (!ep || (!ep->desc && ep != &pcd->ep0) ||
46221 +           (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
46222 +               DWC_WARN("%s, bad ep\n", __func__);
46223 +               return -DWC_E_INVALID;
46224 +       }
46225 +
46226 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46227 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
46228 +               DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
46229 +                        ep->dwc_ep.is_in ? "IN" : "OUT");
46230 +               retval = -DWC_E_AGAIN;
46231 +       } else if (value == 0) {
46232 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46233 +       } else if (value == 1) {
46234 +               if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
46235 +                       dtxfsts_data_t txstatus;
46236 +                       fifosize_data_t txfifosize;
46237 +
46238 +                       txfifosize.d32 =
46239 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
46240 +                                          dtxfsiz[ep->dwc_ep.tx_fifo_num]);
46241 +                       txstatus.d32 =
46242 +                           DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
46243 +                                          in_ep_regs[ep->dwc_ep.num]->dtxfsts);
46244 +
46245 +                       if (txstatus.b.txfspcavail < txfifosize.b.depth) {
46246 +                               DWC_WARN("%s() Data In Tx Fifo\n", __func__);
46247 +                               retval = -DWC_E_AGAIN;
46248 +                       } else {
46249 +                               if (ep->dwc_ep.num == 0) {
46250 +                                       pcd->ep0state = EP0_STALL;
46251 +                               }
46252 +
46253 +                               ep->stopped = 1;
46254 +                               dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
46255 +                                                    &ep->dwc_ep);
46256 +                       }
46257 +               } else {
46258 +                       if (ep->dwc_ep.num == 0) {
46259 +                               pcd->ep0state = EP0_STALL;
46260 +                       }
46261 +
46262 +                       ep->stopped = 1;
46263 +                       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
46264 +               }
46265 +       } else if (value == 2) {
46266 +               ep->dwc_ep.stall_clear_flag = 0;
46267 +       } else if (value == 3) {
46268 +               ep->dwc_ep.stall_clear_flag = 1;
46269 +       }
46270 +
46271 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46272 +
46273 +       return retval;
46274 +}
46275 +
46276 +/**
46277 + * This function initiates remote wakeup of the host from suspend state.
46278 + */
46279 +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
46280 +{
46281 +       dctl_data_t dctl = { 0 };
46282 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46283 +       dsts_data_t dsts;
46284 +
46285 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
46286 +       if (!dsts.b.suspsts) {
46287 +               DWC_WARN("Remote wakeup while is not in suspend state\n");
46288 +       }
46289 +       /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
46290 +       if (pcd->remote_wakeup_enable) {
46291 +               if (set) {
46292 +
46293 +                       if (core_if->adp_enable) {
46294 +                               gpwrdn_data_t gpwrdn;
46295 +
46296 +                               dwc_otg_adp_probe_stop(core_if);
46297 +
46298 +                               /* Mask SRP detected interrupt from Power Down Logic */
46299 +                               gpwrdn.d32 = 0;
46300 +                               gpwrdn.b.srp_det_msk = 1;
46301 +                               DWC_MODIFY_REG32(&core_if->
46302 +                                                core_global_regs->gpwrdn,
46303 +                                                gpwrdn.d32, 0);
46304 +
46305 +                               /* Disable Power Down Logic */
46306 +                               gpwrdn.d32 = 0;
46307 +                               gpwrdn.b.pmuactv = 1;
46308 +                               DWC_MODIFY_REG32(&core_if->
46309 +                                                core_global_regs->gpwrdn,
46310 +                                                gpwrdn.d32, 0);
46311 +
46312 +                               /*
46313 +                                * Initialize the Core for Device mode.
46314 +                                */
46315 +                               core_if->op_state = B_PERIPHERAL;
46316 +                               dwc_otg_core_init(core_if);
46317 +                               dwc_otg_enable_global_interrupts(core_if);
46318 +                               cil_pcd_start(core_if);
46319 +
46320 +                               dwc_otg_initiate_srp(core_if);
46321 +                       }
46322 +
46323 +                       dctl.b.rmtwkupsig = 1;
46324 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46325 +                                        dctl, 0, dctl.d32);
46326 +                       DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46327 +
46328 +                       dwc_mdelay(2);
46329 +                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
46330 +                                        dctl, dctl.d32, 0);
46331 +                       DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
46332 +               }
46333 +       } else {
46334 +               DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
46335 +       }
46336 +}
46337 +
46338 +#ifdef CONFIG_USB_DWC_OTG_LPM
46339 +/**
46340 + * This function initiates remote wakeup of the host from L1 sleep state.
46341 + */
46342 +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
46343 +{
46344 +       glpmcfg_data_t lpmcfg;
46345 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46346 +
46347 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46348 +
46349 +       /* Check if we are in L1 state */
46350 +       if (!lpmcfg.b.prt_sleep_sts) {
46351 +               DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
46352 +               return;
46353 +       }
46354 +
46355 +       /* Check if host allows remote wakeup */
46356 +       if (!lpmcfg.b.rem_wkup_en) {
46357 +               DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
46358 +               return;
46359 +       }
46360 +
46361 +       /* Check if Resume OK */
46362 +       if (!lpmcfg.b.sleep_state_resumeok) {
46363 +               DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
46364 +               return;
46365 +       }
46366 +
46367 +       lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
46368 +       lpmcfg.b.en_utmi_sleep = 0;
46369 +       lpmcfg.b.hird_thres &= (~(1 << 4));
46370 +       DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
46371 +
46372 +       if (set) {
46373 +               dctl_data_t dctl = {.d32 = 0 };
46374 +               dctl.b.rmtwkupsig = 1;
46375 +               /* Set RmtWkUpSig bit to start remote wakup signaling.
46376 +                * Hardware will automatically clear this bit.
46377 +                */
46378 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
46379 +                                0, dctl.d32);
46380 +               DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
46381 +       }
46382 +
46383 +}
46384 +#endif
46385 +
46386 +/**
46387 + * Performs remote wakeup.
46388 + */
46389 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
46390 +{
46391 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46392 +       dwc_irqflags_t flags;
46393 +       if (dwc_otg_is_device_mode(core_if)) {
46394 +               DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46395 +#ifdef CONFIG_USB_DWC_OTG_LPM
46396 +               if (core_if->lx_state == DWC_OTG_L1) {
46397 +                       dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
46398 +               } else {
46399 +#endif
46400 +                       dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
46401 +#ifdef CONFIG_USB_DWC_OTG_LPM
46402 +               }
46403 +#endif
46404 +               DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46405 +       }
46406 +       return;
46407 +}
46408 +
46409 +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
46410 +{
46411 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
46412 +       dctl_data_t dctl = { 0 };
46413 +
46414 +       if (dwc_otg_is_device_mode(core_if)) {
46415 +               dctl.b.sftdiscon = 1;
46416 +               DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
46417 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
46418 +               dwc_udelay(no_of_usecs);
46419 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
46420 +
46421 +       } else{
46422 +               DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
46423 +       }
46424 +       return;
46425 +
46426 +}
46427 +
46428 +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
46429 +{
46430 +       dsts_data_t dsts;
46431 +       gotgctl_data_t gotgctl;
46432 +
46433 +       /*
46434 +        * This function starts the Protocol if no session is in progress. If
46435 +        * a session is already in progress, but the device is suspended,
46436 +        * remote wakeup signaling is started.
46437 +        */
46438 +
46439 +       /* Check if valid session */
46440 +       gotgctl.d32 =
46441 +           DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
46442 +       if (gotgctl.b.bsesvld) {
46443 +               /* Check if suspend state */
46444 +               dsts.d32 =
46445 +                   DWC_READ_REG32(&
46446 +                                  (GET_CORE_IF(pcd)->dev_if->
46447 +                                   dev_global_regs->dsts));
46448 +               if (dsts.b.suspsts) {
46449 +                       dwc_otg_pcd_remote_wakeup(pcd, 1);
46450 +               }
46451 +       } else {
46452 +               dwc_otg_pcd_initiate_srp(pcd);
46453 +       }
46454 +
46455 +       return 0;
46456 +
46457 +}
46458 +
46459 +/**
46460 + * Start the SRP timer to detect when the SRP does not complete within
46461 + * 6 seconds.
46462 + *
46463 + * @param pcd the pcd structure.
46464 + */
46465 +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
46466 +{
46467 +       dwc_irqflags_t flags;
46468 +       DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
46469 +       dwc_otg_initiate_srp(GET_CORE_IF(pcd));
46470 +       DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
46471 +}
46472 +
46473 +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
46474 +{
46475 +       return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
46476 +}
46477 +
46478 +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
46479 +{
46480 +       return GET_CORE_IF(pcd)->core_params->lpm_enable;
46481 +}
46482 +
46483 +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
46484 +{
46485 +       return pcd->b_hnp_enable;
46486 +}
46487 +
46488 +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
46489 +{
46490 +       return pcd->a_hnp_support;
46491 +}
46492 +
46493 +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
46494 +{
46495 +       return pcd->a_alt_hnp_support;
46496 +}
46497 +
46498 +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
46499 +{
46500 +       return pcd->remote_wakeup_enable;
46501 +}
46502 +
46503 +#endif /* DWC_HOST_ONLY */
46504 --- /dev/null
46505 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
46506 @@ -0,0 +1,266 @@
46507 +/* ==========================================================================
46508 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
46509 + * $Revision: #48 $
46510 + * $Date: 2012/08/10 $
46511 + * $Change: 2047372 $
46512 + *
46513 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46514 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46515 + * otherwise expressly agreed to in writing between Synopsys and you.
46516 + *
46517 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46518 + * any End User Software License Agreement or Agreement for Licensed Product
46519 + * with Synopsys or any supplement thereto. You are permitted to use and
46520 + * redistribute this Software in source and binary forms, with or without
46521 + * modification, provided that redistributions of source code must retain this
46522 + * notice. You may not view, use, disclose, copy or distribute this file or
46523 + * any information contained herein except pursuant to this license grant from
46524 + * Synopsys. If you do not agree with this notice, including the disclaimer
46525 + * below, then you are not authorized to use the Software.
46526 + *
46527 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46528 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46529 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46530 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46531 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46532 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46533 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46534 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46535 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46536 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46537 + * DAMAGE.
46538 + * ========================================================================== */
46539 +#ifndef DWC_HOST_ONLY
46540 +#if !defined(__DWC_PCD_H__)
46541 +#define __DWC_PCD_H__
46542 +
46543 +#include "dwc_otg_os_dep.h"
46544 +#include "usb.h"
46545 +#include "dwc_otg_cil.h"
46546 +#include "dwc_otg_pcd_if.h"
46547 +struct cfiobject;
46548 +
46549 +/**
46550 + * @file
46551 + *
46552 + * This file contains the structures, constants, and interfaces for
46553 + * the Perpherial Contoller Driver (PCD).
46554 + *
46555 + * The Peripheral Controller Driver (PCD) for Linux will implement the
46556 + * Gadget API, so that the existing Gadget drivers can be used. For
46557 + * the Mass Storage Function driver the File-backed USB Storage Gadget
46558 + * (FBS) driver will be used.  The FBS driver supports the
46559 + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
46560 + * transports.
46561 + *
46562 + */
46563 +
46564 +/** Invalid DMA Address */
46565 +#define DWC_DMA_ADDR_INVALID   (~(dwc_dma_t)0)
46566 +
46567 +/** Max Transfer size for any EP */
46568 +#define DDMA_MAX_TRANSFER_SIZE 65535
46569 +
46570 +/**
46571 + * Get the pointer to the core_if from the pcd pointer.
46572 + */
46573 +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
46574 +
46575 +/**
46576 + * States of EP0.
46577 + */
46578 +typedef enum ep0_state {
46579 +       EP0_DISCONNECT,         /* no host */
46580 +       EP0_IDLE,
46581 +       EP0_IN_DATA_PHASE,
46582 +       EP0_OUT_DATA_PHASE,
46583 +       EP0_IN_STATUS_PHASE,
46584 +       EP0_OUT_STATUS_PHASE,
46585 +       EP0_STALL,
46586 +} ep0state_e;
46587 +
46588 +/** Fordward declaration.*/
46589 +struct dwc_otg_pcd;
46590 +
46591 +/** DWC_otg iso request structure.
46592 + *
46593 + */
46594 +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
46595 +
46596 +#ifdef DWC_UTE_PER_IO
46597 +
46598 +/**
46599 + * This shall be the exact analogy of the same type structure defined in the
46600 + * usb_gadget.h. Each descriptor contains
46601 + */
46602 +struct dwc_iso_pkt_desc_port {
46603 +       uint32_t offset;
46604 +       uint32_t length;        /* expected length */
46605 +       uint32_t actual_length;
46606 +       uint32_t status;
46607 +};
46608 +
46609 +struct dwc_iso_xreq_port {
46610 +       /** transfer/submission flag */
46611 +       uint32_t tr_sub_flags;
46612 +       /** Start the request ASAP */
46613 +#define DWC_EREQ_TF_ASAP               0x00000002
46614 +       /** Just enqueue the request w/o initiating a transfer */
46615 +#define DWC_EREQ_TF_ENQUEUE            0x00000004
46616 +
46617 +       /**
46618 +       * count of ISO packets attached to this request - shall
46619 +       * not exceed the pio_alloc_pkt_count
46620 +       */
46621 +       uint32_t pio_pkt_count;
46622 +       /** count of ISO packets allocated for this request */
46623 +       uint32_t pio_alloc_pkt_count;
46624 +       /** number of ISO packet errors */
46625 +       uint32_t error_count;
46626 +       /** reserved for future extension */
46627 +       uint32_t res;
46628 +       /** Will be allocated and freed in the UTE gadget and based on the CFC value */
46629 +       struct dwc_iso_pkt_desc_port *per_io_frame_descs;
46630 +};
46631 +#endif
46632 +/** DWC_otg request structure.
46633 + * This structure is a list of requests.
46634 + */
46635 +typedef struct dwc_otg_pcd_request {
46636 +       void *priv;
46637 +       void *buf;
46638 +       dwc_dma_t dma;
46639 +       uint32_t length;
46640 +       uint32_t actual;
46641 +       unsigned sent_zlp:1;
46642 +    /**
46643 +     * Used instead of original buffer if
46644 +     * it(physical address) is not dword-aligned.
46645 +     **/
46646 +     uint8_t *dw_align_buf;
46647 +     dwc_dma_t dw_align_buf_dma;
46648 +
46649 +        DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
46650 +#ifdef DWC_UTE_PER_IO
46651 +       struct dwc_iso_xreq_port ext_req;
46652 +       //void *priv_ereq_nport; /*  */
46653 +#endif
46654 +} dwc_otg_pcd_request_t;
46655 +
46656 +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
46657 +
46658 +/**      PCD EP structure.
46659 + * This structure describes an EP, there is an array of EPs in the PCD
46660 + * structure.
46661 + */
46662 +typedef struct dwc_otg_pcd_ep {
46663 +       /** USB EP Descriptor */
46664 +       const usb_endpoint_descriptor_t *desc;
46665 +
46666 +       /** queue of dwc_otg_pcd_requests. */
46667 +       struct req_list queue;
46668 +       unsigned stopped:1;
46669 +       unsigned disabling:1;
46670 +       unsigned dma:1;
46671 +       unsigned queue_sof:1;
46672 +
46673 +#ifdef DWC_EN_ISOC
46674 +       /** ISOC req handle passed */
46675 +       void *iso_req_handle;
46676 +#endif                         //_EN_ISOC_
46677 +
46678 +       /** DWC_otg ep data. */
46679 +       dwc_ep_t dwc_ep;
46680 +
46681 +       /** Pointer to PCD */
46682 +       struct dwc_otg_pcd *pcd;
46683 +
46684 +       void *priv;
46685 +} dwc_otg_pcd_ep_t;
46686 +
46687 +/** DWC_otg PCD Structure.
46688 + * This structure encapsulates the data for the dwc_otg PCD.
46689 + */
46690 +struct dwc_otg_pcd {
46691 +       const struct dwc_otg_pcd_function_ops *fops;
46692 +       /** The DWC otg device pointer */
46693 +       struct dwc_otg_device *otg_dev;
46694 +       /** Core Interface */
46695 +       dwc_otg_core_if_t *core_if;
46696 +       /** State of EP0 */
46697 +       ep0state_e ep0state;
46698 +       /** EP0 Request is pending */
46699 +       unsigned ep0_pending:1;
46700 +       /** Indicates when SET CONFIGURATION Request is in process */
46701 +       unsigned request_config:1;
46702 +       /** The state of the Remote Wakeup Enable. */
46703 +       unsigned remote_wakeup_enable:1;
46704 +       /** The state of the B-Device HNP Enable. */
46705 +       unsigned b_hnp_enable:1;
46706 +       /** The state of A-Device HNP Support. */
46707 +       unsigned a_hnp_support:1;
46708 +       /** The state of the A-Device Alt HNP support. */
46709 +       unsigned a_alt_hnp_support:1;
46710 +       /** Count of pending Requests */
46711 +       unsigned request_pending;
46712 +
46713 +       /** SETUP packet for EP0
46714 +        * This structure is allocated as a DMA buffer on PCD initialization
46715 +        * with enough space for up to 3 setup packets.
46716 +        */
46717 +       union {
46718 +               usb_device_request_t req;
46719 +               uint32_t d32[2];
46720 +       } *setup_pkt;
46721 +
46722 +       dwc_dma_t setup_pkt_dma_handle;
46723 +
46724 +       /* Additional buffer and flag for CTRL_WR premature case */
46725 +       uint8_t *backup_buf;
46726 +       unsigned data_terminated;
46727 +
46728 +       /** 2-byte dma buffer used to return status from GET_STATUS */
46729 +       uint16_t *status_buf;
46730 +       dwc_dma_t status_buf_dma_handle;
46731 +
46732 +       /** EP0 */
46733 +       dwc_otg_pcd_ep_t ep0;
46734 +
46735 +       /** Array of IN EPs. */
46736 +       dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
46737 +       /** Array of OUT EPs. */
46738 +       dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
46739 +       /** number of valid EPs in the above array. */
46740 +//        unsigned      num_eps : 4;
46741 +       dwc_spinlock_t *lock;
46742 +
46743 +       /** Tasklet to defer starting of TEST mode transmissions until
46744 +        *      Status Phase has been completed.
46745 +        */
46746 +       dwc_tasklet_t *test_mode_tasklet;
46747 +
46748 +       /** Tasklet to delay starting of xfer in DMA mode */
46749 +       dwc_tasklet_t *start_xfer_tasklet;
46750 +
46751 +       /** The test mode to enter when the tasklet is executed. */
46752 +       unsigned test_mode;
46753 +       /** The cfi_api structure that implements most of the CFI API
46754 +        * and OTG specific core configuration functionality
46755 +        */
46756 +#ifdef DWC_UTE_CFI
46757 +       struct cfiobject *cfi;
46758 +#endif
46759 +
46760 +};
46761 +
46762 +//FIXME this functions should be static, and this prototypes should be removed
46763 +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
46764 +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
46765 +                                dwc_otg_pcd_request_t * req, int32_t status);
46766 +
46767 +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
46768 +                            void *req_handle);
46769 +
46770 +extern void do_test_mode(void *data);
46771 +#endif
46772 +#endif /* DWC_HOST_ONLY */
46773 --- /dev/null
46774 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
46775 @@ -0,0 +1,360 @@
46776 +/* ==========================================================================
46777 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
46778 + * $Revision: #11 $
46779 + * $Date: 2011/10/26 $
46780 + * $Change: 1873028 $
46781 + *
46782 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
46783 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
46784 + * otherwise expressly agreed to in writing between Synopsys and you.
46785 + *
46786 + * The Software IS NOT an item of Licensed Software or Licensed Product under
46787 + * any End User Software License Agreement or Agreement for Licensed Product
46788 + * with Synopsys or any supplement thereto. You are permitted to use and
46789 + * redistribute this Software in source and binary forms, with or without
46790 + * modification, provided that redistributions of source code must retain this
46791 + * notice. You may not view, use, disclose, copy or distribute this file or
46792 + * any information contained herein except pursuant to this license grant from
46793 + * Synopsys. If you do not agree with this notice, including the disclaimer
46794 + * below, then you are not authorized to use the Software.
46795 + *
46796 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
46797 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46798 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46799 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
46800 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46801 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
46802 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
46803 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46804 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46805 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46806 + * DAMAGE.
46807 + * ========================================================================== */
46808 +#ifndef DWC_HOST_ONLY
46809 +
46810 +#if !defined(__DWC_PCD_IF_H__)
46811 +#define __DWC_PCD_IF_H__
46812 +
46813 +//#include "dwc_os.h"
46814 +#include "dwc_otg_core_if.h"
46815 +
46816 +/** @file
46817 + * This file defines DWC_OTG PCD Core API.
46818 + */
46819 +
46820 +struct dwc_otg_pcd;
46821 +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
46822 +
46823 +/** Maxpacket size for EP0 */
46824 +#define MAX_EP0_SIZE   64
46825 +/** Maxpacket size for any EP */
46826 +#define MAX_PACKET_SIZE 1024
46827 +
46828 +/** @name Function Driver Callbacks */
46829 +/** @{ */
46830 +
46831 +/** This function will be called whenever a previously queued request has
46832 + * completed.  The status value will be set to -DWC_E_SHUTDOWN to indicated a
46833 + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
46834 + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
46835 + * parameters. */
46836 +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46837 +                                   void *req_handle, int32_t status,
46838 +                                   uint32_t actual);
46839 +/**
46840 + * This function will be called whenever a previousle queued ISOC request has
46841 + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
46842 + * function.
46843 + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
46844 + * functions.
46845 + */
46846 +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46847 +                                        void *req_handle, int proc_buf_num);
46848 +/** This function should handle any SETUP request that cannot be handled by the
46849 + * PCD Core.  This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
46850 + * class-specific requests, etc.  The function must non-blocking.
46851 + *
46852 + * Returns 0 on success.
46853 + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
46854 + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
46855 + * Returns -DWC_E_SHUTDOWN on any other error. */
46856 +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
46857 +/** This is called whenever the device has been disconnected.  The function
46858 + * driver should take appropriate action to clean up all pending requests in the
46859 + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
46860 + * state. */
46861 +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
46862 +/** This function is called when device has been connected. */
46863 +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
46864 +/** This function is called when device has been suspended */
46865 +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
46866 +/** This function is called when device has received LPM tokens, i.e.
46867 + * device has been sent to sleep state. */
46868 +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
46869 +/** This function is called when device has been resumed
46870 + * from suspend(L2) or L1 sleep state. */
46871 +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
46872 +/** This function is called whenever hnp params has been changed.
46873 + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
46874 + * to get hnp parameters. */
46875 +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
46876 +/** This function is called whenever USB RESET is detected. */
46877 +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
46878 +
46879 +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
46880 +
46881 +/**
46882 + *
46883 + * @param ep_handle    Void pointer to the usb_ep structure
46884 + * @param ereq_port Pointer to the extended request structure created in the
46885 + *                                     portable part.
46886 + */
46887 +typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
46888 +                                    void *req_handle, int32_t status,
46889 +                                    void *ereq_port);
46890 +/** Function Driver Ops Data Structure */
46891 +struct dwc_otg_pcd_function_ops {
46892 +       dwc_connect_cb_t connect;
46893 +       dwc_disconnect_cb_t disconnect;
46894 +       dwc_setup_cb_t setup;
46895 +       dwc_completion_cb_t complete;
46896 +       dwc_isoc_completion_cb_t isoc_complete;
46897 +       dwc_suspend_cb_t suspend;
46898 +       dwc_sleep_cb_t sleep;
46899 +       dwc_resume_cb_t resume;
46900 +       dwc_reset_cb_t reset;
46901 +       dwc_hnp_params_changed_cb_t hnp_changed;
46902 +       cfi_setup_cb_t cfi_setup;
46903 +#ifdef DWC_UTE_PER_IO
46904 +       xiso_completion_cb_t xisoc_complete;
46905 +#endif
46906 +};
46907 +/** @} */
46908 +
46909 +/** @name Function Driver Functions */
46910 +/** @{ */
46911 +
46912 +/** Call this function to get pointer on dwc_otg_pcd_t,
46913 + * this pointer will be used for all PCD API functions.
46914 + *
46915 + * @param core_if The DWC_OTG Core
46916 + */
46917 +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
46918 +
46919 +/** Frees PCD allocated by dwc_otg_pcd_init
46920 + *
46921 + * @param pcd The PCD
46922 + */
46923 +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
46924 +
46925 +/** Call this to bind the function driver to the PCD Core.
46926 + *
46927 + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
46928 + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
46929 + */
46930 +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
46931 +                             const struct dwc_otg_pcd_function_ops *fops);
46932 +
46933 +/** Enables an endpoint for use.  This function enables an endpoint in
46934 + * the PCD.  The endpoint is described by the ep_desc which has the
46935 + * same format as a USB ep descriptor.  The ep_handle parameter is used to refer
46936 + * to the endpoint from other API functions and in callbacks.  Normally this
46937 + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
46938 + * core for that interface.
46939 + *
46940 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46941 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46942 + * Returns 0 on success.
46943 + *
46944 + * @param pcd The PCD
46945 + * @param ep_desc Endpoint descriptor
46946 + * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
46947 + */
46948 +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
46949 +                                const uint8_t * ep_desc, void *usb_ep);
46950 +
46951 +/** Disable the endpoint referenced by ep_handle.
46952 + *
46953 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46954 + * Returns -DWC_E_SHUTDOWN if any other error occurred.
46955 + * Returns 0 on success. */
46956 +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
46957 +
46958 +/** Queue a data transfer request on the endpoint referenced by ep_handle.
46959 + * After the transfer is completes, the complete callback will be called with
46960 + * the request status.
46961 + *
46962 + * @param pcd The PCD
46963 + * @param ep_handle The handle of the endpoint
46964 + * @param buf The buffer for the data
46965 + * @param dma_buf The DMA buffer for the data
46966 + * @param buflen The length of the data transfer
46967 + * @param zero Specifies whether to send zero length last packet.
46968 + * @param req_handle Set this handle to any value to use to reference this
46969 + * request in the ep_dequeue function or from the complete callback
46970 + * @param atomic_alloc If driver need to perform atomic allocations
46971 + * for internal data structures.
46972 + *
46973 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46974 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46975 + * Returns 0 on success. */
46976 +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46977 +                               uint8_t * buf, dwc_dma_t dma_buf,
46978 +                               uint32_t buflen, int zero, void *req_handle,
46979 +                               int atomic_alloc);
46980 +#ifdef DWC_UTE_PER_IO
46981 +/**
46982 + *
46983 + * @param ereq_nonport Pointer to the extended request part of the
46984 + *                                             usb_request structure defined in usb_gadget.h file.
46985 + */
46986 +extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
46987 +                                    uint8_t * buf, dwc_dma_t dma_buf,
46988 +                                    uint32_t buflen, int zero,
46989 +                                    void *req_handle, int atomic_alloc,
46990 +                                    void *ereq_nonport);
46991 +
46992 +#endif
46993 +
46994 +/** De-queue the specified data transfer that has not yet completed.
46995 + *
46996 + * Returns -DWC_E_INVALID if invalid parameters were passed.
46997 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
46998 + * Returns 0 on success. */
46999 +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
47000 +                                 void *req_handle);
47001 +
47002 +/** Halt (STALL) an endpoint or clear it.
47003 + *
47004 + * Returns -DWC_E_INVALID if invalid parameters were passed.
47005 + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
47006 + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
47007 + * Returns 0 on success. */
47008 +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
47009 +
47010 +/** This function */
47011 +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
47012 +
47013 +/** This function should be called on every hardware interrupt */
47014 +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
47015 +
47016 +/** This function returns current frame number */
47017 +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
47018 +
47019 +/**
47020 + * Start isochronous transfers on the endpoint referenced by ep_handle.
47021 + * For isochronous transfers duble buffering is used.
47022 + * After processing each of buffers comlete callback will be called with
47023 + * status for each transaction.
47024 + *
47025 + * @param pcd The PCD
47026 + * @param ep_handle The handle of the endpoint
47027 + * @param buf0 The virtual address of first data buffer
47028 + * @param buf1 The virtual address of second data buffer
47029 + * @param dma0 The DMA address of first data buffer
47030 + * @param dma1 The DMA address of second data buffer
47031 + * @param sync_frame Data pattern frame number
47032 + * @param dp_frame Data size for pattern frame
47033 + * @param data_per_frame Data size for regular frame
47034 + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
47035 + * @param buf_proc_intrvl Interval of ISOC Buffer processing
47036 + * @param req_handle Handle of ISOC request
47037 + * @param atomic_alloc Specefies whether to perform atomic allocation for
47038 + *                     internal data structures.
47039 + *
47040 + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
47041 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
47042 + * Returns -DW_E_SHUTDOWN for any other error.
47043 + * Returns 0 on success
47044 + */
47045 +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
47046 +                                   uint8_t * buf0, uint8_t * buf1,
47047 +                                   dwc_dma_t dma0, dwc_dma_t dma1,
47048 +                                   int sync_frame, int dp_frame,
47049 +                                   int data_per_frame, int start_frame,
47050 +                                   int buf_proc_intrvl, void *req_handle,
47051 +                                   int atomic_alloc);
47052 +
47053 +/** Stop ISOC transfers on endpoint referenced by ep_handle.
47054 + *
47055 + * @param pcd The PCD
47056 + * @param ep_handle The handle of the endpoint
47057 + * @param req_handle Handle of ISOC request
47058 + *
47059 + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
47060 + * Returns 0 on success
47061 + */
47062 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
47063 +                           void *req_handle);
47064 +
47065 +/** Get ISOC packet status.
47066 + *
47067 + * @param pcd The PCD
47068 + * @param ep_handle The handle of the endpoint
47069 + * @param iso_req_handle Isochronoush request handle
47070 + * @param packet Number of packet
47071 + * @param status Out parameter for returning status
47072 + * @param actual Out parameter for returning actual length
47073 + * @param offset Out parameter for returning offset
47074 + *
47075 + */
47076 +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
47077 +                                             void *ep_handle,
47078 +                                             void *iso_req_handle, int packet,
47079 +                                             int *status, int *actual,
47080 +                                             int *offset);
47081 +
47082 +/** Get ISOC packet count.
47083 + *
47084 + * @param pcd The PCD
47085 + * @param ep_handle The handle of the endpoint
47086 + * @param iso_req_handle
47087 + */
47088 +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
47089 +                                           void *ep_handle,
47090 +                                           void *iso_req_handle);
47091 +
47092 +/** This function starts the SRP Protocol if no session is in progress. If
47093 + * a session is already in progress, but the device is suspended,
47094 + * remote wakeup signaling is started.
47095 + */
47096 +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
47097 +
47098 +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
47099 +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
47100 +
47101 +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
47102 +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
47103 +
47104 +/** Initiate SRP */
47105 +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
47106 +
47107 +/** Starts remote wakeup signaling. */
47108 +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
47109 +
47110 +/** Starts micorsecond soft disconnect. */
47111 +extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);
47112 +/** This function returns whether device is dualspeed.*/
47113 +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
47114 +
47115 +/** This function returns whether device is otg. */
47116 +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
47117 +
47118 +/** These functions allow to get hnp parameters */
47119 +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
47120 +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
47121 +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
47122 +
47123 +/** CFI specific Interface functions */
47124 +/** Allocate a cfi buffer */
47125 +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
47126 +                                    dwc_dma_t * addr, size_t buflen,
47127 +                                    int flags);
47128 +
47129 +/******************************************************************************/
47130 +
47131 +/** @} */
47132 +
47133 +#endif                         /* __DWC_PCD_IF_H__ */
47134 +
47135 +#endif                         /* DWC_HOST_ONLY */
47136 --- /dev/null
47137 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
47138 @@ -0,0 +1,5147 @@
47139 +/* ==========================================================================
47140 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
47141 + * $Revision: #116 $
47142 + * $Date: 2012/08/10 $
47143 + * $Change: 2047372 $
47144 + *
47145 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
47146 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
47147 + * otherwise expressly agreed to in writing between Synopsys and you.
47148 + *
47149 + * The Software IS NOT an item of Licensed Software or Licensed Product under
47150 + * any End User Software License Agreement or Agreement for Licensed Product
47151 + * with Synopsys or any supplement thereto. You are permitted to use and
47152 + * redistribute this Software in source and binary forms, with or without
47153 + * modification, provided that redistributions of source code must retain this
47154 + * notice. You may not view, use, disclose, copy or distribute this file or
47155 + * any information contained herein except pursuant to this license grant from
47156 + * Synopsys. If you do not agree with this notice, including the disclaimer
47157 + * below, then you are not authorized to use the Software.
47158 + *
47159 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
47160 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47161 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47162 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
47163 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47164 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
47165 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47166 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47167 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47168 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
47169 + * DAMAGE.
47170 + * ========================================================================== */
47171 +#ifndef DWC_HOST_ONLY
47172 +
47173 +#include "dwc_otg_pcd.h"
47174 +
47175 +#ifdef DWC_UTE_CFI
47176 +#include "dwc_otg_cfi.h"
47177 +#endif
47178 +
47179 +#ifdef DWC_UTE_PER_IO
47180 +extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
47181 +#endif
47182 +//#define PRINT_CFI_DMA_DESCS
47183 +
47184 +#define DEBUG_EP0
47185 +
47186 +/**
47187 + * This function updates OTG.
47188 + */
47189 +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
47190 +{
47191 +
47192 +       if (reset) {
47193 +               pcd->b_hnp_enable = 0;
47194 +               pcd->a_hnp_support = 0;
47195 +               pcd->a_alt_hnp_support = 0;
47196 +       }
47197 +
47198 +       if (pcd->fops->hnp_changed) {
47199 +               pcd->fops->hnp_changed(pcd);
47200 +       }
47201 +}
47202 +
47203 +/** @file
47204 + * This file contains the implementation of the PCD Interrupt handlers.
47205 + *
47206 + * The PCD handles the device interrupts.  Many conditions can cause a
47207 + * device interrupt. When an interrupt occurs, the device interrupt
47208 + * service routine determines the cause of the interrupt and
47209 + * dispatches handling to the appropriate function. These interrupt
47210 + * handling functions are described below.
47211 + * All interrupt registers are processed from LSB to MSB.
47212 + */
47213 +
47214 +/**
47215 + * This function prints the ep0 state for debug purposes.
47216 + */
47217 +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
47218 +{
47219 +#ifdef DEBUG
47220 +       char str[40];
47221 +
47222 +       switch (pcd->ep0state) {
47223 +       case EP0_DISCONNECT:
47224 +               dwc_strcpy(str, "EP0_DISCONNECT");
47225 +               break;
47226 +       case EP0_IDLE:
47227 +               dwc_strcpy(str, "EP0_IDLE");
47228 +               break;
47229 +       case EP0_IN_DATA_PHASE:
47230 +               dwc_strcpy(str, "EP0_IN_DATA_PHASE");
47231 +               break;
47232 +       case EP0_OUT_DATA_PHASE:
47233 +               dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
47234 +               break;
47235 +       case EP0_IN_STATUS_PHASE:
47236 +               dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
47237 +               break;
47238 +       case EP0_OUT_STATUS_PHASE:
47239 +               dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
47240 +               break;
47241 +       case EP0_STALL:
47242 +               dwc_strcpy(str, "EP0_STALL");
47243 +               break;
47244 +       default:
47245 +               dwc_strcpy(str, "EP0_INVALID");
47246 +       }
47247 +
47248 +       DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
47249 +#endif
47250 +}
47251 +
47252 +/**
47253 + * This function calculate the size of the payload in the memory
47254 + * for out endpoints and prints size for debug purposes(used in
47255 + * 2.93a DevOutNak feature).
47256 + */
47257 +static inline void print_memory_payload(dwc_otg_pcd_t * pcd,  dwc_ep_t * ep)
47258 +{
47259 +#ifdef DEBUG
47260 +       deptsiz_data_t deptsiz_init = {.d32 = 0 };
47261 +       deptsiz_data_t deptsiz_updt = {.d32 = 0 };
47262 +       int pack_num;
47263 +       unsigned payload;
47264 +
47265 +       deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
47266 +       deptsiz_updt.d32 =
47267 +               DWC_READ_REG32(&pcd->core_if->dev_if->
47268 +                                               out_ep_regs[ep->num]->doeptsiz);
47269 +       /* Payload will be */
47270 +       payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
47271 +       /* Packet count is decremented every time a packet
47272 +        * is written to the RxFIFO not in to the external memory
47273 +        * So, if payload == 0, then it means no packet was sent to ext memory*/
47274 +       pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
47275 +       DWC_DEBUGPL(DBG_PCDV,
47276 +               "Payload for EP%d-%s\n",
47277 +               ep->num, (ep->is_in ? "IN" : "OUT"));
47278 +       DWC_DEBUGPL(DBG_PCDV,
47279 +               "Number of transfered bytes = 0x%08x\n", payload);
47280 +       DWC_DEBUGPL(DBG_PCDV,
47281 +               "Number of transfered packets = %d\n", pack_num);
47282 +#endif
47283 +}
47284 +
47285 +
47286 +#ifdef DWC_UTE_CFI
47287 +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
47288 +                             const uint8_t * epname, int descnum)
47289 +{
47290 +       CFI_INFO
47291 +           ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
47292 +            epname, descnum, ddesc->buf, ddesc->status.b.bytes,
47293 +            ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
47294 +            ddesc->status.b.bs);
47295 +}
47296 +#endif
47297 +
47298 +/**
47299 + * This function returns pointer to in ep struct with number ep_num
47300 + */
47301 +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47302 +{
47303 +       int i;
47304 +       int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47305 +       if (ep_num == 0) {
47306 +               return &pcd->ep0;
47307 +       } else {
47308 +               for (i = 0; i < num_in_eps; ++i) {
47309 +                       if (pcd->in_ep[i].dwc_ep.num == ep_num)
47310 +                               return &pcd->in_ep[i];
47311 +               }
47312 +               return 0;
47313 +       }
47314 +}
47315 +
47316 +/**
47317 + * This function returns pointer to out ep struct with number ep_num
47318 + */
47319 +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
47320 +{
47321 +       int i;
47322 +       int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47323 +       if (ep_num == 0) {
47324 +               return &pcd->ep0;
47325 +       } else {
47326 +               for (i = 0; i < num_out_eps; ++i) {
47327 +                       if (pcd->out_ep[i].dwc_ep.num == ep_num)
47328 +                               return &pcd->out_ep[i];
47329 +               }
47330 +               return 0;
47331 +       }
47332 +}
47333 +
47334 +/**
47335 + * This functions gets a pointer to an EP from the wIndex address
47336 + * value of the control request.
47337 + */
47338 +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
47339 +{
47340 +       dwc_otg_pcd_ep_t *ep;
47341 +       uint32_t ep_num = UE_GET_ADDR(wIndex);
47342 +
47343 +       if (ep_num == 0) {
47344 +               ep = &pcd->ep0;
47345 +       } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) {   /* in ep */
47346 +               ep = &pcd->in_ep[ep_num - 1];
47347 +       } else {
47348 +               ep = &pcd->out_ep[ep_num - 1];
47349 +       }
47350 +
47351 +       return ep;
47352 +}
47353 +
47354 +/**
47355 + * This function checks the EP request queue, if the queue is not
47356 + * empty the next request is started.
47357 + */
47358 +void start_next_request(dwc_otg_pcd_ep_t * ep)
47359 +{
47360 +       dwc_otg_pcd_request_t *req = 0;
47361 +       uint32_t max_transfer =
47362 +           GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
47363 +
47364 +#ifdef DWC_UTE_CFI
47365 +       struct dwc_otg_pcd *pcd;
47366 +       pcd = ep->pcd;
47367 +#endif
47368 +
47369 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
47370 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
47371 +
47372 +#ifdef DWC_UTE_CFI
47373 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
47374 +                       ep->dwc_ep.cfi_req_len = req->length;
47375 +                       pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
47376 +               } else {
47377 +#endif
47378 +                       /* Setup and start the Transfer */
47379 +                       if (req->dw_align_buf) {
47380 +                               ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
47381 +                               ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
47382 +                               ep->dwc_ep.xfer_buff = req->dw_align_buf;
47383 +                       } else {
47384 +                               ep->dwc_ep.dma_addr = req->dma;
47385 +                               ep->dwc_ep.start_xfer_buff = req->buf;
47386 +                               ep->dwc_ep.xfer_buff = req->buf;
47387 +                       }
47388 +                       ep->dwc_ep.sent_zlp = 0;
47389 +                       ep->dwc_ep.total_len = req->length;
47390 +                       ep->dwc_ep.xfer_len = 0;
47391 +                       ep->dwc_ep.xfer_count = 0;
47392 +
47393 +                       ep->dwc_ep.maxxfer = max_transfer;
47394 +                       if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
47395 +                               uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
47396 +                                   - (DDMA_MAX_TRANSFER_SIZE % 4);
47397 +                               if (ep->dwc_ep.is_in) {
47398 +                                       if (ep->dwc_ep.maxxfer >
47399 +                                           DDMA_MAX_TRANSFER_SIZE) {
47400 +                                               ep->dwc_ep.maxxfer =
47401 +                                                   DDMA_MAX_TRANSFER_SIZE;
47402 +                                       }
47403 +                               } else {
47404 +                                       if (ep->dwc_ep.maxxfer > out_max_xfer) {
47405 +                                               ep->dwc_ep.maxxfer =
47406 +                                                   out_max_xfer;
47407 +                                       }
47408 +                               }
47409 +                       }
47410 +                       if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
47411 +                               ep->dwc_ep.maxxfer -=
47412 +                                   (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
47413 +                       }
47414 +                       if (req->sent_zlp) {
47415 +                               if ((ep->dwc_ep.total_len %
47416 +                                    ep->dwc_ep.maxpacket == 0)
47417 +                                   && (ep->dwc_ep.total_len != 0)) {
47418 +                                       ep->dwc_ep.sent_zlp = 1;
47419 +                               }
47420 +
47421 +                       }
47422 +#ifdef DWC_UTE_CFI
47423 +               }
47424 +#endif
47425 +               dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
47426 +       } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
47427 +               DWC_PRINTF("There are no more ISOC requests \n");
47428 +               ep->dwc_ep.frame_num = 0xFFFFFFFF;
47429 +       }
47430 +}
47431 +
47432 +/**
47433 + * This function handles the SOF Interrupts. At this time the SOF
47434 + * Interrupt is disabled.
47435 + */
47436 +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
47437 +{
47438 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47439 +
47440 +       gintsts_data_t gintsts;
47441 +
47442 +       DWC_DEBUGPL(DBG_PCD, "SOF\n");
47443 +
47444 +       /* Clear interrupt */
47445 +       gintsts.d32 = 0;
47446 +       gintsts.b.sofintr = 1;
47447 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
47448 +
47449 +       return 1;
47450 +}
47451 +
47452 +/**
47453 + * This function handles the Rx Status Queue Level Interrupt, which
47454 + * indicates that there is a least one packet in the Rx FIFO.  The
47455 + * packets are moved from the FIFO to memory, where they will be
47456 + * processed when the Endpoint Interrupt Register indicates Transfer
47457 + * Complete or SETUP Phase Done.
47458 + *
47459 + * Repeat the following until the Rx Status Queue is empty:
47460 + *      -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
47461 + *             info
47462 + *      -# If Receive FIFO is empty then skip to step Clear the interrupt
47463 + *             and exit
47464 + *      -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
47465 + *             SETUP data to the buffer
47466 + *      -# If OUT Data Packet call dwc_otg_read_packet to copy the data
47467 + *             to the destination buffer
47468 + */
47469 +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
47470 +{
47471 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47472 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47473 +       gintmsk_data_t gintmask = {.d32 = 0 };
47474 +       device_grxsts_data_t status;
47475 +       dwc_otg_pcd_ep_t *ep;
47476 +       gintsts_data_t gintsts;
47477 +#ifdef DEBUG
47478 +       static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
47479 +#endif
47480 +
47481 +       //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
47482 +       /* Disable the Rx Status Queue Level interrupt */
47483 +       gintmask.b.rxstsqlvl = 1;
47484 +       DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
47485 +
47486 +       /* Get the Status from the top of the FIFO */
47487 +       status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
47488 +
47489 +       DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
47490 +                   "pktsts:%x Frame:%d(0x%0x)\n",
47491 +                   status.b.epnum, status.b.bcnt,
47492 +                   dpid_str[status.b.dpid],
47493 +                   status.b.pktsts, status.b.fn, status.b.fn);
47494 +       /* Get pointer to EP structure */
47495 +       ep = get_out_ep(pcd, status.b.epnum);
47496 +
47497 +       switch (status.b.pktsts) {
47498 +       case DWC_DSTS_GOUT_NAK:
47499 +               DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
47500 +               break;
47501 +       case DWC_STS_DATA_UPDT:
47502 +               DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
47503 +               if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
47504 +                       /** @todo NGS Check for buffer overflow? */
47505 +                       dwc_otg_read_packet(core_if,
47506 +                                           ep->dwc_ep.xfer_buff,
47507 +                                           status.b.bcnt);
47508 +                       ep->dwc_ep.xfer_count += status.b.bcnt;
47509 +                       ep->dwc_ep.xfer_buff += status.b.bcnt;
47510 +               }
47511 +               break;
47512 +       case DWC_STS_XFER_COMP:
47513 +               DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
47514 +               break;
47515 +       case DWC_DSTS_SETUP_COMP:
47516 +#ifdef DEBUG_EP0
47517 +               DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
47518 +#endif
47519 +               break;
47520 +       case DWC_DSTS_SETUP_UPDT:
47521 +               dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
47522 +#ifdef DEBUG_EP0
47523 +               DWC_DEBUGPL(DBG_PCD,
47524 +                           "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
47525 +                           pcd->setup_pkt->req.bmRequestType,
47526 +                           pcd->setup_pkt->req.bRequest,
47527 +                           UGETW(pcd->setup_pkt->req.wValue),
47528 +                           UGETW(pcd->setup_pkt->req.wIndex),
47529 +                           UGETW(pcd->setup_pkt->req.wLength));
47530 +#endif
47531 +               ep->dwc_ep.xfer_count += status.b.bcnt;
47532 +               break;
47533 +       default:
47534 +               DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
47535 +                           status.b.pktsts);
47536 +               break;
47537 +       }
47538 +
47539 +       /* Enable the Rx Status Queue Level interrupt */
47540 +       DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
47541 +       /* Clear interrupt */
47542 +       gintsts.d32 = 0;
47543 +       gintsts.b.rxstsqlvl = 1;
47544 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47545 +
47546 +       //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
47547 +       return 1;
47548 +}
47549 +
47550 +/**
47551 + * This function examines the Device IN Token Learning Queue to
47552 + * determine the EP number of the last IN token received.  This
47553 + * implementation is for the Mass Storage device where there are only
47554 + * 2 IN EPs (Control-IN and BULK-IN).
47555 + *
47556 + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
47557 + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
47558 + *
47559 + * @param core_if Programming view of DWC_otg controller.
47560 + *
47561 + */
47562 +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
47563 +{
47564 +       dwc_otg_device_global_regs_t *dev_global_regs =
47565 +           core_if->dev_if->dev_global_regs;
47566 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
47567 +       /* Number of Token Queue Registers */
47568 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
47569 +       dtknq1_data_t dtknqr1;
47570 +       uint32_t in_tkn_epnums[4];
47571 +       int ndx = 0;
47572 +       int i = 0;
47573 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
47574 +       int epnum = 0;
47575 +
47576 +       //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
47577 +
47578 +       /* Read the DTKNQ Registers */
47579 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
47580 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
47581 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
47582 +                           in_tkn_epnums[i]);
47583 +               if (addr == &dev_global_regs->dvbusdis) {
47584 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
47585 +               } else {
47586 +                       ++addr;
47587 +               }
47588 +
47589 +       }
47590 +
47591 +       /* Copy the DTKNQR1 data to the bit field. */
47592 +       dtknqr1.d32 = in_tkn_epnums[0];
47593 +       /* Get the EP numbers */
47594 +       in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
47595 +       ndx = dtknqr1.b.intknwptr - 1;
47596 +
47597 +       //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
47598 +       if (ndx == -1) {
47599 +               /** @todo Find a simpler way to calculate the max
47600 +                * queue position.*/
47601 +               int cnt = TOKEN_Q_DEPTH;
47602 +               if (TOKEN_Q_DEPTH <= 6) {
47603 +                       cnt = TOKEN_Q_DEPTH - 1;
47604 +               } else if (TOKEN_Q_DEPTH <= 14) {
47605 +                       cnt = TOKEN_Q_DEPTH - 7;
47606 +               } else if (TOKEN_Q_DEPTH <= 22) {
47607 +                       cnt = TOKEN_Q_DEPTH - 15;
47608 +               } else {
47609 +                       cnt = TOKEN_Q_DEPTH - 23;
47610 +               }
47611 +               epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
47612 +       } else {
47613 +               if (ndx <= 5) {
47614 +                       epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
47615 +               } else if (ndx <= 13) {
47616 +                       ndx -= 6;
47617 +                       epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
47618 +               } else if (ndx <= 21) {
47619 +                       ndx -= 14;
47620 +                       epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
47621 +               } else if (ndx <= 29) {
47622 +                       ndx -= 22;
47623 +                       epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
47624 +               }
47625 +       }
47626 +       //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
47627 +       return epnum;
47628 +}
47629 +
47630 +/**
47631 + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
47632 + * The active request is checked for the next packet to be loaded into
47633 + * the non-periodic Tx FIFO.
47634 + */
47635 +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
47636 +{
47637 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47638 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
47639 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47640 +       gnptxsts_data_t txstatus = {.d32 = 0 };
47641 +       gintsts_data_t gintsts;
47642 +
47643 +       int epnum = 0;
47644 +       dwc_otg_pcd_ep_t *ep = 0;
47645 +       uint32_t len = 0;
47646 +       int dwords;
47647 +
47648 +       /* Get the epnum from the IN Token Learning Queue. */
47649 +       epnum = get_ep_of_last_in_token(core_if);
47650 +       ep = get_in_ep(pcd, epnum);
47651 +
47652 +       DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
47653 +
47654 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47655 +
47656 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47657 +       if (len > ep->dwc_ep.maxpacket) {
47658 +               len = ep->dwc_ep.maxpacket;
47659 +       }
47660 +       dwords = (len + 3) / 4;
47661 +
47662 +       /* While there is space in the queue and space in the FIFO and
47663 +        * More data to tranfer, Write packets to the Tx FIFO */
47664 +       txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47665 +       DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
47666 +
47667 +       while (txstatus.b.nptxqspcavail > 0 &&
47668 +              txstatus.b.nptxfspcavail > dwords &&
47669 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
47670 +               /* Write the FIFO */
47671 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47672 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47673 +
47674 +               if (len > ep->dwc_ep.maxpacket) {
47675 +                       len = ep->dwc_ep.maxpacket;
47676 +               }
47677 +
47678 +               dwords = (len + 3) / 4;
47679 +               txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
47680 +               DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
47681 +       }
47682 +
47683 +       DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
47684 +                   DWC_READ_REG32(&global_regs->gnptxsts));
47685 +
47686 +       /* Clear interrupt */
47687 +       gintsts.d32 = 0;
47688 +       gintsts.b.nptxfempty = 1;
47689 +       DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
47690 +
47691 +       return 1;
47692 +}
47693 +
47694 +/**
47695 + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
47696 + * The active request is checked for the next packet to be loaded into
47697 + * apropriate Tx FIFO.
47698 + */
47699 +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
47700 +{
47701 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47702 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47703 +       dwc_otg_dev_in_ep_regs_t *ep_regs;
47704 +       dtxfsts_data_t txstatus = {.d32 = 0 };
47705 +       dwc_otg_pcd_ep_t *ep = 0;
47706 +       uint32_t len = 0;
47707 +       int dwords;
47708 +
47709 +       ep = get_in_ep(pcd, epnum);
47710 +
47711 +       DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
47712 +
47713 +       ep_regs = core_if->dev_if->in_ep_regs[epnum];
47714 +
47715 +       len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47716 +
47717 +       if (len > ep->dwc_ep.maxpacket) {
47718 +               len = ep->dwc_ep.maxpacket;
47719 +       }
47720 +
47721 +       dwords = (len + 3) / 4;
47722 +
47723 +       /* While there is space in the queue and space in the FIFO and
47724 +        * More data to tranfer, Write packets to the Tx FIFO */
47725 +       txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47726 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
47727 +
47728 +       while (txstatus.b.txfspcavail > dwords &&
47729 +              ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
47730 +              ep->dwc_ep.xfer_len != 0) {
47731 +               /* Write the FIFO */
47732 +               dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
47733 +
47734 +               len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
47735 +               if (len > ep->dwc_ep.maxpacket) {
47736 +                       len = ep->dwc_ep.maxpacket;
47737 +               }
47738 +
47739 +               dwords = (len + 3) / 4;
47740 +               txstatus.d32 =
47741 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
47742 +               DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
47743 +                           txstatus.d32);
47744 +       }
47745 +
47746 +       DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
47747 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
47748 +
47749 +       return 1;
47750 +}
47751 +
47752 +/**
47753 + * This function is called when the Device is disconnected. It stops
47754 + * any active requests and informs the Gadget driver of the
47755 + * disconnect.
47756 + */
47757 +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
47758 +{
47759 +       int i, num_in_eps, num_out_eps;
47760 +       dwc_otg_pcd_ep_t *ep;
47761 +
47762 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47763 +
47764 +       DWC_SPINLOCK(pcd->lock);
47765 +
47766 +       num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
47767 +       num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
47768 +
47769 +       DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
47770 +       /* don't disconnect drivers more than once */
47771 +       if (pcd->ep0state == EP0_DISCONNECT) {
47772 +               DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
47773 +               DWC_SPINUNLOCK(pcd->lock);
47774 +               return;
47775 +       }
47776 +       pcd->ep0state = EP0_DISCONNECT;
47777 +
47778 +       /* Reset the OTG state. */
47779 +       dwc_otg_pcd_update_otg(pcd, 1);
47780 +
47781 +       /* Disable the NP Tx Fifo Empty Interrupt. */
47782 +       intr_mask.b.nptxfempty = 1;
47783 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47784 +                        intr_mask.d32, 0);
47785 +
47786 +       /* Flush the FIFOs */
47787 +       /**@todo NGS Flush Periodic FIFOs */
47788 +       dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
47789 +       dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
47790 +
47791 +       /* prevent new request submissions, kill any outstanding requests  */
47792 +       ep = &pcd->ep0;
47793 +       dwc_otg_request_nuke(ep);
47794 +       /* prevent new request submissions, kill any outstanding requests  */
47795 +       for (i = 0; i < num_in_eps; i++) {
47796 +               dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
47797 +               dwc_otg_request_nuke(ep);
47798 +       }
47799 +       /* prevent new request submissions, kill any outstanding requests  */
47800 +       for (i = 0; i < num_out_eps; i++) {
47801 +               dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
47802 +               dwc_otg_request_nuke(ep);
47803 +       }
47804 +
47805 +       /* report disconnect; the driver is already quiesced */
47806 +       if (pcd->fops->disconnect) {
47807 +               DWC_SPINUNLOCK(pcd->lock);
47808 +               pcd->fops->disconnect(pcd);
47809 +               DWC_SPINLOCK(pcd->lock);
47810 +       }
47811 +       DWC_SPINUNLOCK(pcd->lock);
47812 +}
47813 +
47814 +/**
47815 + * This interrupt indicates that ...
47816 + */
47817 +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
47818 +{
47819 +       gintmsk_data_t intr_mask = {.d32 = 0 };
47820 +       gintsts_data_t gintsts;
47821 +
47822 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
47823 +       intr_mask.b.i2cintr = 1;
47824 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
47825 +                        intr_mask.d32, 0);
47826 +
47827 +       /* Clear interrupt */
47828 +       gintsts.d32 = 0;
47829 +       gintsts.b.i2cintr = 1;
47830 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
47831 +                       gintsts.d32);
47832 +       return 1;
47833 +}
47834 +
47835 +/**
47836 + * This interrupt indicates that ...
47837 + */
47838 +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
47839 +{
47840 +       gintsts_data_t gintsts;
47841 +#if defined(VERBOSE)
47842 +       DWC_PRINTF("Early Suspend Detected\n");
47843 +#endif
47844 +
47845 +       /* Clear interrupt */
47846 +       gintsts.d32 = 0;
47847 +       gintsts.b.erlysuspend = 1;
47848 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
47849 +                       gintsts.d32);
47850 +       return 1;
47851 +}
47852 +
47853 +/**
47854 + * This function configures EPO to receive SETUP packets.
47855 + *
47856 + * @todo NGS: Update the comments from the HW FS.
47857 + *
47858 + *     -# Program the following fields in the endpoint specific registers
47859 + *     for Control OUT EP 0, in order to receive a setup packet
47860 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
47861 + *       setup packets)
47862 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
47863 + *       to back setup packets)
47864 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
47865 + *               store any setup packets received
47866 + *
47867 + * @param core_if Programming view of DWC_otg controller.
47868 + * @param pcd    Programming view of the PCD.
47869 + */
47870 +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
47871 +                                dwc_otg_pcd_t * pcd)
47872 +{
47873 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47874 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
47875 +       dwc_otg_dev_dma_desc_t *dma_desc;
47876 +       depctl_data_t doepctl = {.d32 = 0 };
47877 +
47878 +#ifdef VERBOSE
47879 +       DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
47880 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
47881 +#endif
47882 +       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
47883 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
47884 +               if (doepctl.b.epena) {
47885 +                       return;
47886 +               }
47887 +       }
47888 +
47889 +       doeptsize0.b.supcnt = 3;
47890 +       doeptsize0.b.pktcnt = 1;
47891 +       doeptsize0.b.xfersize = 8 * 3;
47892 +
47893 +       if (core_if->dma_enable) {
47894 +               if (!core_if->dma_desc_enable) {
47895 +                       /** put here as for Hermes mode deptisz register should not be written */
47896 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
47897 +                                       doeptsize0.d32);
47898 +
47899 +                       /** @todo dma needs to handle multiple setup packets (up to 3) */
47900 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
47901 +                                       pcd->setup_pkt_dma_handle);
47902 +               } else {
47903 +                       dev_if->setup_desc_index =
47904 +                           (dev_if->setup_desc_index + 1) & 1;
47905 +                       dma_desc =
47906 +                           dev_if->setup_desc_addr[dev_if->setup_desc_index];
47907 +
47908 +                       /** DMA Descriptor Setup */
47909 +                       dma_desc->status.b.bs = BS_HOST_BUSY;
47910 +                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
47911 +                               dma_desc->status.b.sr = 0;
47912 +                               dma_desc->status.b.mtrf = 0;
47913 +                       }
47914 +                       dma_desc->status.b.l = 1;
47915 +                       dma_desc->status.b.ioc = 1;
47916 +                       dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
47917 +                       dma_desc->buf = pcd->setup_pkt_dma_handle;
47918 +                       dma_desc->status.b.sts = 0;
47919 +                       dma_desc->status.b.bs = BS_HOST_READY;
47920 +
47921 +                       /** DOEPDMA0 Register write */
47922 +                       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
47923 +                                       dev_if->dma_setup_desc_addr
47924 +                                       [dev_if->setup_desc_index]);
47925 +               }
47926 +
47927 +       } else {
47928 +               /** put here as for Hermes mode deptisz register should not be written */
47929 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
47930 +                               doeptsize0.d32);
47931 +       }
47932 +
47933 +       /** DOEPCTL0 Register write cnak will be set after setup interrupt */
47934 +       doepctl.d32 = 0;
47935 +       doepctl.b.epena = 1;
47936 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
47937 +       doepctl.b.cnak = 1;
47938 +       DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
47939 +       } else {
47940 +               DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
47941 +       }
47942 +
47943 +#ifdef VERBOSE
47944 +       DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
47945 +                   DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
47946 +       DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
47947 +                   DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
47948 +#endif
47949 +}
47950 +
47951 +/**
47952 + * This interrupt occurs when a USB Reset is detected. When the USB
47953 + * Reset Interrupt occurs the device state is set to DEFAULT and the
47954 + * EP0 state is set to IDLE.
47955 + *     -#      Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
47956 + *     -#      Unmask the following interrupt bits
47957 + *             - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
47958 + *     - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
47959 + *     - DOEPMSK.SETUP = 1
47960 + *     - DOEPMSK.XferCompl = 1
47961 + *     - DIEPMSK.XferCompl = 1
47962 + *     - DIEPMSK.TimeOut = 1
47963 + *     -# Program the following fields in the endpoint specific registers
47964 + *     for Control OUT EP 0, in order to receive a setup packet
47965 + *     - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
47966 + *       setup packets)
47967 + *     - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
47968 + *       to back setup packets)
47969 + *             - In DMA mode, DOEPDMA0 Register with a memory address to
47970 + *               store any setup packets received
47971 + * At this point, all the required initialization, except for enabling
47972 + * the control 0 OUT endpoint is done, for receiving SETUP packets.
47973 + */
47974 +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
47975 +{
47976 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
47977 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
47978 +       depctl_data_t doepctl = {.d32 = 0 };
47979 +       depctl_data_t diepctl = {.d32 = 0 };
47980 +       daint_data_t daintmsk = {.d32 = 0 };
47981 +       doepmsk_data_t doepmsk = {.d32 = 0 };
47982 +       diepmsk_data_t diepmsk = {.d32 = 0 };
47983 +       dcfg_data_t dcfg = {.d32 = 0 };
47984 +       grstctl_t resetctl = {.d32 = 0 };
47985 +       dctl_data_t dctl = {.d32 = 0 };
47986 +       int i = 0;
47987 +       gintsts_data_t gintsts;
47988 +       pcgcctl_data_t power = {.d32 = 0 };
47989 +
47990 +       power.d32 = DWC_READ_REG32(core_if->pcgcctl);
47991 +       if (power.b.stoppclk) {
47992 +               power.d32 = 0;
47993 +               power.b.stoppclk = 1;
47994 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
47995 +
47996 +               power.b.pwrclmp = 1;
47997 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
47998 +
47999 +               power.b.rstpdwnmodule = 1;
48000 +               DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
48001 +       }
48002 +
48003 +       core_if->lx_state = DWC_OTG_L0;
48004 +
48005 +       DWC_PRINTF("USB RESET\n");
48006 +#ifdef DWC_EN_ISOC
48007 +       for (i = 1; i < 16; ++i) {
48008 +               dwc_otg_pcd_ep_t *ep;
48009 +               dwc_ep_t *dwc_ep;
48010 +               ep = get_in_ep(pcd, i);
48011 +               if (ep != 0) {
48012 +                       dwc_ep = &ep->dwc_ep;
48013 +                       dwc_ep->next_frame = 0xffffffff;
48014 +               }
48015 +       }
48016 +#endif /* DWC_EN_ISOC */
48017 +
48018 +       /* reset the HNP settings */
48019 +       dwc_otg_pcd_update_otg(pcd, 1);
48020 +
48021 +       /* Clear the Remote Wakeup Signalling */
48022 +       dctl.b.rmtwkupsig = 1;
48023 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
48024 +
48025 +       /* Set NAK for all OUT EPs */
48026 +       doepctl.b.snak = 1;
48027 +       for (i = 0; i <= dev_if->num_out_eps; i++) {
48028 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
48029 +       }
48030 +
48031 +       /* Flush the NP Tx FIFO */
48032 +       dwc_otg_flush_tx_fifo(core_if, 0x10);
48033 +       /* Flush the Learning Queue */
48034 +       resetctl.b.intknqflsh = 1;
48035 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
48036 +
48037 +       if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
48038 +               core_if->start_predict = 0;
48039 +               for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
48040 +                       core_if->nextep_seq[i] = 0xff;  // 0xff - EP not active
48041 +               }
48042 +               core_if->nextep_seq[0] = 0;
48043 +               core_if->first_in_nextep_seq = 0;
48044 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
48045 +               diepctl.b.nextep = 0;
48046 +               DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
48047 +
48048 +               /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
48049 +               dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48050 +               dcfg.b.epmscnt = 2;
48051 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48052 +
48053 +               DWC_DEBUGPL(DBG_PCDV,
48054 +                           "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
48055 +                       __func__, core_if->first_in_nextep_seq);
48056 +               for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
48057 +                       DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
48058 +               }
48059 +       }
48060 +
48061 +       if (core_if->multiproc_int_enable) {
48062 +               daintmsk.b.inep0 = 1;
48063 +               daintmsk.b.outep0 = 1;
48064 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
48065 +                               daintmsk.d32);
48066 +
48067 +               doepmsk.b.setup = 1;
48068 +               doepmsk.b.xfercompl = 1;
48069 +               doepmsk.b.ahberr = 1;
48070 +               doepmsk.b.epdisabled = 1;
48071 +
48072 +               if ((core_if->dma_desc_enable) ||
48073 +                   (core_if->dma_enable
48074 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48075 +                       doepmsk.b.stsphsercvd = 1;
48076 +               }
48077 +               if (core_if->dma_desc_enable)
48078 +                       doepmsk.b.bna = 1;
48079 +/*
48080 +               doepmsk.b.babble = 1;
48081 +               doepmsk.b.nyet = 1;
48082 +
48083 +               if (core_if->dma_enable) {
48084 +                       doepmsk.b.nak = 1;
48085 +               }
48086 +*/
48087 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
48088 +                               doepmsk.d32);
48089 +
48090 +               diepmsk.b.xfercompl = 1;
48091 +               diepmsk.b.timeout = 1;
48092 +               diepmsk.b.epdisabled = 1;
48093 +               diepmsk.b.ahberr = 1;
48094 +               diepmsk.b.intknepmis = 1;
48095 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48096 +                       diepmsk.b.intknepmis = 0;
48097 +
48098 +/*             if (core_if->dma_desc_enable) {
48099 +                       diepmsk.b.bna = 1;
48100 +               }
48101 +*/
48102 +/*
48103 +               if (core_if->dma_enable) {
48104 +                       diepmsk.b.nak = 1;
48105 +               }
48106 +*/
48107 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
48108 +                               diepmsk.d32);
48109 +       } else {
48110 +               daintmsk.b.inep0 = 1;
48111 +               daintmsk.b.outep0 = 1;
48112 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
48113 +                               daintmsk.d32);
48114 +
48115 +               doepmsk.b.setup = 1;
48116 +               doepmsk.b.xfercompl = 1;
48117 +               doepmsk.b.ahberr = 1;
48118 +               doepmsk.b.epdisabled = 1;
48119 +
48120 +               if ((core_if->dma_desc_enable) ||
48121 +                   (core_if->dma_enable
48122 +                    && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
48123 +                       doepmsk.b.stsphsercvd = 1;
48124 +               }
48125 +               if (core_if->dma_desc_enable)
48126 +                       doepmsk.b.bna = 1;
48127 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
48128 +
48129 +               diepmsk.b.xfercompl = 1;
48130 +               diepmsk.b.timeout = 1;
48131 +               diepmsk.b.epdisabled = 1;
48132 +               diepmsk.b.ahberr = 1;
48133 +               if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
48134 +                       diepmsk.b.intknepmis = 0;
48135 +/*
48136 +               if (core_if->dma_desc_enable) {
48137 +                       diepmsk.b.bna = 1;
48138 +               }
48139 +*/
48140 +
48141 +               DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
48142 +       }
48143 +
48144 +       /* Reset Device Address */
48145 +       dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
48146 +       dcfg.b.devaddr = 0;
48147 +       DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
48148 +
48149 +       /* setup EP0 to receive SETUP packets */
48150 +       if (core_if->snpsid <= OTG_CORE_REV_2_94a)
48151 +               ep0_out_start(core_if, pcd);
48152 +
48153 +       /* Clear interrupt */
48154 +       gintsts.d32 = 0;
48155 +       gintsts.b.usbreset = 1;
48156 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48157 +
48158 +       return 1;
48159 +}
48160 +
48161 +/**
48162 + * Get the device speed from the device status register and convert it
48163 + * to USB speed constant.
48164 + *
48165 + * @param core_if Programming view of DWC_otg controller.
48166 + */
48167 +static int get_device_speed(dwc_otg_core_if_t * core_if)
48168 +{
48169 +       dsts_data_t dsts;
48170 +       int speed = 0;
48171 +       dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
48172 +
48173 +       switch (dsts.b.enumspd) {
48174 +       case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
48175 +               speed = USB_SPEED_HIGH;
48176 +               break;
48177 +       case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
48178 +       case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
48179 +               speed = USB_SPEED_FULL;
48180 +               break;
48181 +
48182 +       case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
48183 +               speed = USB_SPEED_LOW;
48184 +               break;
48185 +       }
48186 +
48187 +       return speed;
48188 +}
48189 +
48190 +/**
48191 + * Read the device status register and set the device speed in the
48192 + * data structure.
48193 + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
48194 + */
48195 +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
48196 +{
48197 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48198 +       gintsts_data_t gintsts;
48199 +       gusbcfg_data_t gusbcfg;
48200 +       dwc_otg_core_global_regs_t *global_regs =
48201 +           GET_CORE_IF(pcd)->core_global_regs;
48202 +       uint8_t utmi16b, utmi8b;
48203 +       int speed;
48204 +       DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
48205 +
48206 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
48207 +               utmi16b = 6;    //vahrama old value was 6;
48208 +               utmi8b = 9;
48209 +       } else {
48210 +               utmi16b = 4;
48211 +               utmi8b = 8;
48212 +       }
48213 +       dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
48214 +       if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
48215 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48216 +       }
48217 +
48218 +#ifdef DEBUG_EP0
48219 +       print_ep0_state(pcd);
48220 +#endif
48221 +
48222 +       if (pcd->ep0state == EP0_DISCONNECT) {
48223 +               pcd->ep0state = EP0_IDLE;
48224 +       } else if (pcd->ep0state == EP0_STALL) {
48225 +               pcd->ep0state = EP0_IDLE;
48226 +       }
48227 +
48228 +       pcd->ep0state = EP0_IDLE;
48229 +
48230 +       ep0->stopped = 0;
48231 +
48232 +       speed = get_device_speed(GET_CORE_IF(pcd));
48233 +       pcd->fops->connect(pcd, speed);
48234 +
48235 +       /* Set USB turnaround time based on device speed and PHY interface. */
48236 +       gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
48237 +       if (speed == USB_SPEED_HIGH) {
48238 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48239 +                   DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
48240 +                       /* ULPI interface */
48241 +                       gusbcfg.b.usbtrdtim = 9;
48242 +               }
48243 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48244 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
48245 +                       /* UTMI+ interface */
48246 +                       if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
48247 +                               gusbcfg.b.usbtrdtim = utmi8b;
48248 +                       } else if (GET_CORE_IF(pcd)->hwcfg4.
48249 +                                  b.utmi_phy_data_width == 1) {
48250 +                               gusbcfg.b.usbtrdtim = utmi16b;
48251 +                       } else if (GET_CORE_IF(pcd)->
48252 +                                  core_params->phy_utmi_width == 8) {
48253 +                               gusbcfg.b.usbtrdtim = utmi8b;
48254 +                       } else {
48255 +                               gusbcfg.b.usbtrdtim = utmi16b;
48256 +                       }
48257 +               }
48258 +               if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
48259 +                   DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
48260 +                       /* UTMI+  OR  ULPI interface */
48261 +                       if (gusbcfg.b.ulpi_utmi_sel == 1) {
48262 +                               /* ULPI interface */
48263 +                               gusbcfg.b.usbtrdtim = 9;
48264 +                       } else {
48265 +                               /* UTMI+ interface */
48266 +                               if (GET_CORE_IF(pcd)->
48267 +                                   core_params->phy_utmi_width == 16) {
48268 +                                       gusbcfg.b.usbtrdtim = utmi16b;
48269 +                               } else {
48270 +                                       gusbcfg.b.usbtrdtim = utmi8b;
48271 +                               }
48272 +                       }
48273 +               }
48274 +       } else {
48275 +               /* Full or low speed */
48276 +               gusbcfg.b.usbtrdtim = 9;
48277 +       }
48278 +       DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
48279 +
48280 +       /* Clear interrupt */
48281 +       gintsts.d32 = 0;
48282 +       gintsts.b.enumdone = 1;
48283 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48284 +                       gintsts.d32);
48285 +       return 1;
48286 +}
48287 +
48288 +/**
48289 + * This interrupt indicates that the ISO OUT Packet was dropped due to
48290 + * Rx FIFO full or Rx Status Queue Full.  If this interrupt occurs
48291 + * read all the data from the Rx FIFO.
48292 + */
48293 +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
48294 +{
48295 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48296 +       gintsts_data_t gintsts;
48297 +
48298 +       DWC_WARN("INTERRUPT Handler not implemented for %s\n",
48299 +                "ISOC Out Dropped");
48300 +
48301 +       intr_mask.b.isooutdrop = 1;
48302 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48303 +                        intr_mask.d32, 0);
48304 +
48305 +       /* Clear interrupt */
48306 +       gintsts.d32 = 0;
48307 +       gintsts.b.isooutdrop = 1;
48308 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48309 +                       gintsts.d32);
48310 +
48311 +       return 1;
48312 +}
48313 +
48314 +/**
48315 + * This interrupt indicates the end of the portion of the micro-frame
48316 + * for periodic transactions.  If there is a periodic transaction for
48317 + * the next frame, load the packets into the EP periodic Tx FIFO.
48318 + */
48319 +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
48320 +{
48321 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48322 +       gintsts_data_t gintsts;
48323 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
48324 +
48325 +       intr_mask.b.eopframe = 1;
48326 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
48327 +                        intr_mask.d32, 0);
48328 +
48329 +       /* Clear interrupt */
48330 +       gintsts.d32 = 0;
48331 +       gintsts.b.eopframe = 1;
48332 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
48333 +                       gintsts.d32);
48334 +
48335 +       return 1;
48336 +}
48337 +
48338 +/**
48339 + * This interrupt indicates that EP of the packet on the top of the
48340 + * non-periodic Tx FIFO does not match EP of the IN Token received.
48341 + *
48342 + * The "Device IN Token Queue" Registers are read to determine the
48343 + * order the IN Tokens have been received. The non-periodic Tx FIFO
48344 + * is flushed, so it can be reloaded in the order seen in the IN Token
48345 + * Queue.
48346 + */
48347 +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
48348 +{
48349 +       gintsts_data_t gintsts;
48350 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48351 +       dctl_data_t dctl;
48352 +       gintmsk_data_t intr_mask = {.d32 = 0 };
48353 +
48354 +       if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
48355 +               core_if->start_predict = 1;
48356 +
48357 +               DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48358 +
48359 +               gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
48360 +               if (!gintsts.b.ginnakeff) {
48361 +                       /* Disable EP Mismatch interrupt */
48362 +                       intr_mask.d32 = 0;
48363 +                       intr_mask.b.epmismatch = 1;
48364 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
48365 +                       /* Enable the Global IN NAK Effective Interrupt */
48366 +                       intr_mask.d32 = 0;
48367 +                       intr_mask.b.ginnakeff = 1;
48368 +                       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
48369 +                       /* Set the global non-periodic IN NAK handshake */
48370 +                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48371 +                       dctl.b.sgnpinnak = 1;
48372 +                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48373 +               } else {
48374 +                       DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
48375 +               }
48376 +               /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
48377 +                * handler after Global IN NAK Effective interrupt will be asserted */
48378 +       }
48379 +       /* Clear interrupt */
48380 +       gintsts.d32 = 0;
48381 +       gintsts.b.epmismatch = 1;
48382 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48383 +
48384 +       return 1;
48385 +}
48386 +
48387 +/**
48388 + * This interrupt is valid only in DMA mode. This interrupt indicates that the
48389 + * core has stopped fetching data for IN endpoints due to the unavailability of
48390 + * TxFIFO space or Request Queue space. This interrupt is used by the
48391 + * application for an endpoint mismatch algorithm.
48392 + *
48393 + * @param pcd The PCD
48394 + */
48395 +int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
48396 +{
48397 +       gintsts_data_t gintsts;
48398 +       gintmsk_data_t gintmsk_data;
48399 +       dctl_data_t dctl;
48400 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48401 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
48402 +
48403 +       /* Clear the global non-periodic IN NAK handshake */
48404 +       dctl.d32 = 0;
48405 +       dctl.b.cgnpinnak = 1;
48406 +       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
48407 +
48408 +       /* Mask GINTSTS.FETSUSP interrupt */
48409 +       gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
48410 +       gintmsk_data.b.fetsusp = 0;
48411 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
48412 +
48413 +       /* Clear interrupt */
48414 +       gintsts.d32 = 0;
48415 +       gintsts.b.fetsusp = 1;
48416 +       DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
48417 +
48418 +       return 1;
48419 +}
48420 +/**
48421 + * This funcion stalls EP0.
48422 + */
48423 +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
48424 +{
48425 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48426 +       usb_device_request_t *ctrl = &pcd->setup_pkt->req;
48427 +       DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
48428 +                ctrl->bmRequestType, ctrl->bRequest, err_val);
48429 +
48430 +       ep0->dwc_ep.is_in = 1;
48431 +       dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
48432 +       pcd->ep0.stopped = 1;
48433 +       pcd->ep0state = EP0_IDLE;
48434 +       ep0_out_start(GET_CORE_IF(pcd), pcd);
48435 +}
48436 +
48437 +/**
48438 + * This functions delegates the setup command to the gadget driver.
48439 + */
48440 +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
48441 +                                  usb_device_request_t * ctrl)
48442 +{
48443 +       int ret = 0;
48444 +       DWC_SPINUNLOCK(pcd->lock);
48445 +       ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
48446 +       DWC_SPINLOCK(pcd->lock);
48447 +       if (ret < 0) {
48448 +               ep0_do_stall(pcd, ret);
48449 +       }
48450 +
48451 +       /** @todo This is a g_file_storage gadget driver specific
48452 +        * workaround: a DELAYED_STATUS result from the fsg_setup
48453 +        * routine will result in the gadget queueing a EP0 IN status
48454 +        * phase for a two-stage control transfer. Exactly the same as
48455 +        * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
48456 +        * specific request.  Need a generic way to know when the gadget
48457 +        * driver will queue the status phase. Can we assume when we
48458 +        * call the gadget driver setup() function that it will always
48459 +        * queue and require the following flag? Need to look into
48460 +        * this.
48461 +        */
48462 +
48463 +       if (ret == 256 + 999) {
48464 +               pcd->request_config = 1;
48465 +       }
48466 +}
48467 +
48468 +#ifdef DWC_UTE_CFI
48469 +/**
48470 + * This functions delegates the CFI setup commands to the gadget driver.
48471 + * This function will return a negative value to indicate a failure.
48472 + */
48473 +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
48474 +                                  struct cfi_usb_ctrlrequest *ctrl_req)
48475 +{
48476 +       int ret = 0;
48477 +
48478 +       if (pcd->fops && pcd->fops->cfi_setup) {
48479 +               DWC_SPINUNLOCK(pcd->lock);
48480 +               ret = pcd->fops->cfi_setup(pcd, ctrl_req);
48481 +               DWC_SPINLOCK(pcd->lock);
48482 +               if (ret < 0) {
48483 +                       ep0_do_stall(pcd, ret);
48484 +                       return ret;
48485 +               }
48486 +       }
48487 +
48488 +       return ret;
48489 +}
48490 +#endif
48491 +
48492 +/**
48493 + * This function starts the Zero-Length Packet for the IN status phase
48494 + * of a 2 stage control transfer.
48495 + */
48496 +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
48497 +{
48498 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48499 +       if (pcd->ep0state == EP0_STALL) {
48500 +               return;
48501 +       }
48502 +
48503 +       pcd->ep0state = EP0_IN_STATUS_PHASE;
48504 +
48505 +       /* Prepare for more SETUP Packets */
48506 +       DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
48507 +       if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
48508 +           && (pcd->core_if->dma_desc_enable)
48509 +           && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
48510 +               DWC_DEBUGPL(DBG_PCDV,
48511 +                           "Data terminated wait next packet in out_desc_addr\n");
48512 +               pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
48513 +               pcd->data_terminated = 1;
48514 +       }
48515 +       ep0->dwc_ep.xfer_len = 0;
48516 +       ep0->dwc_ep.xfer_count = 0;
48517 +       ep0->dwc_ep.is_in = 1;
48518 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48519 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48520 +
48521 +       /* Prepare for more SETUP Packets */
48522 +       //ep0_out_start(GET_CORE_IF(pcd), pcd);
48523 +}
48524 +
48525 +/**
48526 + * This function starts the Zero-Length Packet for the OUT status phase
48527 + * of a 2 stage control transfer.
48528 + */
48529 +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
48530 +{
48531 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48532 +       if (pcd->ep0state == EP0_STALL) {
48533 +               DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
48534 +               return;
48535 +       }
48536 +       pcd->ep0state = EP0_OUT_STATUS_PHASE;
48537 +
48538 +       DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
48539 +       ep0->dwc_ep.xfer_len = 0;
48540 +       ep0->dwc_ep.xfer_count = 0;
48541 +       ep0->dwc_ep.is_in = 0;
48542 +       ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
48543 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48544 +
48545 +       /* Prepare for more SETUP Packets */
48546 +       if (GET_CORE_IF(pcd)->dma_enable == 0) {
48547 +               ep0_out_start(GET_CORE_IF(pcd), pcd);
48548 +       }
48549 +}
48550 +
48551 +/**
48552 + * Clear the EP halt (STALL) and if pending requests start the
48553 + * transfer.
48554 + */
48555 +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
48556 +{
48557 +       if (ep->dwc_ep.stall_clear_flag == 0)
48558 +               dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
48559 +
48560 +       /* Reactive the EP */
48561 +       dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
48562 +       if (ep->stopped) {
48563 +               ep->stopped = 0;
48564 +               /* If there is a request in the EP queue start it */
48565 +
48566 +               /** @todo FIXME: this causes an EP mismatch in DMA mode.
48567 +                * epmismatch not yet implemented. */
48568 +
48569 +               /*
48570 +                * Above fixme is solved by implmenting a tasklet to call the
48571 +                * start_next_request(), outside of interrupt context at some
48572 +                * time after the current time, after a clear-halt setup packet.
48573 +                * Still need to implement ep mismatch in the future if a gadget
48574 +                * ever uses more than one endpoint at once
48575 +                */
48576 +               ep->queue_sof = 1;
48577 +               DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
48578 +       }
48579 +       /* Start Control Status Phase */
48580 +       do_setup_in_status_phase(pcd);
48581 +}
48582 +
48583 +/**
48584 + * This function is called when the SET_FEATURE TEST_MODE Setup packet
48585 + * is sent from the host.  The Device Control register is written with
48586 + * the Test Mode bits set to the specified Test Mode.  This is done as
48587 + * a tasklet so that the "Status" phase of the control transfer
48588 + * completes before transmitting the TEST packets.
48589 + *
48590 + * @todo This has not been tested since the tasklet struct was put
48591 + * into the PCD struct!
48592 + *
48593 + */
48594 +void do_test_mode(void *data)
48595 +{
48596 +       dctl_data_t dctl;
48597 +       dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
48598 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48599 +       int test_mode = pcd->test_mode;
48600 +
48601 +//        DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
48602 +
48603 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
48604 +       switch (test_mode) {
48605 +       case 1:         // TEST_J
48606 +               dctl.b.tstctl = 1;
48607 +               break;
48608 +
48609 +       case 2:         // TEST_K
48610 +               dctl.b.tstctl = 2;
48611 +               break;
48612 +
48613 +       case 3:         // TEST_SE0_NAK
48614 +               dctl.b.tstctl = 3;
48615 +               break;
48616 +
48617 +       case 4:         // TEST_PACKET
48618 +               dctl.b.tstctl = 4;
48619 +               break;
48620 +
48621 +       case 5:         // TEST_FORCE_ENABLE
48622 +               dctl.b.tstctl = 5;
48623 +               break;
48624 +       }
48625 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
48626 +}
48627 +
48628 +/**
48629 + * This function process the GET_STATUS Setup Commands.
48630 + */
48631 +static inline void do_get_status(dwc_otg_pcd_t * pcd)
48632 +{
48633 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48634 +       dwc_otg_pcd_ep_t *ep;
48635 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48636 +       uint16_t *status = pcd->status_buf;
48637 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48638 +
48639 +#ifdef DEBUG_EP0
48640 +       DWC_DEBUGPL(DBG_PCD,
48641 +                   "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
48642 +                   ctrl.bmRequestType, ctrl.bRequest,
48643 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48644 +                   UGETW(ctrl.wLength));
48645 +#endif
48646 +
48647 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48648 +       case UT_DEVICE:
48649 +               if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
48650 +                       DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
48651 +                       DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
48652 +                       DWC_PRINTF("OTG CAP - %d, %d\n",
48653 +                                  core_if->core_params->otg_cap,
48654 +                                               DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
48655 +                       if (core_if->otg_ver == 1
48656 +                           && core_if->core_params->otg_cap ==
48657 +                           DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48658 +                               uint8_t *otgsts = (uint8_t*)pcd->status_buf;
48659 +                               *otgsts = (core_if->otg_sts & 0x1);
48660 +                               pcd->ep0_pending = 1;
48661 +                               ep0->dwc_ep.start_xfer_buff =
48662 +                                   (uint8_t *) otgsts;
48663 +                               ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
48664 +                               ep0->dwc_ep.dma_addr =
48665 +                                   pcd->status_buf_dma_handle;
48666 +                               ep0->dwc_ep.xfer_len = 1;
48667 +                               ep0->dwc_ep.xfer_count = 0;
48668 +                               ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48669 +                               dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
48670 +                                                          &ep0->dwc_ep);
48671 +                               return;
48672 +                       } else {
48673 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48674 +                               return;
48675 +                       }
48676 +                       break;
48677 +               } else {
48678 +                       *status = 0x1;  /* Self powered */
48679 +                       *status |= pcd->remote_wakeup_enable << 1;
48680 +                       break;
48681 +               }
48682 +       case UT_INTERFACE:
48683 +               *status = 0;
48684 +               break;
48685 +
48686 +       case UT_ENDPOINT:
48687 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48688 +               if (ep == 0 || UGETW(ctrl.wLength) > 2) {
48689 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48690 +                       return;
48691 +               }
48692 +               /** @todo check for EP stall */
48693 +               *status = ep->stopped;
48694 +               break;
48695 +       }
48696 +       pcd->ep0_pending = 1;
48697 +       ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
48698 +       ep0->dwc_ep.xfer_buff = (uint8_t *) status;
48699 +       ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
48700 +       ep0->dwc_ep.xfer_len = 2;
48701 +       ep0->dwc_ep.xfer_count = 0;
48702 +       ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
48703 +       dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
48704 +}
48705 +
48706 +/**
48707 + * This function process the SET_FEATURE Setup Commands.
48708 + */
48709 +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
48710 +{
48711 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48712 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
48713 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48714 +       dwc_otg_pcd_ep_t *ep = 0;
48715 +       int32_t otg_cap_param = core_if->core_params->otg_cap;
48716 +       gotgctl_data_t gotgctl = {.d32 = 0 };
48717 +
48718 +       DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48719 +                   ctrl.bmRequestType, ctrl.bRequest,
48720 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48721 +                   UGETW(ctrl.wLength));
48722 +       DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
48723 +
48724 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48725 +       case UT_DEVICE:
48726 +               switch (UGETW(ctrl.wValue)) {
48727 +               case UF_DEVICE_REMOTE_WAKEUP:
48728 +                       pcd->remote_wakeup_enable = 1;
48729 +                       break;
48730 +
48731 +               case UF_TEST_MODE:
48732 +                       /* Setup the Test Mode tasklet to do the Test
48733 +                        * Packet generation after the SETUP Status
48734 +                        * phase has completed. */
48735 +
48736 +                       /** @todo This has not been tested since the
48737 +                        * tasklet struct was put into the PCD
48738 +                        * struct! */
48739 +                       pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
48740 +                       DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
48741 +                       break;
48742 +
48743 +               case UF_DEVICE_B_HNP_ENABLE:
48744 +                       DWC_DEBUGPL(DBG_PCDV,
48745 +                                   "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
48746 +
48747 +                       /* dev may initiate HNP */
48748 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48749 +                               pcd->b_hnp_enable = 1;
48750 +                               dwc_otg_pcd_update_otg(pcd, 0);
48751 +                               DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
48752 +                               /**@todo Is the gotgctl.devhnpen cleared
48753 +                                * by a USB Reset? */
48754 +                               gotgctl.b.devhnpen = 1;
48755 +                               gotgctl.b.hnpreq = 1;
48756 +                               DWC_WRITE_REG32(&global_regs->gotgctl,
48757 +                                               gotgctl.d32);
48758 +                       } else {
48759 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48760 +                               return;
48761 +                       }
48762 +                       break;
48763 +
48764 +               case UF_DEVICE_A_HNP_SUPPORT:
48765 +                       /* RH port supports HNP */
48766 +                       DWC_DEBUGPL(DBG_PCDV,
48767 +                                   "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
48768 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48769 +                               pcd->a_hnp_support = 1;
48770 +                               dwc_otg_pcd_update_otg(pcd, 0);
48771 +                       } else {
48772 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48773 +                               return;
48774 +                       }
48775 +                       break;
48776 +
48777 +               case UF_DEVICE_A_ALT_HNP_SUPPORT:
48778 +                       /* other RH port does */
48779 +                       DWC_DEBUGPL(DBG_PCDV,
48780 +                                   "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
48781 +                       if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
48782 +                               pcd->a_alt_hnp_support = 1;
48783 +                               dwc_otg_pcd_update_otg(pcd, 0);
48784 +                       } else {
48785 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48786 +                               return;
48787 +                       }
48788 +                       break;
48789 +
48790 +               default:
48791 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48792 +                       return;
48793 +
48794 +               }
48795 +               do_setup_in_status_phase(pcd);
48796 +               break;
48797 +
48798 +       case UT_INTERFACE:
48799 +               do_gadget_setup(pcd, &ctrl);
48800 +               break;
48801 +
48802 +       case UT_ENDPOINT:
48803 +               if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
48804 +                       ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48805 +                       if (ep == 0) {
48806 +                               ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48807 +                               return;
48808 +                       }
48809 +                       ep->stopped = 1;
48810 +                       dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
48811 +               }
48812 +               do_setup_in_status_phase(pcd);
48813 +               break;
48814 +       }
48815 +}
48816 +
48817 +/**
48818 + * This function process the CLEAR_FEATURE Setup Commands.
48819 + */
48820 +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
48821 +{
48822 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48823 +       dwc_otg_pcd_ep_t *ep = 0;
48824 +
48825 +       DWC_DEBUGPL(DBG_PCD,
48826 +                   "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
48827 +                   ctrl.bmRequestType, ctrl.bRequest,
48828 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48829 +                   UGETW(ctrl.wLength));
48830 +
48831 +       switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
48832 +       case UT_DEVICE:
48833 +               switch (UGETW(ctrl.wValue)) {
48834 +               case UF_DEVICE_REMOTE_WAKEUP:
48835 +                       pcd->remote_wakeup_enable = 0;
48836 +                       break;
48837 +
48838 +               case UF_TEST_MODE:
48839 +                       /** @todo Add CLEAR_FEATURE for TEST modes. */
48840 +                       break;
48841 +
48842 +               default:
48843 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48844 +                       return;
48845 +               }
48846 +               do_setup_in_status_phase(pcd);
48847 +               break;
48848 +
48849 +       case UT_ENDPOINT:
48850 +               ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
48851 +               if (ep == 0) {
48852 +                       ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
48853 +                       return;
48854 +               }
48855 +
48856 +               pcd_clear_halt(pcd, ep);
48857 +
48858 +               break;
48859 +       }
48860 +}
48861 +
48862 +/**
48863 + * This function process the SET_ADDRESS Setup Commands.
48864 + */
48865 +static inline void do_set_address(dwc_otg_pcd_t * pcd)
48866 +{
48867 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
48868 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48869 +
48870 +       if (ctrl.bmRequestType == UT_DEVICE) {
48871 +               dcfg_data_t dcfg = {.d32 = 0 };
48872 +
48873 +#ifdef DEBUG_EP0
48874 +//                      DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
48875 +#endif
48876 +               dcfg.b.devaddr = UGETW(ctrl.wValue);
48877 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
48878 +               do_setup_in_status_phase(pcd);
48879 +       }
48880 +}
48881 +
48882 +/**
48883 + *     This function processes SETUP commands. In Linux, the USB Command
48884 + *     processing is done in two places - the first being the PCD and the
48885 + *     second in the Gadget Driver (for example, the File-Backed Storage
48886 + *     Gadget Driver).
48887 + *
48888 + * <table>
48889 + * <tr><td>Command     </td><td>Driver </td><td>Description</td></tr>
48890 + *
48891 + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
48892 + * defined in chapter 9 of the USB 2.0 Specification chapter 9
48893 + * </td></tr>
48894 + *
48895 + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
48896 + * requests are the ENDPOINT_HALT feature is procesed, all others the
48897 + * interface requests are ignored.</td></tr>
48898 + *
48899 + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
48900 + * requests are processed by the PCD.  Interface requests are passed
48901 + * to the Gadget Driver.</td></tr>
48902 + *
48903 + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
48904 + * with device address received </td></tr>
48905 + *
48906 + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
48907 + * requested descriptor</td></tr>
48908 + *
48909 + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
48910 + * not implemented by any of the existing Gadget Drivers.</td></tr>
48911 + *
48912 + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
48913 + * all EPs and enable EPs for new configuration.</td></tr>
48914 + *
48915 + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
48916 + * the current configuration</td></tr>
48917 + *
48918 + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
48919 + * EPs and enable EPs for new configuration.</td></tr>
48920 + *
48921 + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
48922 + * current interface.</td></tr>
48923 + *
48924 + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
48925 + * message.</td></tr>
48926 + * </table>
48927 + *
48928 + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
48929 + * processed by pcd_setup. Calling the Function Driver's setup function from
48930 + * pcd_setup processes the gadget SETUP commands.
48931 + */
48932 +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
48933 +{
48934 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
48935 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
48936 +       usb_device_request_t ctrl = pcd->setup_pkt->req;
48937 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
48938 +
48939 +       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
48940 +
48941 +#ifdef DWC_UTE_CFI
48942 +       int retval = 0;
48943 +       struct cfi_usb_ctrlrequest cfi_req;
48944 +#endif
48945 +
48946 +       doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
48947 +
48948 +       /** In BDMA more then 1 setup packet is not supported till 3.00a */
48949 +       if (core_if->dma_enable && core_if->dma_desc_enable == 0
48950 +           && (doeptsize0.b.supcnt < 2)
48951 +           && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
48952 +               DWC_ERROR
48953 +                   ("\n\n-----------    CANNOT handle > 1 setup packet in DMA mode\n\n");
48954 +       }
48955 +       if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
48956 +           && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
48957 +               ctrl =
48958 +                   (pcd->setup_pkt +
48959 +                    (3 - doeptsize0.b.supcnt - 1 +
48960 +                     ep0->dwc_ep.stp_rollover))->req;
48961 +       }
48962 +#ifdef DEBUG_EP0
48963 +       DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
48964 +                   ctrl.bmRequestType, ctrl.bRequest,
48965 +                   UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
48966 +                   UGETW(ctrl.wLength));
48967 +#endif
48968 +
48969 +       /* Clean up the request queue */
48970 +       dwc_otg_request_nuke(ep0);
48971 +       ep0->stopped = 0;
48972 +
48973 +       if (ctrl.bmRequestType & UE_DIR_IN) {
48974 +               ep0->dwc_ep.is_in = 1;
48975 +               pcd->ep0state = EP0_IN_DATA_PHASE;
48976 +       } else {
48977 +               ep0->dwc_ep.is_in = 0;
48978 +               pcd->ep0state = EP0_OUT_DATA_PHASE;
48979 +       }
48980 +
48981 +       if (UGETW(ctrl.wLength) == 0) {
48982 +               ep0->dwc_ep.is_in = 1;
48983 +               pcd->ep0state = EP0_IN_STATUS_PHASE;
48984 +       }
48985 +
48986 +       if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
48987 +
48988 +#ifdef DWC_UTE_CFI
48989 +               DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
48990 +
48991 +               //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",
48992 +                               ctrl.bRequestType, ctrl.bRequest);
48993 +               if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
48994 +                       if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
48995 +                               retval = cfi_setup(pcd, &cfi_req);
48996 +                               if (retval < 0) {
48997 +                                       ep0_do_stall(pcd, retval);
48998 +                                       pcd->ep0_pending = 0;
48999 +                                       return;
49000 +                               }
49001 +
49002 +                               /* if need gadget setup then call it and check the retval */
49003 +                               if (pcd->cfi->need_gadget_att) {
49004 +                                       retval =
49005 +                                           cfi_gadget_setup(pcd,
49006 +                                                            &pcd->
49007 +                                                            cfi->ctrl_req);
49008 +                                       if (retval < 0) {
49009 +                                               pcd->ep0_pending = 0;
49010 +                                               return;
49011 +                                       }
49012 +                               }
49013 +
49014 +                               if (pcd->cfi->need_status_in_complete) {
49015 +                                       do_setup_in_status_phase(pcd);
49016 +                               }
49017 +                               return;
49018 +                       }
49019 +               }
49020 +#endif
49021 +
49022 +               /* handle non-standard (class/vendor) requests in the gadget driver */
49023 +               do_gadget_setup(pcd, &ctrl);
49024 +               return;
49025 +       }
49026 +
49027 +       /** @todo NGS: Handle bad setup packet? */
49028 +
49029 +///////////////////////////////////////////
49030 +//// --- Standard Request handling --- ////
49031 +
49032 +       switch (ctrl.bRequest) {
49033 +       case UR_GET_STATUS:
49034 +               do_get_status(pcd);
49035 +               break;
49036 +
49037 +       case UR_CLEAR_FEATURE:
49038 +               do_clear_feature(pcd);
49039 +               break;
49040 +
49041 +       case UR_SET_FEATURE:
49042 +               do_set_feature(pcd);
49043 +               break;
49044 +
49045 +       case UR_SET_ADDRESS:
49046 +               do_set_address(pcd);
49047 +               break;
49048 +
49049 +       case UR_SET_INTERFACE:
49050 +       case UR_SET_CONFIG:
49051 +//              _pcd->request_config = 1;       /* Configuration changed */
49052 +               do_gadget_setup(pcd, &ctrl);
49053 +               break;
49054 +
49055 +       case UR_SYNCH_FRAME:
49056 +               do_gadget_setup(pcd, &ctrl);
49057 +               break;
49058 +
49059 +       default:
49060 +               /* Call the Gadget Driver's setup functions */
49061 +               do_gadget_setup(pcd, &ctrl);
49062 +               break;
49063 +       }
49064 +}
49065 +
49066 +/**
49067 + * This function completes the ep0 control transfer.
49068 + */
49069 +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
49070 +{
49071 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49072 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49073 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49074 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49075 +#ifdef DEBUG_EP0
49076 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49077 +           dev_if->out_ep_regs[ep->dwc_ep.num];
49078 +#endif
49079 +       deptsiz0_data_t deptsiz;
49080 +       dev_dma_desc_sts_t desc_sts;
49081 +       dwc_otg_pcd_request_t *req;
49082 +       int is_last = 0;
49083 +       dwc_otg_pcd_t *pcd = ep->pcd;
49084 +
49085 +#ifdef DWC_UTE_CFI
49086 +       struct cfi_usb_ctrlrequest *ctrlreq;
49087 +       int retval = -DWC_E_NOT_SUPPORTED;
49088 +#endif
49089 +
49090 +        desc_sts.b.bytes = 0;
49091 +
49092 +       if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49093 +               if (ep->dwc_ep.is_in) {
49094 +#ifdef DEBUG_EP0
49095 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
49096 +#endif
49097 +                       do_setup_out_status_phase(pcd);
49098 +               } else {
49099 +#ifdef DEBUG_EP0
49100 +                       DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
49101 +#endif
49102 +
49103 +#ifdef DWC_UTE_CFI
49104 +                       ctrlreq = &pcd->cfi->ctrl_req;
49105 +
49106 +                       if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
49107 +                               if (ctrlreq->bRequest > 0xB0
49108 +                                   && ctrlreq->bRequest < 0xBF) {
49109 +
49110 +                                       /* Return if the PCD failed to handle the request */
49111 +                                       if ((retval =
49112 +                                            pcd->cfi->ops.
49113 +                                            ctrl_write_complete(pcd->cfi,
49114 +                                                                pcd)) < 0) {
49115 +                                               CFI_INFO
49116 +                                                   ("ERROR setting a new value in the PCD(%d)\n",
49117 +                                                    retval);
49118 +                                               ep0_do_stall(pcd, retval);
49119 +                                               pcd->ep0_pending = 0;
49120 +                                               return 0;
49121 +                                       }
49122 +
49123 +                                       /* If the gadget needs to be notified on the request */
49124 +                                       if (pcd->cfi->need_gadget_att == 1) {
49125 +                                               //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
49126 +                                               retval =
49127 +                                                   cfi_gadget_setup(pcd,
49128 +                                                                    &pcd->cfi->
49129 +                                                                    ctrl_req);
49130 +
49131 +                                               /* Return from the function if the gadget failed to process
49132 +                                                * the request properly - this should never happen !!!
49133 +                                                */
49134 +                                               if (retval < 0) {
49135 +                                                       CFI_INFO
49136 +                                                           ("ERROR setting a new value in the gadget(%d)\n",
49137 +                                                            retval);
49138 +                                                       pcd->ep0_pending = 0;
49139 +                                                       return 0;
49140 +                                               }
49141 +                                       }
49142 +
49143 +                                       CFI_INFO("%s: RETVAL=%d\n", __func__,
49144 +                                                retval);
49145 +                                       /* If we hit here then the PCD and the gadget has properly
49146 +                                        * handled the request - so send the ZLP IN to the host.
49147 +                                        */
49148 +                                       /* @todo: MAS - decide whether we need to start the setup
49149 +                                        * stage based on the need_setup value of the cfi object
49150 +                                        */
49151 +                                       do_setup_in_status_phase(pcd);
49152 +                                       pcd->ep0_pending = 0;
49153 +                                       return 1;
49154 +                               }
49155 +                       }
49156 +#endif
49157 +
49158 +                       do_setup_in_status_phase(pcd);
49159 +               }
49160 +               pcd->ep0_pending = 0;
49161 +               return 1;
49162 +       }
49163 +
49164 +       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49165 +               return 0;
49166 +       }
49167 +       req = DWC_CIRCLEQ_FIRST(&ep->queue);
49168 +
49169 +       if (pcd->ep0state == EP0_OUT_STATUS_PHASE
49170 +           || pcd->ep0state == EP0_IN_STATUS_PHASE) {
49171 +               is_last = 1;
49172 +       } else if (ep->dwc_ep.is_in) {
49173 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49174 +               if (core_if->dma_desc_enable != 0)
49175 +                       desc_sts = dev_if->in_desc_addr->status;
49176 +#ifdef DEBUG_EP0
49177 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d  xfersize=%d pktcnt=%d\n",
49178 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49179 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49180 +#endif
49181 +
49182 +               if (((core_if->dma_desc_enable == 0)
49183 +                    && (deptsiz.b.xfersize == 0))
49184 +                   || ((core_if->dma_desc_enable != 0)
49185 +                       && (desc_sts.b.bytes == 0))) {
49186 +                       req->actual = ep->dwc_ep.xfer_count;
49187 +                       /* Is a Zero Len Packet needed? */
49188 +                       if (req->sent_zlp) {
49189 +#ifdef DEBUG_EP0
49190 +                               DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
49191 +#endif
49192 +                               req->sent_zlp = 0;
49193 +                       }
49194 +                       do_setup_out_status_phase(pcd);
49195 +               }
49196 +       } else {
49197 +               /* ep0-OUT */
49198 +#ifdef DEBUG_EP0
49199 +               deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
49200 +               DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
49201 +                           ep->dwc_ep.num, ep->dwc_ep.xfer_len,
49202 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49203 +#endif
49204 +               req->actual = ep->dwc_ep.xfer_count;
49205 +
49206 +               /* Is a Zero Len Packet needed? */
49207 +               if (req->sent_zlp) {
49208 +#ifdef DEBUG_EP0
49209 +                       DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
49210 +#endif
49211 +                       req->sent_zlp = 0;
49212 +               }
49213 +               /* For older cores do setup in status phase in Slave/BDMA modes,
49214 +                * starting from 3.00 do that only in slave, and for DMA modes
49215 +                * just re-enable ep 0 OUT here*/
49216 +               if (core_if->dma_enable == 0
49217 +                   || (core_if->dma_desc_enable == 0
49218 +                       && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
49219 +                       do_setup_in_status_phase(pcd);
49220 +               } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
49221 +                       DWC_DEBUGPL(DBG_PCDV,
49222 +                                   "Enable out ep before in status phase\n");
49223 +                       ep0_out_start(core_if, pcd);
49224 +               }
49225 +       }
49226 +
49227 +       /* Complete the request */
49228 +       if (is_last) {
49229 +               dwc_otg_request_done(ep, req, 0);
49230 +               ep->dwc_ep.start_xfer_buff = 0;
49231 +               ep->dwc_ep.xfer_buff = 0;
49232 +               ep->dwc_ep.xfer_len = 0;
49233 +               return 1;
49234 +       }
49235 +       return 0;
49236 +}
49237 +
49238 +#ifdef DWC_UTE_CFI
49239 +/**
49240 + * This function calculates traverses all the CFI DMA descriptors and
49241 + * and accumulates the bytes that are left to be transfered.
49242 + *
49243 + * @return The total bytes left to transfered, or a negative value as failure
49244 + */
49245 +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
49246 +{
49247 +       int32_t ret = 0;
49248 +       int i;
49249 +       struct dwc_otg_dma_desc *ddesc = NULL;
49250 +       struct cfi_ep *cfiep;
49251 +
49252 +       /* See if the pcd_ep has its respective cfi_ep mapped */
49253 +       cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
49254 +       if (!cfiep) {
49255 +               CFI_INFO("%s: Failed to find ep\n", __func__);
49256 +               return -1;
49257 +       }
49258 +
49259 +       ddesc = ep->dwc_ep.descs;
49260 +
49261 +       for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
49262 +
49263 +#if defined(PRINT_CFI_DMA_DESCS)
49264 +               print_desc(ddesc, ep->ep.name, i);
49265 +#endif
49266 +               ret += ddesc->status.b.bytes;
49267 +               ddesc++;
49268 +       }
49269 +
49270 +       if (ret)
49271 +               CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
49272 +                        ret);
49273 +
49274 +       return ret;
49275 +}
49276 +#endif
49277 +
49278 +/**
49279 + * This function completes the request for the EP. If there are
49280 + * additional requests for the EP in the queue they will be started.
49281 + */
49282 +static void complete_ep(dwc_otg_pcd_ep_t * ep)
49283 +{
49284 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
49285 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
49286 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs =
49287 +           dev_if->in_ep_regs[ep->dwc_ep.num];
49288 +       deptsiz_data_t deptsiz;
49289 +       dev_dma_desc_sts_t desc_sts;
49290 +       dwc_otg_pcd_request_t *req = 0;
49291 +       dwc_otg_dev_dma_desc_t *dma_desc;
49292 +       uint32_t byte_count = 0;
49293 +       int is_last = 0;
49294 +       int i;
49295 +
49296 +       DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
49297 +                   (ep->dwc_ep.is_in ? "IN" : "OUT"));
49298 +
49299 +       /* Get any pending requests */
49300 +       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
49301 +               req = DWC_CIRCLEQ_FIRST(&ep->queue);
49302 +               if (!req) {
49303 +                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
49304 +                       return;
49305 +               }
49306 +       } else {
49307 +               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
49308 +               return;
49309 +       }
49310 +
49311 +       DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
49312 +
49313 +       if (ep->dwc_ep.is_in) {
49314 +               deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
49315 +
49316 +               if (core_if->dma_enable) {
49317 +                       if (core_if->dma_desc_enable == 0) {
49318 +                               if (deptsiz.b.xfersize == 0
49319 +                                   && deptsiz.b.pktcnt == 0) {
49320 +                                       byte_count =
49321 +                                           ep->dwc_ep.xfer_len -
49322 +                                           ep->dwc_ep.xfer_count;
49323 +
49324 +                                       ep->dwc_ep.xfer_buff += byte_count;
49325 +                                       ep->dwc_ep.dma_addr += byte_count;
49326 +                                       ep->dwc_ep.xfer_count += byte_count;
49327 +
49328 +                                       DWC_DEBUGPL(DBG_PCDV,
49329 +                                                   "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49330 +                                                   ep->dwc_ep.num,
49331 +                                                   (ep->dwc_ep.
49332 +                                                    is_in ? "IN" : "OUT"),
49333 +                                                   ep->dwc_ep.xfer_len,
49334 +                                                   deptsiz.b.xfersize,
49335 +                                                   deptsiz.b.pktcnt);
49336 +
49337 +                                       if (ep->dwc_ep.xfer_len <
49338 +                                           ep->dwc_ep.total_len) {
49339 +                                               dwc_otg_ep_start_transfer
49340 +                                                   (core_if, &ep->dwc_ep);
49341 +                                       } else if (ep->dwc_ep.sent_zlp) {
49342 +                                               /*
49343 +                                                * This fragment of code should initiate 0
49344 +                                                * length transfer in case if it is queued
49345 +                                                * a transfer with size divisible to EPs max
49346 +                                                * packet size and with usb_request zero field
49347 +                                                * is set, which means that after data is transfered,
49348 +                                                * it is also should be transfered
49349 +                                                * a 0 length packet at the end. For Slave and
49350 +                                                * Buffer DMA modes in this case SW has
49351 +                                                * to initiate 2 transfers one with transfer size,
49352 +                                                * and the second with 0 size. For Descriptor
49353 +                                                * DMA mode SW is able to initiate a transfer,
49354 +                                                * which will handle all the packets including
49355 +                                                * the last  0 length.
49356 +                                                */
49357 +                                               ep->dwc_ep.sent_zlp = 0;
49358 +                                               dwc_otg_ep_start_zl_transfer
49359 +                                                   (core_if, &ep->dwc_ep);
49360 +                                       } else {
49361 +                                               is_last = 1;
49362 +                                       }
49363 +                               } else {
49364 +                                       if (ep->dwc_ep.type ==
49365 +                                           DWC_OTG_EP_TYPE_ISOC) {
49366 +                                               req->actual = 0;
49367 +                                               dwc_otg_request_done(ep, req, 0);
49368 +
49369 +                                               ep->dwc_ep.start_xfer_buff = 0;
49370 +                                               ep->dwc_ep.xfer_buff = 0;
49371 +                                               ep->dwc_ep.xfer_len = 0;
49372 +
49373 +                                               /* If there is a request in the queue start it. */
49374 +                                               start_next_request(ep);
49375 +                                       } else
49376 +                                               DWC_WARN
49377 +                                               ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
49378 +                                               ep->dwc_ep.num,
49379 +                                               (ep->dwc_ep.is_in ? "IN" : "OUT"),
49380 +                                               deptsiz.b.xfersize,
49381 +                                               deptsiz.b.pktcnt);
49382 +                               }
49383 +                       } else {
49384 +                               dma_desc = ep->dwc_ep.desc_addr;
49385 +                               byte_count = 0;
49386 +                               ep->dwc_ep.sent_zlp = 0;
49387 +
49388 +#ifdef DWC_UTE_CFI
49389 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49390 +                                        ep->dwc_ep.buff_mode);
49391 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49392 +                                       int residue;
49393 +
49394 +                                       residue = cfi_calc_desc_residue(ep);
49395 +                                       if (residue < 0)
49396 +                                               return;
49397 +
49398 +                                       byte_count = residue;
49399 +                               } else {
49400 +#endif
49401 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49402 +                                            ++i) {
49403 +                                       desc_sts = dma_desc->status;
49404 +                                       byte_count += desc_sts.b.bytes;
49405 +                                       dma_desc++;
49406 +                               }
49407 +#ifdef DWC_UTE_CFI
49408 +                               }
49409 +#endif
49410 +                               if (byte_count == 0) {
49411 +                                       ep->dwc_ep.xfer_count =
49412 +                                           ep->dwc_ep.total_len;
49413 +                                       is_last = 1;
49414 +                               } else {
49415 +                                       DWC_WARN("Incomplete transfer\n");
49416 +                               }
49417 +                       }
49418 +               } else {
49419 +                       if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
49420 +                               DWC_DEBUGPL(DBG_PCDV,
49421 +                                           "%d-%s len=%d  xfersize=%d pktcnt=%d\n",
49422 +                                           ep->dwc_ep.num,
49423 +                                           ep->dwc_ep.is_in ? "IN" : "OUT",
49424 +                                           ep->dwc_ep.xfer_len,
49425 +                                           deptsiz.b.xfersize,
49426 +                                           deptsiz.b.pktcnt);
49427 +
49428 +                               /*      Check if the whole transfer was completed,
49429 +                                *      if no, setup transfer for next portion of data
49430 +                                */
49431 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49432 +                                       dwc_otg_ep_start_transfer(core_if,
49433 +                                                                 &ep->dwc_ep);
49434 +                               } else if (ep->dwc_ep.sent_zlp) {
49435 +                                       /*
49436 +                                        * This fragment of code should initiate 0
49437 +                                        * length trasfer in case if it is queued
49438 +                                        * a trasfer with size divisible to EPs max
49439 +                                        * packet size and with usb_request zero field
49440 +                                        * is set, which means that after data is transfered,
49441 +                                        * it is also should be transfered
49442 +                                        * a 0 length packet at the end. For Slave and
49443 +                                        * Buffer DMA modes in this case SW has
49444 +                                        * to initiate 2 transfers one with transfer size,
49445 +                                        * and the second with 0 size. For Desriptor
49446 +                                        * DMA mode SW is able to initiate a transfer,
49447 +                                        * which will handle all the packets including
49448 +                                        * the last  0 legth.
49449 +                                        */
49450 +                                       ep->dwc_ep.sent_zlp = 0;
49451 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49452 +                                                                    &ep->dwc_ep);
49453 +                               } else {
49454 +                                       is_last = 1;
49455 +                               }
49456 +                       } else {
49457 +                               DWC_WARN
49458 +                                   ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
49459 +                                    ep->dwc_ep.num,
49460 +                                    (ep->dwc_ep.is_in ? "IN" : "OUT"),
49461 +                                    deptsiz.b.xfersize, deptsiz.b.pktcnt);
49462 +                       }
49463 +               }
49464 +       } else {
49465 +               dwc_otg_dev_out_ep_regs_t *out_ep_regs =
49466 +                   dev_if->out_ep_regs[ep->dwc_ep.num];
49467 +               desc_sts.d32 = 0;
49468 +               if (core_if->dma_enable) {
49469 +                       if (core_if->dma_desc_enable) {
49470 +                               dma_desc = ep->dwc_ep.desc_addr;
49471 +                               byte_count = 0;
49472 +                               ep->dwc_ep.sent_zlp = 0;
49473 +
49474 +#ifdef DWC_UTE_CFI
49475 +                               CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
49476 +                                        ep->dwc_ep.buff_mode);
49477 +                               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49478 +                                       int residue;
49479 +                                       residue = cfi_calc_desc_residue(ep);
49480 +                                       if (residue < 0)
49481 +                                               return;
49482 +                                       byte_count = residue;
49483 +                               } else {
49484 +#endif
49485 +
49486 +                                       for (i = 0; i < ep->dwc_ep.desc_cnt;
49487 +                                            ++i) {
49488 +                                               desc_sts = dma_desc->status;
49489 +                                               byte_count += desc_sts.b.bytes;
49490 +                                               dma_desc++;
49491 +                                       }
49492 +
49493 +#ifdef DWC_UTE_CFI
49494 +                               }
49495 +#endif
49496 +                               /* Checking for interrupt Out transfers with not
49497 +                                * dword aligned mps sizes
49498 +                                */
49499 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
49500 +                                                       (ep->dwc_ep.maxpacket%4)) {
49501 +                                       ep->dwc_ep.xfer_count =
49502 +                                           ep->dwc_ep.total_len - byte_count;
49503 +                                       if ((ep->dwc_ep.xfer_len %
49504 +                                            ep->dwc_ep.maxpacket)
49505 +                                           && (ep->dwc_ep.xfer_len /
49506 +                                               ep->dwc_ep.maxpacket <
49507 +                                               MAX_DMA_DESC_CNT))
49508 +                                               ep->dwc_ep.xfer_len -=
49509 +                                                   (ep->dwc_ep.desc_cnt -
49510 +                                                    1) * ep->dwc_ep.maxpacket +
49511 +                                                   ep->dwc_ep.xfer_len %
49512 +                                                   ep->dwc_ep.maxpacket;
49513 +                                       else
49514 +                                               ep->dwc_ep.xfer_len -=
49515 +                                                   ep->dwc_ep.desc_cnt *
49516 +                                                   ep->dwc_ep.maxpacket;
49517 +                                       if (ep->dwc_ep.xfer_len > 0) {
49518 +                                               dwc_otg_ep_start_transfer
49519 +                                                   (core_if, &ep->dwc_ep);
49520 +                                       } else {
49521 +                                               is_last = 1;
49522 +                                       }
49523 +                               } else {
49524 +                                       ep->dwc_ep.xfer_count =
49525 +                                           ep->dwc_ep.total_len - byte_count +
49526 +                                           ((4 -
49527 +                                             (ep->dwc_ep.
49528 +                                              total_len & 0x3)) & 0x3);
49529 +                                       is_last = 1;
49530 +                               }
49531 +                       } else {
49532 +                               deptsiz.d32 = 0;
49533 +                               deptsiz.d32 =
49534 +                                   DWC_READ_REG32(&out_ep_regs->doeptsiz);
49535 +
49536 +                               byte_count = (ep->dwc_ep.xfer_len -
49537 +                                             ep->dwc_ep.xfer_count -
49538 +                                             deptsiz.b.xfersize);
49539 +                               ep->dwc_ep.xfer_buff += byte_count;
49540 +                               ep->dwc_ep.dma_addr += byte_count;
49541 +                               ep->dwc_ep.xfer_count += byte_count;
49542 +
49543 +                               /*      Check if the whole transfer was completed,
49544 +                                *      if no, setup transfer for next portion of data
49545 +                                */
49546 +                               if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49547 +                                       dwc_otg_ep_start_transfer(core_if,
49548 +                                                                 &ep->dwc_ep);
49549 +                               } else if (ep->dwc_ep.sent_zlp) {
49550 +                                       /*
49551 +                                        * This fragment of code should initiate 0
49552 +                                        * length trasfer in case if it is queued
49553 +                                        * a trasfer with size divisible to EPs max
49554 +                                        * packet size and with usb_request zero field
49555 +                                        * is set, which means that after data is transfered,
49556 +                                        * it is also should be transfered
49557 +                                        * a 0 length packet at the end. For Slave and
49558 +                                        * Buffer DMA modes in this case SW has
49559 +                                        * to initiate 2 transfers one with transfer size,
49560 +                                        * and the second with 0 size. For Desriptor
49561 +                                        * DMA mode SW is able to initiate a transfer,
49562 +                                        * which will handle all the packets including
49563 +                                        * the last  0 legth.
49564 +                                        */
49565 +                                       ep->dwc_ep.sent_zlp = 0;
49566 +                                       dwc_otg_ep_start_zl_transfer(core_if,
49567 +                                                                    &ep->dwc_ep);
49568 +                               } else {
49569 +                                       is_last = 1;
49570 +                               }
49571 +                       }
49572 +               } else {
49573 +                       /*      Check if the whole transfer was completed,
49574 +                        *      if no, setup transfer for next portion of data
49575 +                        */
49576 +                       if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
49577 +                               dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
49578 +                       } else if (ep->dwc_ep.sent_zlp) {
49579 +                               /*
49580 +                                * This fragment of code should initiate 0
49581 +                                * length transfer in case if it is queued
49582 +                                * a transfer with size divisible to EPs max
49583 +                                * packet size and with usb_request zero field
49584 +                                * is set, which means that after data is transfered,
49585 +                                * it is also should be transfered
49586 +                                * a 0 length packet at the end. For Slave and
49587 +                                * Buffer DMA modes in this case SW has
49588 +                                * to initiate 2 transfers one with transfer size,
49589 +                                * and the second with 0 size. For Descriptor
49590 +                                * DMA mode SW is able to initiate a transfer,
49591 +                                * which will handle all the packets including
49592 +                                * the last  0 length.
49593 +                                */
49594 +                               ep->dwc_ep.sent_zlp = 0;
49595 +                               dwc_otg_ep_start_zl_transfer(core_if,
49596 +                                                            &ep->dwc_ep);
49597 +                       } else {
49598 +                               is_last = 1;
49599 +                       }
49600 +               }
49601 +
49602 +               DWC_DEBUGPL(DBG_PCDV,
49603 +                           "addr %p,    %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
49604 +                           &out_ep_regs->doeptsiz, ep->dwc_ep.num,
49605 +                           ep->dwc_ep.is_in ? "IN" : "OUT",
49606 +                           ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
49607 +                           deptsiz.b.xfersize, deptsiz.b.pktcnt);
49608 +       }
49609 +
49610 +       /* Complete the request */
49611 +       if (is_last) {
49612 +#ifdef DWC_UTE_CFI
49613 +               if (ep->dwc_ep.buff_mode != BM_STANDARD) {
49614 +                       req->actual = ep->dwc_ep.cfi_req_len - byte_count;
49615 +               } else {
49616 +#endif
49617 +                       req->actual = ep->dwc_ep.xfer_count;
49618 +#ifdef DWC_UTE_CFI
49619 +               }
49620 +#endif
49621 +               if (req->dw_align_buf) {
49622 +                       if (!ep->dwc_ep.is_in) {
49623 +                               dwc_memcpy(req->buf, req->dw_align_buf, req->length);
49624 +                       }
49625 +                       DWC_DMA_FREE(req->length, req->dw_align_buf,
49626 +                                    req->dw_align_buf_dma);
49627 +               }
49628 +
49629 +               dwc_otg_request_done(ep, req, 0);
49630 +
49631 +               ep->dwc_ep.start_xfer_buff = 0;
49632 +               ep->dwc_ep.xfer_buff = 0;
49633 +               ep->dwc_ep.xfer_len = 0;
49634 +
49635 +               /* If there is a request in the queue start it. */
49636 +               start_next_request(ep);
49637 +       }
49638 +}
49639 +
49640 +#ifdef DWC_EN_ISOC
49641 +
49642 +/**
49643 + * This function BNA interrupt for Isochronous EPs
49644 + *
49645 + */
49646 +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
49647 +{
49648 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
49649 +       volatile uint32_t *addr;
49650 +       depctl_data_t depctl = {.d32 = 0 };
49651 +       dwc_otg_pcd_t *pcd = ep->pcd;
49652 +       dwc_otg_dev_dma_desc_t *dma_desc;
49653 +       int i;
49654 +
49655 +       dma_desc =
49656 +           dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
49657 +
49658 +       if (dwc_ep->is_in) {
49659 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49660 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49661 +                       sts.d32 = dma_desc->status.d32;
49662 +                       sts.b_iso_in.bs = BS_HOST_READY;
49663 +                       dma_desc->status.d32 = sts.d32;
49664 +               }
49665 +       } else {
49666 +               dev_dma_desc_sts_t sts = {.d32 = 0 };
49667 +               for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
49668 +                       sts.d32 = dma_desc->status.d32;
49669 +                       sts.b_iso_out.bs = BS_HOST_READY;
49670 +                       dma_desc->status.d32 = sts.d32;
49671 +               }
49672 +       }
49673 +
49674 +       if (dwc_ep->is_in == 0) {
49675 +               addr =
49676 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
49677 +                                                          num]->doepctl;
49678 +       } else {
49679 +               addr =
49680 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
49681 +       }
49682 +       depctl.b.epena = 1;
49683 +       DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
49684 +}
49685 +
49686 +/**
49687 + * This function sets latest iso packet information(non-PTI mode)
49688 + *
49689 + * @param core_if Programming view of DWC_otg controller.
49690 + * @param ep The EP to start the transfer on.
49691 + *
49692 + */
49693 +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
49694 +{
49695 +       deptsiz_data_t deptsiz = {.d32 = 0 };
49696 +       dma_addr_t dma_addr;
49697 +       uint32_t offset;
49698 +
49699 +       if (ep->proc_buf_num)
49700 +               dma_addr = ep->dma_addr1;
49701 +       else
49702 +               dma_addr = ep->dma_addr0;
49703 +
49704 +       if (ep->is_in) {
49705 +               deptsiz.d32 =
49706 +                   DWC_READ_REG32(&core_if->dev_if->
49707 +                                  in_ep_regs[ep->num]->dieptsiz);
49708 +               offset = ep->data_per_frame;
49709 +       } else {
49710 +               deptsiz.d32 =
49711 +                   DWC_READ_REG32(&core_if->dev_if->
49712 +                                  out_ep_regs[ep->num]->doeptsiz);
49713 +               offset =
49714 +                   ep->data_per_frame +
49715 +                   (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
49716 +       }
49717 +
49718 +       if (!deptsiz.b.xfersize) {
49719 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49720 +               ep->pkt_info[ep->cur_pkt].offset =
49721 +                   ep->cur_pkt_dma_addr - dma_addr;
49722 +               ep->pkt_info[ep->cur_pkt].status = 0;
49723 +       } else {
49724 +               ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
49725 +               ep->pkt_info[ep->cur_pkt].offset =
49726 +                   ep->cur_pkt_dma_addr - dma_addr;
49727 +               ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
49728 +       }
49729 +       ep->cur_pkt_addr += offset;
49730 +       ep->cur_pkt_dma_addr += offset;
49731 +       ep->cur_pkt++;
49732 +}
49733 +
49734 +/**
49735 + * This function sets latest iso packet information(DDMA mode)
49736 + *
49737 + * @param core_if Programming view of DWC_otg controller.
49738 + * @param dwc_ep The EP to start the transfer on.
49739 + *
49740 + */
49741 +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
49742 +                                  dwc_ep_t * dwc_ep)
49743 +{
49744 +       dwc_otg_dev_dma_desc_t *dma_desc;
49745 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
49746 +       iso_pkt_info_t *iso_packet;
49747 +       uint32_t data_per_desc;
49748 +       uint32_t offset;
49749 +       int i, j;
49750 +
49751 +       iso_packet = dwc_ep->pkt_info;
49752 +
49753 +       /** Reinit closed DMA Descriptors*/
49754 +       /** ISO OUT EP */
49755 +       if (dwc_ep->is_in == 0) {
49756 +               dma_desc =
49757 +                   dwc_ep->iso_desc_addr +
49758 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49759 +               offset = 0;
49760 +
49761 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
49762 +                    i += dwc_ep->pkt_per_frm) {
49763 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
49764 +                               data_per_desc =
49765 +                                   ((j + 1) * dwc_ep->maxpacket >
49766 +                                    dwc_ep->
49767 +                                    data_per_frame) ? dwc_ep->data_per_frame -
49768 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49769 +                               data_per_desc +=
49770 +                                   (data_per_desc % 4) ? (4 -
49771 +                                                          data_per_desc %
49772 +                                                          4) : 0;
49773 +
49774 +                               sts.d32 = dma_desc->status.d32;
49775 +
49776 +                               /* Write status in iso_packet_decsriptor  */
49777 +                               iso_packet->status =
49778 +                                   sts.b_iso_out.rxsts +
49779 +                                   (sts.b_iso_out.bs ^ BS_DMA_DONE);
49780 +                               if (iso_packet->status) {
49781 +                                       iso_packet->status = -DWC_E_NO_DATA;
49782 +                               }
49783 +
49784 +                               /* Received data length */
49785 +                               if (!sts.b_iso_out.rxbytes) {
49786 +                                       iso_packet->length =
49787 +                                           data_per_desc -
49788 +                                           sts.b_iso_out.rxbytes;
49789 +                               } else {
49790 +                                       iso_packet->length =
49791 +                                           data_per_desc -
49792 +                                           sts.b_iso_out.rxbytes + (4 -
49793 +                                                                    dwc_ep->data_per_frame
49794 +                                                                    % 4);
49795 +                               }
49796 +
49797 +                               iso_packet->offset = offset;
49798 +
49799 +                               offset += data_per_desc;
49800 +                               dma_desc++;
49801 +                               iso_packet++;
49802 +                       }
49803 +               }
49804 +
49805 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
49806 +                       data_per_desc =
49807 +                           ((j + 1) * dwc_ep->maxpacket >
49808 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49809 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49810 +                       data_per_desc +=
49811 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49812 +
49813 +                       sts.d32 = dma_desc->status.d32;
49814 +
49815 +                       /* Write status in iso_packet_decsriptor  */
49816 +                       iso_packet->status =
49817 +                           sts.b_iso_out.rxsts +
49818 +                           (sts.b_iso_out.bs ^ BS_DMA_DONE);
49819 +                       if (iso_packet->status) {
49820 +                               iso_packet->status = -DWC_E_NO_DATA;
49821 +                       }
49822 +
49823 +                       /* Received data length */
49824 +                       iso_packet->length =
49825 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49826 +
49827 +                       iso_packet->offset = offset;
49828 +
49829 +                       offset += data_per_desc;
49830 +                       iso_packet++;
49831 +                       dma_desc++;
49832 +               }
49833 +
49834 +               sts.d32 = dma_desc->status.d32;
49835 +
49836 +               /* Write status in iso_packet_decsriptor  */
49837 +               iso_packet->status =
49838 +                   sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
49839 +               if (iso_packet->status) {
49840 +                       iso_packet->status = -DWC_E_NO_DATA;
49841 +               }
49842 +               /* Received data length */
49843 +               if (!sts.b_iso_out.rxbytes) {
49844 +                       iso_packet->length =
49845 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
49846 +               } else {
49847 +                       iso_packet->length =
49848 +                           dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
49849 +                           (4 - dwc_ep->data_per_frame % 4);
49850 +               }
49851 +
49852 +               iso_packet->offset = offset;
49853 +       } else {
49854 +/** ISO IN EP */
49855 +
49856 +               dma_desc =
49857 +                   dwc_ep->iso_desc_addr +
49858 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49859 +
49860 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
49861 +                       sts.d32 = dma_desc->status.d32;
49862 +
49863 +                       /* Write status in iso packet descriptor */
49864 +                       iso_packet->status =
49865 +                           sts.b_iso_in.txsts +
49866 +                           (sts.b_iso_in.bs ^ BS_DMA_DONE);
49867 +                       if (iso_packet->status != 0) {
49868 +                               iso_packet->status = -DWC_E_NO_DATA;
49869 +
49870 +                       }
49871 +                       /* Bytes has been transfered */
49872 +                       iso_packet->length =
49873 +                           dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
49874 +
49875 +                       dma_desc++;
49876 +                       iso_packet++;
49877 +               }
49878 +
49879 +               sts.d32 = dma_desc->status.d32;
49880 +               while (sts.b_iso_in.bs == BS_DMA_BUSY) {
49881 +                       sts.d32 = dma_desc->status.d32;
49882 +               }
49883 +
49884 +               /* Write status in iso packet descriptor ??? do be done with ERROR codes */
49885 +               iso_packet->status =
49886 +                   sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
49887 +               if (iso_packet->status != 0) {
49888 +                       iso_packet->status = -DWC_E_NO_DATA;
49889 +               }
49890 +
49891 +               /* Bytes has been transfered */
49892 +               iso_packet->length =
49893 +                   dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
49894 +       }
49895 +}
49896 +
49897 +/**
49898 + * This function reinitialize DMA Descriptors for Isochronous transfer
49899 + *
49900 + * @param core_if Programming view of DWC_otg controller.
49901 + * @param dwc_ep The EP to start the transfer on.
49902 + *
49903 + */
49904 +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
49905 +{
49906 +       int i, j;
49907 +       dwc_otg_dev_dma_desc_t *dma_desc;
49908 +       dma_addr_t dma_ad;
49909 +       volatile uint32_t *addr;
49910 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
49911 +       uint32_t data_per_desc;
49912 +
49913 +       if (dwc_ep->is_in == 0) {
49914 +               addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
49915 +       } else {
49916 +               addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
49917 +       }
49918 +
49919 +       if (dwc_ep->proc_buf_num == 0) {
49920 +               /** Buffer 0 descriptors setup */
49921 +               dma_ad = dwc_ep->dma_addr0;
49922 +       } else {
49923 +               /** Buffer 1 descriptors setup */
49924 +               dma_ad = dwc_ep->dma_addr1;
49925 +       }
49926 +
49927 +       /** Reinit closed DMA Descriptors*/
49928 +       /** ISO OUT EP */
49929 +       if (dwc_ep->is_in == 0) {
49930 +               dma_desc =
49931 +                   dwc_ep->iso_desc_addr +
49932 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49933 +
49934 +               sts.b_iso_out.bs = BS_HOST_READY;
49935 +               sts.b_iso_out.rxsts = 0;
49936 +               sts.b_iso_out.l = 0;
49937 +               sts.b_iso_out.sp = 0;
49938 +               sts.b_iso_out.ioc = 0;
49939 +               sts.b_iso_out.pid = 0;
49940 +               sts.b_iso_out.framenum = 0;
49941 +
49942 +               for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
49943 +                    i += dwc_ep->pkt_per_frm) {
49944 +                       for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
49945 +                               data_per_desc =
49946 +                                   ((j + 1) * dwc_ep->maxpacket >
49947 +                                    dwc_ep->
49948 +                                    data_per_frame) ? dwc_ep->data_per_frame -
49949 +                                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49950 +                               data_per_desc +=
49951 +                                   (data_per_desc % 4) ? (4 -
49952 +                                                          data_per_desc %
49953 +                                                          4) : 0;
49954 +                               sts.b_iso_out.rxbytes = data_per_desc;
49955 +                               dma_desc->buf = dma_ad;
49956 +                               dma_desc->status.d32 = sts.d32;
49957 +
49958 +                               dma_ad += data_per_desc;
49959 +                               dma_desc++;
49960 +                       }
49961 +               }
49962 +
49963 +               for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
49964 +
49965 +                       data_per_desc =
49966 +                           ((j + 1) * dwc_ep->maxpacket >
49967 +                            dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49968 +                           j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49969 +                       data_per_desc +=
49970 +                           (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49971 +                       sts.b_iso_out.rxbytes = data_per_desc;
49972 +
49973 +                       dma_desc->buf = dma_ad;
49974 +                       dma_desc->status.d32 = sts.d32;
49975 +
49976 +                       dma_desc++;
49977 +                       dma_ad += data_per_desc;
49978 +               }
49979 +
49980 +               sts.b_iso_out.ioc = 1;
49981 +               sts.b_iso_out.l = dwc_ep->proc_buf_num;
49982 +
49983 +               data_per_desc =
49984 +                   ((j + 1) * dwc_ep->maxpacket >
49985 +                    dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
49986 +                   j * dwc_ep->maxpacket : dwc_ep->maxpacket;
49987 +               data_per_desc +=
49988 +                   (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
49989 +               sts.b_iso_out.rxbytes = data_per_desc;
49990 +
49991 +               dma_desc->buf = dma_ad;
49992 +               dma_desc->status.d32 = sts.d32;
49993 +       } else {
49994 +/** ISO IN EP */
49995 +
49996 +               dma_desc =
49997 +                   dwc_ep->iso_desc_addr +
49998 +                   dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
49999 +
50000 +               sts.b_iso_in.bs = BS_HOST_READY;
50001 +               sts.b_iso_in.txsts = 0;
50002 +               sts.b_iso_in.sp = 0;
50003 +               sts.b_iso_in.ioc = 0;
50004 +               sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
50005 +               sts.b_iso_in.framenum = dwc_ep->next_frame;
50006 +               sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
50007 +               sts.b_iso_in.l = 0;
50008 +
50009 +               for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
50010 +                       dma_desc->buf = dma_ad;
50011 +                       dma_desc->status.d32 = sts.d32;
50012 +
50013 +                       sts.b_iso_in.framenum += dwc_ep->bInterval;
50014 +                       dma_ad += dwc_ep->data_per_frame;
50015 +                       dma_desc++;
50016 +               }
50017 +
50018 +               sts.b_iso_in.ioc = 1;
50019 +               sts.b_iso_in.l = dwc_ep->proc_buf_num;
50020 +
50021 +               dma_desc->buf = dma_ad;
50022 +               dma_desc->status.d32 = sts.d32;
50023 +
50024 +               dwc_ep->next_frame =
50025 +                   sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
50026 +       }
50027 +       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50028 +}
50029 +
50030 +/**
50031 + * This function is to handle Iso EP transfer complete interrupt
50032 + * in case Iso out packet was dropped
50033 + *
50034 + * @param core_if Programming view of DWC_otg controller.
50035 + * @param dwc_ep The EP for wihich transfer complete was asserted
50036 + *
50037 + */
50038 +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
50039 +                                          dwc_ep_t * dwc_ep)
50040 +{
50041 +       uint32_t dma_addr;
50042 +       uint32_t drp_pkt;
50043 +       uint32_t drp_pkt_cnt;
50044 +       deptsiz_data_t deptsiz = {.d32 = 0 };
50045 +       depctl_data_t depctl = {.d32 = 0 };
50046 +       int i;
50047 +
50048 +       deptsiz.d32 =
50049 +           DWC_READ_REG32(&core_if->dev_if->
50050 +                          out_ep_regs[dwc_ep->num]->doeptsiz);
50051 +
50052 +       drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
50053 +       drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
50054 +
50055 +       /* Setting dropped packets status */
50056 +       for (i = 0; i < drp_pkt_cnt; ++i) {
50057 +               dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
50058 +               drp_pkt++;
50059 +               deptsiz.b.pktcnt--;
50060 +       }
50061 +
50062 +       if (deptsiz.b.pktcnt > 0) {
50063 +               deptsiz.b.xfersize =
50064 +                   dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
50065 +                                       deptsiz.b.pktcnt) * dwc_ep->maxpacket;
50066 +       } else {
50067 +               deptsiz.b.xfersize = 0;
50068 +               deptsiz.b.pktcnt = 0;
50069 +       }
50070 +
50071 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
50072 +                       deptsiz.d32);
50073 +
50074 +       if (deptsiz.b.pktcnt > 0) {
50075 +               if (dwc_ep->proc_buf_num) {
50076 +                       dma_addr =
50077 +                           dwc_ep->dma_addr1 + dwc_ep->xfer_len -
50078 +                           deptsiz.b.xfersize;
50079 +               } else {
50080 +                       dma_addr =
50081 +                           dwc_ep->dma_addr0 + dwc_ep->xfer_len -
50082 +                           deptsiz.b.xfersize;;
50083 +               }
50084 +
50085 +               DWC_WRITE_REG32(&core_if->dev_if->
50086 +                               out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
50087 +
50088 +               /** Re-enable endpoint, clear nak  */
50089 +               depctl.d32 = 0;
50090 +               depctl.b.epena = 1;
50091 +               depctl.b.cnak = 1;
50092 +
50093 +               DWC_MODIFY_REG32(&core_if->dev_if->
50094 +                                out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
50095 +                                depctl.d32);
50096 +               return 0;
50097 +       } else {
50098 +               return 1;
50099 +       }
50100 +}
50101 +
50102 +/**
50103 + * This function sets iso packets information(PTI mode)
50104 + *
50105 + * @param core_if Programming view of DWC_otg controller.
50106 + * @param ep The EP to start the transfer on.
50107 + *
50108 + */
50109 +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
50110 +{
50111 +       int i, j;
50112 +       dma_addr_t dma_ad;
50113 +       iso_pkt_info_t *packet_info = ep->pkt_info;
50114 +       uint32_t offset;
50115 +       uint32_t frame_data;
50116 +       deptsiz_data_t deptsiz;
50117 +
50118 +       if (ep->proc_buf_num == 0) {
50119 +               /** Buffer 0 descriptors setup */
50120 +               dma_ad = ep->dma_addr0;
50121 +       } else {
50122 +               /** Buffer 1 descriptors setup */
50123 +               dma_ad = ep->dma_addr1;
50124 +       }
50125 +
50126 +       if (ep->is_in) {
50127 +               deptsiz.d32 =
50128 +                   DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
50129 +                                  dieptsiz);
50130 +       } else {
50131 +               deptsiz.d32 =
50132 +                   DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
50133 +                                  doeptsiz);
50134 +       }
50135 +
50136 +       if (!deptsiz.b.xfersize) {
50137 +               offset = 0;
50138 +               for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
50139 +                       frame_data = ep->data_per_frame;
50140 +                       for (j = 0; j < ep->pkt_per_frm; ++j) {
50141 +
50142 +                               /* Packet status - is not set as initially
50143 +                                * it is set to 0 and if packet was sent
50144 +                                successfully, status field will remain 0*/
50145 +
50146 +                               /* Bytes has been transfered */
50147 +                               packet_info->length =
50148 +                                   (ep->maxpacket <
50149 +                                    frame_data) ? ep->maxpacket : frame_data;
50150 +
50151 +                               /* Received packet offset */
50152 +                               packet_info->offset = offset;
50153 +                               offset += packet_info->length;
50154 +                               frame_data -= packet_info->length;
50155 +
50156 +                               packet_info++;
50157 +                       }
50158 +               }
50159 +               return 1;
50160 +       } else {
50161 +               /* This is a workaround for in case of Transfer Complete with
50162 +                * PktDrpSts interrupts merging - in this case Transfer complete
50163 +                * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
50164 +                * set and with DOEPTSIZ register non zero. Investigations showed,
50165 +                * that this happens when Out packet is dropped, but because of
50166 +                * interrupts merging during first interrupt handling PktDrpSts
50167 +                * bit is cleared and for next merged interrupts it is not reset.
50168 +                * In this case SW hadles the interrupt as if PktDrpSts bit is set.
50169 +                */
50170 +               if (ep->is_in) {
50171 +                       return 1;
50172 +               } else {
50173 +                       return handle_iso_out_pkt_dropped(core_if, ep);
50174 +               }
50175 +       }
50176 +}
50177 +
50178 +/**
50179 + * This function is to handle Iso EP transfer complete interrupt
50180 + *
50181 + * @param pcd The PCD
50182 + * @param ep The EP for which transfer complete was asserted
50183 + *
50184 + */
50185 +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
50186 +{
50187 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
50188 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50189 +       uint8_t is_last = 0;
50190 +
50191 +       if (ep->dwc_ep.next_frame == 0xffffffff) {
50192 +               DWC_WARN("Next frame is not set!\n");
50193 +               return;
50194 +       }
50195 +
50196 +       if (core_if->dma_enable) {
50197 +               if (core_if->dma_desc_enable) {
50198 +                       set_ddma_iso_pkts_info(core_if, dwc_ep);
50199 +                       reinit_ddma_iso_xfer(core_if, dwc_ep);
50200 +                       is_last = 1;
50201 +               } else {
50202 +                       if (core_if->pti_enh_enable) {
50203 +                               if (set_iso_pkts_info(core_if, dwc_ep)) {
50204 +                                       dwc_ep->proc_buf_num =
50205 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50206 +                                       dwc_otg_iso_ep_start_buf_transfer
50207 +                                           (core_if, dwc_ep);
50208 +                                       is_last = 1;
50209 +                               }
50210 +                       } else {
50211 +                               set_current_pkt_info(core_if, dwc_ep);
50212 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50213 +                                       is_last = 1;
50214 +                                       dwc_ep->cur_pkt = 0;
50215 +                                       dwc_ep->proc_buf_num =
50216 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
50217 +                                       if (dwc_ep->proc_buf_num) {
50218 +                                               dwc_ep->cur_pkt_addr =
50219 +                                                   dwc_ep->xfer_buff1;
50220 +                                               dwc_ep->cur_pkt_dma_addr =
50221 +                                                   dwc_ep->dma_addr1;
50222 +                                       } else {
50223 +                                               dwc_ep->cur_pkt_addr =
50224 +                                                   dwc_ep->xfer_buff0;
50225 +                                               dwc_ep->cur_pkt_dma_addr =
50226 +                                                   dwc_ep->dma_addr0;
50227 +                                       }
50228 +
50229 +                               }
50230 +                               dwc_otg_iso_ep_start_frm_transfer(core_if,
50231 +                                                                 dwc_ep);
50232 +                       }
50233 +               }
50234 +       } else {
50235 +               set_current_pkt_info(core_if, dwc_ep);
50236 +               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
50237 +                       is_last = 1;
50238 +                       dwc_ep->cur_pkt = 0;
50239 +                       dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
50240 +                       if (dwc_ep->proc_buf_num) {
50241 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
50242 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
50243 +                       } else {
50244 +                               dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
50245 +                               dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
50246 +                       }
50247 +
50248 +               }
50249 +               dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
50250 +       }
50251 +       if (is_last)
50252 +               dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
50253 +}
50254 +#endif /* DWC_EN_ISOC */
50255 +
50256 +/**
50257 + * This function handle BNA interrupt for Non Isochronous EPs
50258 + *
50259 + */
50260 +static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
50261 +{
50262 +       dwc_ep_t *dwc_ep = &ep->dwc_ep;
50263 +       volatile uint32_t *addr;
50264 +       depctl_data_t depctl = {.d32 = 0 };
50265 +       dwc_otg_pcd_t *pcd = ep->pcd;
50266 +       dwc_otg_dev_dma_desc_t *dma_desc;
50267 +       dev_dma_desc_sts_t sts = {.d32 = 0 };
50268 +       dwc_otg_core_if_t *core_if = ep->pcd->core_if;
50269 +       int i, start;
50270 +
50271 +       if (!dwc_ep->desc_cnt)
50272 +               DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
50273 +                        (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
50274 +
50275 +       if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
50276 +                                                       && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
50277 +               uint32_t doepdma;
50278 +               dwc_otg_dev_out_ep_regs_t *out_regs =
50279 +                       core_if->dev_if->out_ep_regs[dwc_ep->num];
50280 +               doepdma = DWC_READ_REG32(&(out_regs->doepdma));
50281 +               start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
50282 +               dma_desc = &(dwc_ep->desc_addr[start]);
50283 +       } else {
50284 +               start = 0;
50285 +               dma_desc = dwc_ep->desc_addr;
50286 +       }
50287 +
50288 +
50289 +       for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
50290 +               sts.d32 = dma_desc->status.d32;
50291 +               sts.b.bs = BS_HOST_READY;
50292 +               dma_desc->status.d32 = sts.d32;
50293 +       }
50294 +
50295 +       if (dwc_ep->is_in == 0) {
50296 +               addr =
50297 +                   &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
50298 +                   doepctl;
50299 +       } else {
50300 +               addr =
50301 +                   &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
50302 +       }
50303 +       depctl.b.epena = 1;
50304 +       depctl.b.cnak = 1;
50305 +       DWC_MODIFY_REG32(addr, 0, depctl.d32);
50306 +}
50307 +
50308 +/**
50309 + * This function handles EP0 Control transfers.
50310 + *
50311 + * The state of the control transfers are tracked in
50312 + * <code>ep0state</code>.
50313 + */
50314 +static void handle_ep0(dwc_otg_pcd_t * pcd)
50315 +{
50316 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50317 +       dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
50318 +       dev_dma_desc_sts_t desc_sts;
50319 +       deptsiz0_data_t deptsiz;
50320 +       uint32_t byte_count;
50321 +
50322 +#ifdef DEBUG_EP0
50323 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
50324 +       print_ep0_state(pcd);
50325 +#endif
50326 +
50327 +//      DWC_PRINTF("HANDLE EP0\n");
50328 +
50329 +       switch (pcd->ep0state) {
50330 +       case EP0_DISCONNECT:
50331 +               break;
50332 +
50333 +       case EP0_IDLE:
50334 +               pcd->request_config = 0;
50335 +
50336 +               pcd_setup(pcd);
50337 +               break;
50338 +
50339 +       case EP0_IN_DATA_PHASE:
50340 +#ifdef DEBUG_EP0
50341 +               DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
50342 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50343 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50344 +#endif
50345 +
50346 +               if (core_if->dma_enable != 0) {
50347 +                       /*
50348 +                        * For EP0 we can only program 1 packet at a time so we
50349 +                        * need to do the make calculations after each complete.
50350 +                        * Call write_packet to make the calculations, as in
50351 +                        * slave mode, and use those values to determine if we
50352 +                        * can complete.
50353 +                        */
50354 +                       if (core_if->dma_desc_enable == 0) {
50355 +                               deptsiz.d32 =
50356 +                                   DWC_READ_REG32(&core_if->
50357 +                                                  dev_if->in_ep_regs[0]->
50358 +                                                  dieptsiz);
50359 +                               byte_count =
50360 +                                   ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
50361 +                       } else {
50362 +                               desc_sts =
50363 +                                   core_if->dev_if->in_desc_addr->status;
50364 +                               byte_count =
50365 +                                   ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
50366 +                       }
50367 +                       ep0->dwc_ep.xfer_count += byte_count;
50368 +                       ep0->dwc_ep.xfer_buff += byte_count;
50369 +                       ep0->dwc_ep.dma_addr += byte_count;
50370 +               }
50371 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50372 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50373 +                                                     &ep0->dwc_ep);
50374 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50375 +               } else if (ep0->dwc_ep.sent_zlp) {
50376 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50377 +                                                     &ep0->dwc_ep);
50378 +                       ep0->dwc_ep.sent_zlp = 0;
50379 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50380 +               } else {
50381 +                       ep0_complete_request(ep0);
50382 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50383 +               }
50384 +               break;
50385 +       case EP0_OUT_DATA_PHASE:
50386 +#ifdef DEBUG_EP0
50387 +               DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
50388 +                           ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
50389 +                           ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
50390 +#endif
50391 +               if (core_if->dma_enable != 0) {
50392 +                       if (core_if->dma_desc_enable == 0) {
50393 +                               deptsiz.d32 =
50394 +                                   DWC_READ_REG32(&core_if->
50395 +                                                  dev_if->out_ep_regs[0]->
50396 +                                                  doeptsiz);
50397 +                               byte_count =
50398 +                                   ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
50399 +                       } else {
50400 +                               desc_sts =
50401 +                                   core_if->dev_if->out_desc_addr->status;
50402 +                               byte_count =
50403 +                                   ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
50404 +                       }
50405 +                       ep0->dwc_ep.xfer_count += byte_count;
50406 +                       ep0->dwc_ep.xfer_buff += byte_count;
50407 +                       ep0->dwc_ep.dma_addr += byte_count;
50408 +               }
50409 +               if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
50410 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50411 +                                                     &ep0->dwc_ep);
50412 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
50413 +               } else if (ep0->dwc_ep.sent_zlp) {
50414 +                       dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
50415 +                                                     &ep0->dwc_ep);
50416 +                       ep0->dwc_ep.sent_zlp = 0;
50417 +                       DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
50418 +               } else {
50419 +                       ep0_complete_request(ep0);
50420 +                       DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
50421 +               }
50422 +               break;
50423 +
50424 +       case EP0_IN_STATUS_PHASE:
50425 +       case EP0_OUT_STATUS_PHASE:
50426 +               DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
50427 +               ep0_complete_request(ep0);
50428 +               pcd->ep0state = EP0_IDLE;
50429 +               ep0->stopped = 1;
50430 +               ep0->dwc_ep.is_in = 0;  /* OUT for next SETUP */
50431 +
50432 +               /* Prepare for more SETUP Packets */
50433 +               if (core_if->dma_enable) {
50434 +                       ep0_out_start(core_if, pcd);
50435 +               }
50436 +               break;
50437 +
50438 +       case EP0_STALL:
50439 +               DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
50440 +               break;
50441 +       }
50442 +#ifdef DEBUG_EP0
50443 +       print_ep0_state(pcd);
50444 +#endif
50445 +}
50446 +
50447 +/**
50448 + * Restart transfer
50449 + */
50450 +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
50451 +{
50452 +       dwc_otg_core_if_t *core_if;
50453 +       dwc_otg_dev_if_t *dev_if;
50454 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50455 +       dwc_otg_pcd_ep_t *ep;
50456 +
50457 +       ep = get_in_ep(pcd, epnum);
50458 +
50459 +#ifdef DWC_EN_ISOC
50460 +       if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
50461 +               return;
50462 +       }
50463 +#endif /* DWC_EN_ISOC  */
50464 +
50465 +       core_if = GET_CORE_IF(pcd);
50466 +       dev_if = core_if->dev_if;
50467 +
50468 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50469 +
50470 +       DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
50471 +                   " stopped=%d\n", ep->dwc_ep.xfer_buff,
50472 +                   ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
50473 +       /*
50474 +        * If xfersize is 0 and pktcnt in not 0, resend the last packet.
50475 +        */
50476 +       if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
50477 +           ep->dwc_ep.start_xfer_buff != 0) {
50478 +               if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
50479 +                       ep->dwc_ep.xfer_count = 0;
50480 +                       ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
50481 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50482 +               } else {
50483 +                       ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
50484 +                       /* convert packet size to dwords. */
50485 +                       ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
50486 +                       ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
50487 +               }
50488 +               ep->stopped = 0;
50489 +               DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
50490 +                           "xfer_len=%0x stopped=%d\n",
50491 +                           ep->dwc_ep.xfer_buff,
50492 +                           ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
50493 +                           ep->stopped);
50494 +               if (epnum == 0) {
50495 +                       dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
50496 +               } else {
50497 +                       dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
50498 +               }
50499 +       }
50500 +}
50501 +
50502 +/*
50503 + * This function create new nextep sequnce based on Learn Queue.
50504 + *
50505 + * @param core_if Programming view of DWC_otg controller
50506 + */
50507 +void predict_nextep_seq( dwc_otg_core_if_t * core_if)
50508 +{
50509 +       dwc_otg_device_global_regs_t *dev_global_regs =
50510 +           core_if->dev_if->dev_global_regs;
50511 +       const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
50512 +       /* Number of Token Queue Registers */
50513 +       const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
50514 +       dtknq1_data_t dtknqr1;
50515 +       uint32_t in_tkn_epnums[4];
50516 +       uint8_t seqnum[MAX_EPS_CHANNELS];
50517 +       uint8_t intkn_seq[TOKEN_Q_DEPTH];
50518 +       grstctl_t resetctl = {.d32 = 0 };
50519 +       uint8_t temp;
50520 +       int ndx = 0;
50521 +       int start = 0;
50522 +       int end = 0;
50523 +       int sort_done = 0;
50524 +       int i = 0;
50525 +       volatile uint32_t *addr = &dev_global_regs->dtknqr1;
50526 +
50527 +
50528 +       DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
50529 +
50530 +       /* Read the DTKNQ Registers */
50531 +       for (i = 0; i < DTKNQ_REG_CNT; i++) {
50532 +               in_tkn_epnums[i] = DWC_READ_REG32(addr);
50533 +               DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
50534 +                           in_tkn_epnums[i]);
50535 +               if (addr == &dev_global_regs->dvbusdis) {
50536 +                       addr = &dev_global_regs->dtknqr3_dthrctl;
50537 +               } else {
50538 +                       ++addr;
50539 +               }
50540 +
50541 +       }
50542 +
50543 +       /* Copy the DTKNQR1 data to the bit field. */
50544 +       dtknqr1.d32 = in_tkn_epnums[0];
50545 +       if (dtknqr1.b.wrap_bit) {
50546 +               ndx = dtknqr1.b.intknwptr;
50547 +               end = ndx -1;
50548 +               if (end < 0)
50549 +                       end = TOKEN_Q_DEPTH -1;
50550 +       } else {
50551 +               ndx = 0;
50552 +               end = dtknqr1.b.intknwptr -1;
50553 +               if (end < 0)
50554 +                       end = 0;
50555 +       }
50556 +       start = ndx;
50557 +
50558 +       /* Fill seqnum[] by initial values: EP number + 31 */
50559 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50560 +               seqnum[i] = i +31;
50561 +       }
50562 +
50563 +       /* Fill intkn_seq[] from in_tkn_epnums[0] */
50564 +       for (i=0; i < 6; i++)
50565 +               intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
50566 +
50567 +       if (TOKEN_Q_DEPTH > 6) {
50568 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50569 +               for (i=6; i < 14; i++)
50570 +                       intkn_seq[i] =
50571 +                           (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
50572 +       }
50573 +
50574 +       if (TOKEN_Q_DEPTH > 14) {
50575 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50576 +               for (i=14; i < 22; i++)
50577 +                       intkn_seq[i] =
50578 +                           (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
50579 +       }
50580 +
50581 +       if (TOKEN_Q_DEPTH > 22) {
50582 +               /* Fill intkn_seq[] from in_tkn_epnums[1] */
50583 +               for (i=22; i < 30; i++)
50584 +                       intkn_seq[i] =
50585 +                           (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
50586 +       }
50587 +
50588 +       DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
50589 +                   start, end);
50590 +       for (i=0; i<TOKEN_Q_DEPTH; i++)
50591 +               DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
50592 +
50593 +       /* Update seqnum based on intkn_seq[] */
50594 +       i = 0;
50595 +       do {
50596 +               seqnum[intkn_seq[ndx]] = i;
50597 +               ndx++;
50598 +               i++;
50599 +               if (ndx == TOKEN_Q_DEPTH)
50600 +                       ndx = 0;
50601 +       } while ( i < TOKEN_Q_DEPTH );
50602 +
50603 +       /* Mark non active EP's in seqnum[] by 0xff */
50604 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50605 +               if (core_if->nextep_seq[i] == 0xff )
50606 +                       seqnum[i] = 0xff;
50607 +       }
50608 +
50609 +       /* Sort seqnum[] */
50610 +       sort_done = 0;
50611 +       while (!sort_done) {
50612 +               sort_done = 1;
50613 +               for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50614 +                       if (seqnum[i] > seqnum[i+1]) {
50615 +                               temp = seqnum[i];
50616 +                               seqnum[i] = seqnum[i+1];
50617 +                               seqnum[i+1] = temp;
50618 +                               sort_done = 0;
50619 +                       }
50620 +               }
50621 +       }
50622 +
50623 +       ndx = start + seqnum[0];
50624 +       if (ndx >= TOKEN_Q_DEPTH)
50625 +               ndx = ndx % TOKEN_Q_DEPTH;
50626 +       core_if->first_in_nextep_seq = intkn_seq[ndx];
50627 +
50628 +       /* Update seqnum[] by EP numbers  */
50629 +       for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
50630 +               ndx = start + i;
50631 +               if (seqnum[i] < 31) {
50632 +                       ndx = start + seqnum[i];
50633 +                       if (ndx >= TOKEN_Q_DEPTH)
50634 +                               ndx = ndx % TOKEN_Q_DEPTH;
50635 +                       seqnum[i] = intkn_seq[ndx];
50636 +               } else {
50637 +                       if (seqnum[i] < 0xff) {
50638 +                               seqnum[i] = seqnum[i] - 31;
50639 +                       } else {
50640 +                               break;
50641 +                       }
50642 +               }
50643 +       }
50644 +
50645 +       /* Update nextep_seq[] based on seqnum[] */
50646 +       for (i=0; i<core_if->dev_if->num_in_eps; i++) {
50647 +               if (seqnum[i] != 0xff) {
50648 +                       if (seqnum[i+1] != 0xff) {
50649 +                               core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
50650 +                       } else {
50651 +                               core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
50652 +                               break;
50653 +                       }
50654 +               } else {
50655 +                       break;
50656 +               }
50657 +       }
50658 +
50659 +       DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
50660 +               __func__, core_if->first_in_nextep_seq);
50661 +       for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
50662 +               DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
50663 +       }
50664 +
50665 +       /* Flush the Learning Queue */
50666 +       resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
50667 +       resetctl.b.intknqflsh = 1;
50668 +       DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
50669 +
50670 +
50671 +}
50672 +
50673 +/**
50674 + * handle the IN EP disable interrupt.
50675 + */
50676 +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
50677 +                                            const uint32_t epnum)
50678 +{
50679 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50680 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50681 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50682 +       dctl_data_t dctl = {.d32 = 0 };
50683 +       dwc_otg_pcd_ep_t *ep;
50684 +       dwc_ep_t *dwc_ep;
50685 +       gintmsk_data_t gintmsk_data;
50686 +       depctl_data_t depctl;
50687 +       uint32_t diepdma;
50688 +       uint32_t remain_to_transfer = 0;
50689 +       uint8_t i;
50690 +       uint32_t xfer_size;
50691 +
50692 +       ep = get_in_ep(pcd, epnum);
50693 +       dwc_ep = &ep->dwc_ep;
50694 +
50695 +       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
50696 +               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50697 +               complete_ep(ep);
50698 +               return;
50699 +       }
50700 +
50701 +       DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
50702 +                   DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
50703 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
50704 +       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
50705 +
50706 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
50707 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
50708 +
50709 +       if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {
50710 +               if (ep->stopped) {
50711 +                       if (core_if->en_multiple_tx_fifo)
50712 +                               /* Flush the Tx FIFO */
50713 +                               dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
50714 +                       /* Clear the Global IN NP NAK */
50715 +                       dctl.d32 = 0;
50716 +                       dctl.b.cgnpinnak = 1;
50717 +                       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50718 +                       /* Restart the transaction */
50719 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50720 +                               restart_transfer(pcd, epnum);
50721 +                       }
50722 +               } else {
50723 +                       /* Restart the transaction */
50724 +                       if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
50725 +                               restart_transfer(pcd, epnum);
50726 +                       }
50727 +                       DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
50728 +               }
50729 +               return;
50730 +       }
50731 +
50732 +       if (core_if->start_predict > 2) {       // NP IN EP
50733 +               core_if->start_predict--;
50734 +               return;
50735 +       }
50736 +
50737 +       core_if->start_predict--;
50738 +
50739 +       if (core_if->start_predict == 1) {      // All NP IN Ep's disabled now
50740 +
50741 +               predict_nextep_seq(core_if);
50742 +
50743 +               /* Update all active IN EP's NextEP field based of nextep_seq[] */
50744 +               for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
50745 +                       depctl.d32 =
50746 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50747 +                       if (core_if->nextep_seq[i] != 0xff) {   // Active NP IN EP
50748 +                               depctl.b.nextep = core_if->nextep_seq[i];
50749 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50750 +                       }
50751 +               }
50752 +               /* Flush Shared NP TxFIFO */
50753 +               dwc_otg_flush_tx_fifo(core_if, 0);
50754 +               /* Rewind buffers */
50755 +               if (!core_if->dma_desc_enable) {
50756 +                       i = core_if->first_in_nextep_seq;
50757 +                       do {
50758 +                               ep = get_in_ep(pcd, i);
50759 +                               dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50760 +                               xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
50761 +                               if (xfer_size > ep->dwc_ep.maxxfer)
50762 +                                       xfer_size = ep->dwc_ep.maxxfer;
50763 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50764 +                               if (dieptsiz.b.pktcnt != 0) {
50765 +                                       if (xfer_size == 0) {
50766 +                                               remain_to_transfer = 0;
50767 +                                       } else {
50768 +                                               if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
50769 +                                                       remain_to_transfer =
50770 +                                                               dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
50771 +                                               } else {
50772 +                                                       remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)
50773 +                                                               + (xfer_size % ep->dwc_ep.maxpacket);
50774 +                                               }
50775 +                                       }
50776 +                                       diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
50777 +                                       dieptsiz.b.xfersize = remain_to_transfer;
50778 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
50779 +                                       diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
50780 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
50781 +                               }
50782 +                               i = core_if->nextep_seq[i];
50783 +                       } while (i != core_if->first_in_nextep_seq);
50784 +               } else { // dma_desc_enable
50785 +                               DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
50786 +               }
50787 +
50788 +               /* Restart transfers in predicted sequences */
50789 +               i = core_if->first_in_nextep_seq;
50790 +               do {
50791 +                       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
50792 +                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50793 +                       if (dieptsiz.b.pktcnt != 0) {
50794 +                               depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
50795 +                               depctl.b.epena = 1;
50796 +                               depctl.b.cnak = 1;
50797 +                               DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
50798 +                       }
50799 +                       i = core_if->nextep_seq[i];
50800 +               } while (i != core_if->first_in_nextep_seq);
50801 +
50802 +               /* Clear the global non-periodic IN NAK handshake */
50803 +               dctl.d32 = 0;
50804 +               dctl.b.cgnpinnak = 1;
50805 +               DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50806 +
50807 +               /* Unmask EP Mismatch interrupt */
50808 +               gintmsk_data.d32 = 0;
50809 +               gintmsk_data.b.epmismatch = 1;
50810 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
50811 +
50812 +               core_if->start_predict = 0;
50813 +
50814 +       }
50815 +}
50816 +
50817 +/**
50818 + * Handler for the IN EP timeout handshake interrupt.
50819 + */
50820 +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
50821 +                                            const uint32_t epnum)
50822 +{
50823 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
50824 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
50825 +
50826 +#ifdef DEBUG
50827 +       deptsiz_data_t dieptsiz = {.d32 = 0 };
50828 +       uint32_t num = 0;
50829 +#endif
50830 +       dctl_data_t dctl = {.d32 = 0 };
50831 +       dwc_otg_pcd_ep_t *ep;
50832 +
50833 +       gintmsk_data_t intr_mask = {.d32 = 0 };
50834 +
50835 +       ep = get_in_ep(pcd, epnum);
50836 +
50837 +       /* Disable the NP Tx Fifo Empty Interrrupt */
50838 +       if (!core_if->dma_enable) {
50839 +               intr_mask.b.nptxfempty = 1;
50840 +               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
50841 +                                intr_mask.d32, 0);
50842 +       }
50843 +       /** @todo NGS Check EP type.
50844 +        * Implement for Periodic EPs */
50845 +       /*
50846 +        * Non-periodic EP
50847 +        */
50848 +       /* Enable the Global IN NAK Effective Interrupt */
50849 +       intr_mask.b.ginnakeff = 1;
50850 +       DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
50851 +
50852 +       /* Set Global IN NAK */
50853 +       dctl.b.sgnpinnak = 1;
50854 +       DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
50855 +
50856 +       ep->stopped = 1;
50857 +
50858 +#ifdef DEBUG
50859 +       dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
50860 +       DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
50861 +                   dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
50862 +#endif
50863 +
50864 +#ifdef DISABLE_PERIODIC_EP
50865 +       /*
50866 +        * Set the NAK bit for this EP to
50867 +        * start the disable process.
50868 +        */
50869 +       diepctl.d32 = 0;
50870 +       diepctl.b.snak = 1;
50871 +       DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
50872 +                        diepctl.d32);
50873 +       ep->disabling = 1;
50874 +       ep->stopped = 1;
50875 +#endif
50876 +}
50877 +
50878 +/**
50879 + * Handler for the IN EP NAK interrupt.
50880 + */
50881 +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
50882 +                                           const uint32_t epnum)
50883 +{
50884 +       /** @todo implement ISR */
50885 +       dwc_otg_core_if_t *core_if;
50886 +       diepmsk_data_t intr_mask = {.d32 = 0 };
50887 +
50888 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
50889 +       core_if = GET_CORE_IF(pcd);
50890 +       intr_mask.b.nak = 1;
50891 +
50892 +       if (core_if->multiproc_int_enable) {
50893 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50894 +                                diepeachintmsk[epnum], intr_mask.d32, 0);
50895 +       } else {
50896 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
50897 +                                intr_mask.d32, 0);
50898 +       }
50899 +
50900 +       return 1;
50901 +}
50902 +
50903 +/**
50904 + * Handler for the OUT EP Babble interrupt.
50905 + */
50906 +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
50907 +                                               const uint32_t epnum)
50908 +{
50909 +       /** @todo implement ISR */
50910 +       dwc_otg_core_if_t *core_if;
50911 +       doepmsk_data_t intr_mask = {.d32 = 0 };
50912 +
50913 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
50914 +                  "OUT EP Babble");
50915 +       core_if = GET_CORE_IF(pcd);
50916 +       intr_mask.b.babble = 1;
50917 +
50918 +       if (core_if->multiproc_int_enable) {
50919 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50920 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
50921 +       } else {
50922 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
50923 +                                intr_mask.d32, 0);
50924 +       }
50925 +
50926 +       return 1;
50927 +}
50928 +
50929 +/**
50930 + * Handler for the OUT EP NAK interrupt.
50931 + */
50932 +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
50933 +                                            const uint32_t epnum)
50934 +{
50935 +       /** @todo implement ISR */
50936 +       dwc_otg_core_if_t *core_if;
50937 +       doepmsk_data_t intr_mask = {.d32 = 0 };
50938 +
50939 +       DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
50940 +       core_if = GET_CORE_IF(pcd);
50941 +       intr_mask.b.nak = 1;
50942 +
50943 +       if (core_if->multiproc_int_enable) {
50944 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50945 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
50946 +       } else {
50947 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
50948 +                                intr_mask.d32, 0);
50949 +       }
50950 +
50951 +       return 1;
50952 +}
50953 +
50954 +/**
50955 + * Handler for the OUT EP NYET interrupt.
50956 + */
50957 +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
50958 +                                             const uint32_t epnum)
50959 +{
50960 +       /** @todo implement ISR */
50961 +       dwc_otg_core_if_t *core_if;
50962 +       doepmsk_data_t intr_mask = {.d32 = 0 };
50963 +
50964 +       DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
50965 +       core_if = GET_CORE_IF(pcd);
50966 +       intr_mask.b.nyet = 1;
50967 +
50968 +       if (core_if->multiproc_int_enable) {
50969 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
50970 +                                doepeachintmsk[epnum], intr_mask.d32, 0);
50971 +       } else {
50972 +               DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
50973 +                                intr_mask.d32, 0);
50974 +       }
50975 +
50976 +       return 1;
50977 +}
50978 +
50979 +/**
50980 + * This interrupt indicates that an IN EP has a pending Interrupt.
50981 + * The sequence for handling the IN EP interrupt is shown below:
50982 + * -#  Read the Device All Endpoint Interrupt register
50983 + * -#  Repeat the following for each IN EP interrupt bit set (from
50984 + *             LSB to MSB).
50985 + * -#  Read the Device Endpoint Interrupt (DIEPINTn) register
50986 + * -#  If "Transfer Complete" call the request complete function
50987 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
50988 + * -#  If "AHB Error Interrupt" log error
50989 + * -#  If "Time-out Handshake" log error
50990 + * -#  If "IN Token Received when TxFIFO Empty" write packet to Tx
50991 + *             FIFO.
50992 + * -#  If "IN Token EP Mismatch" (disable, this is handled by EP
50993 + *             Mismatch Interrupt)
50994 + */
50995 +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
50996 +{
50997 +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
50998 +do { \
50999 +               diepint_data_t diepint = {.d32=0}; \
51000 +               diepint.b.__intr = 1; \
51001 +               DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
51002 +               diepint.d32); \
51003 +} while (0)
51004 +
51005 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51006 +       dwc_otg_dev_if_t *dev_if = core_if->dev_if;
51007 +       diepint_data_t diepint = {.d32 = 0 };
51008 +       depctl_data_t depctl = {.d32 = 0 };
51009 +       uint32_t ep_intr;
51010 +       uint32_t epnum = 0;
51011 +       dwc_otg_pcd_ep_t *ep;
51012 +       dwc_ep_t *dwc_ep;
51013 +       gintmsk_data_t intr_mask = {.d32 = 0 };
51014 +
51015 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
51016 +
51017 +       /* Read in the device interrupt bits */
51018 +       ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
51019 +
51020 +       /* Service the Device IN interrupts for each endpoint */
51021 +       while (ep_intr) {
51022 +               if (ep_intr & 0x1) {
51023 +                       uint32_t empty_msk;
51024 +                       /* Get EP pointer */
51025 +                       ep = get_in_ep(pcd, epnum);
51026 +                       dwc_ep = &ep->dwc_ep;
51027 +
51028 +                       depctl.d32 =
51029 +                           DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51030 +                       empty_msk =
51031 +                           DWC_READ_REG32(&dev_if->
51032 +                                          dev_global_regs->dtknqr4_fifoemptymsk);
51033 +
51034 +                       DWC_DEBUGPL(DBG_PCDV,
51035 +                                   "IN EP INTERRUPT - %d\nepmty_msk - %8x  diepctl - %8x\n",
51036 +                                   epnum, empty_msk, depctl.d32);
51037 +
51038 +                       DWC_DEBUGPL(DBG_PCD,
51039 +                                   "EP%d-%s: type=%d, mps=%d\n",
51040 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51041 +                                   dwc_ep->type, dwc_ep->maxpacket);
51042 +
51043 +                       diepint.d32 =
51044 +                           dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
51045 +
51046 +                       DWC_DEBUGPL(DBG_PCDV,
51047 +                                   "EP %d Interrupt Register - 0x%x\n", epnum,
51048 +                                   diepint.d32);
51049 +                       /* Transfer complete */
51050 +                       if (diepint.b.xfercompl) {
51051 +                               /* Disable the NP Tx FIFO Empty
51052 +                                * Interrupt */
51053 +                               if (core_if->en_multiple_tx_fifo == 0) {
51054 +                                       intr_mask.b.nptxfempty = 1;
51055 +                                       DWC_MODIFY_REG32
51056 +                                           (&core_if->core_global_regs->gintmsk,
51057 +                                            intr_mask.d32, 0);
51058 +                               } else {
51059 +                                       /* Disable the Tx FIFO Empty Interrupt for this EP */
51060 +                                       uint32_t fifoemptymsk =
51061 +                                           0x1 << dwc_ep->num;
51062 +                                       DWC_MODIFY_REG32(&core_if->
51063 +                                                        dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
51064 +                                                        fifoemptymsk, 0);
51065 +                               }
51066 +                               /* Clear the bit in DIEPINTn for this interrupt */
51067 +                               CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
51068 +
51069 +                               /* Complete the transfer */
51070 +                               if (epnum == 0) {
51071 +                                       handle_ep0(pcd);
51072 +                               }
51073 +#ifdef DWC_EN_ISOC
51074 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51075 +                                       if (!ep->stopped)
51076 +                                               complete_iso_ep(pcd, ep);
51077 +                               }
51078 +#endif /* DWC_EN_ISOC */
51079 +#ifdef DWC_UTE_PER_IO
51080 +                               else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51081 +                                       if (!ep->stopped)
51082 +                                               complete_xiso_ep(ep);
51083 +                               }
51084 +#endif /* DWC_UTE_PER_IO */
51085 +                               else {
51086 +                                       if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&
51087 +                                                       dwc_ep->bInterval > 1) {
51088 +                                               dwc_ep->frame_num += dwc_ep->bInterval;
51089 +                                               if (dwc_ep->frame_num > 0x3FFF)
51090 +                                               {
51091 +                                                       dwc_ep->frm_overrun = 1;
51092 +                                                       dwc_ep->frame_num &= 0x3FFF;
51093 +                                               } else
51094 +                                                       dwc_ep->frm_overrun = 0;
51095 +                                       }
51096 +                                       complete_ep(ep);
51097 +                                       if(diepint.b.nak)
51098 +                                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51099 +                               }
51100 +                       }
51101 +                       /* Endpoint disable      */
51102 +                       if (diepint.b.epdisabled) {
51103 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
51104 +                                           epnum);
51105 +                               handle_in_ep_disable_intr(pcd, epnum);
51106 +
51107 +                               /* Clear the bit in DIEPINTn for this interrupt */
51108 +                               CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
51109 +                       }
51110 +                       /* AHB Error */
51111 +                       if (diepint.b.ahberr) {
51112 +                               DWC_ERROR("EP%d IN AHB Error\n", epnum);
51113 +                               /* Clear the bit in DIEPINTn for this interrupt */
51114 +                               CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
51115 +                       }
51116 +                       /* TimeOUT Handshake (non-ISOC IN EPs) */
51117 +                       if (diepint.b.timeout) {
51118 +                               DWC_ERROR("EP%d IN Time-out\n", epnum);
51119 +                               handle_in_ep_timeout_intr(pcd, epnum);
51120 +
51121 +                               CLEAR_IN_EP_INTR(core_if, epnum, timeout);
51122 +                       }
51123 +                       /** IN Token received with TxF Empty */
51124 +                       if (diepint.b.intktxfemp) {
51125 +                               DWC_DEBUGPL(DBG_ANY,
51126 +                                           "EP%d IN TKN TxFifo Empty\n",
51127 +                                           epnum);
51128 +                               if (!ep->stopped && epnum != 0) {
51129 +
51130 +                                       diepmsk_data_t diepmsk = {.d32 = 0 };
51131 +                                       diepmsk.b.intktxfemp = 1;
51132 +
51133 +                                       if (core_if->multiproc_int_enable) {
51134 +                                               DWC_MODIFY_REG32
51135 +                                                   (&dev_if->dev_global_regs->diepeachintmsk
51136 +                                                    [epnum], diepmsk.d32, 0);
51137 +                                       } else {
51138 +                                               DWC_MODIFY_REG32
51139 +                                                   (&dev_if->dev_global_regs->diepmsk,
51140 +                                                    diepmsk.d32, 0);
51141 +                                       }
51142 +                               } else if (core_if->dma_desc_enable
51143 +                                          && epnum == 0
51144 +                                          && pcd->ep0state ==
51145 +                                          EP0_OUT_STATUS_PHASE) {
51146 +                                       // EP0 IN set STALL
51147 +                                       depctl.d32 =
51148 +                                           DWC_READ_REG32(&dev_if->in_ep_regs
51149 +                                                          [epnum]->diepctl);
51150 +
51151 +                                       /* set the disable and stall bits */
51152 +                                       if (depctl.b.epena) {
51153 +                                               depctl.b.epdis = 1;
51154 +                                       }
51155 +                                       depctl.b.stall = 1;
51156 +                                       DWC_WRITE_REG32(&dev_if->in_ep_regs
51157 +                                                       [epnum]->diepctl,
51158 +                                                       depctl.d32);
51159 +                               }
51160 +                               CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
51161 +                       }
51162 +                       /** IN Token Received with EP mismatch */
51163 +                       if (diepint.b.intknepmis) {
51164 +                               DWC_DEBUGPL(DBG_ANY,
51165 +                                           "EP%d IN TKN EP Mismatch\n", epnum);
51166 +                               CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
51167 +                       }
51168 +                       /** IN Endpoint NAK Effective */
51169 +                       if (diepint.b.inepnakeff) {
51170 +                               DWC_DEBUGPL(DBG_ANY,
51171 +                                           "EP%d IN EP NAK Effective\n",
51172 +                                           epnum);
51173 +                               /* Periodic EP */
51174 +                               if (ep->disabling) {
51175 +                                       depctl.d32 = 0;
51176 +                                       depctl.b.snak = 1;
51177 +                                       depctl.b.epdis = 1;
51178 +                                       DWC_MODIFY_REG32(&dev_if->in_ep_regs
51179 +                                                        [epnum]->diepctl,
51180 +                                                        depctl.d32,
51181 +                                                        depctl.d32);
51182 +                               }
51183 +                               CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
51184 +
51185 +                       }
51186 +
51187 +                       /** IN EP Tx FIFO Empty Intr */
51188 +                       if (diepint.b.emptyintr) {
51189 +                               DWC_DEBUGPL(DBG_ANY,
51190 +                                           "EP%d Tx FIFO Empty Intr \n",
51191 +                                           epnum);
51192 +                               write_empty_tx_fifo(pcd, epnum);
51193 +
51194 +                               CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
51195 +
51196 +                       }
51197 +
51198 +                       /** IN EP BNA Intr */
51199 +                       if (diepint.b.bna) {
51200 +                               CLEAR_IN_EP_INTR(core_if, epnum, bna);
51201 +                               if (core_if->dma_desc_enable) {
51202 +#ifdef DWC_EN_ISOC
51203 +                                       if (dwc_ep->type ==
51204 +                                           DWC_OTG_EP_TYPE_ISOC) {
51205 +                                               /*
51206 +                                                * This checking is performed to prevent first "false" BNA
51207 +                                                * handling occuring right after reconnect
51208 +                                                */
51209 +                                               if (dwc_ep->next_frame !=
51210 +                                                   0xffffffff)
51211 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51212 +                                       } else
51213 +#endif                         /* DWC_EN_ISOC */
51214 +                                       {
51215 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51216 +                                       }
51217 +                               }
51218 +                       }
51219 +                       /* NAK Interrutp */
51220 +                       if (diepint.b.nak) {
51221 +                               DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
51222 +                                           epnum);
51223 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51224 +                                       depctl_data_t depctl;
51225 +                                       if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
51226 +                                               ep->dwc_ep.frame_num = core_if->frame_num;
51227 +                                               if (ep->dwc_ep.bInterval > 1) {
51228 +                                                       depctl.d32 = 0;
51229 +                                                       depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
51230 +                                                       if (ep->dwc_ep.frame_num & 0x1) {
51231 +                                                               depctl.b.setd1pid = 1;
51232 +                                                               depctl.b.setd0pid = 0;
51233 +                                                       } else {
51234 +                                                               depctl.b.setd0pid = 1;
51235 +                                                               depctl.b.setd1pid = 0;
51236 +                                                       }
51237 +                                                       DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
51238 +                                               }
51239 +                                               start_next_request(ep);
51240 +                                       }
51241 +                                       ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
51242 +                                       if (dwc_ep->frame_num > 0x3FFF) {
51243 +                                               dwc_ep->frm_overrun = 1;
51244 +                                               dwc_ep->frame_num &= 0x3FFF;
51245 +                                       } else
51246 +                                               dwc_ep->frm_overrun = 0;
51247 +                               }
51248 +
51249 +                               CLEAR_IN_EP_INTR(core_if, epnum, nak);
51250 +                       }
51251 +               }
51252 +               epnum++;
51253 +               ep_intr >>= 1;
51254 +       }
51255 +
51256 +       return 1;
51257 +#undef CLEAR_IN_EP_INTR
51258 +}
51259 +
51260 +/**
51261 + * This interrupt indicates that an OUT EP has a pending Interrupt.
51262 + * The sequence for handling the OUT EP interrupt is shown below:
51263 + * -#  Read the Device All Endpoint Interrupt register
51264 + * -#  Repeat the following for each OUT EP interrupt bit set (from
51265 + *             LSB to MSB).
51266 + * -#  Read the Device Endpoint Interrupt (DOEPINTn) register
51267 + * -#  If "Transfer Complete" call the request complete function
51268 + * -#  If "Endpoint Disabled" complete the EP disable procedure.
51269 + * -#  If "AHB Error Interrupt" log error
51270 + * -#  If "Setup Phase Done" process Setup Packet (See Standard USB
51271 + *             Command Processing)
51272 + */
51273 +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
51274 +{
51275 +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
51276 +do { \
51277 +               doepint_data_t doepint = {.d32=0}; \
51278 +               doepint.b.__intr = 1; \
51279 +               DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
51280 +               doepint.d32); \
51281 +} while (0)
51282 +
51283 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
51284 +       uint32_t ep_intr;
51285 +       doepint_data_t doepint = {.d32 = 0 };
51286 +       uint32_t epnum = 0;
51287 +       dwc_otg_pcd_ep_t *ep;
51288 +       dwc_ep_t *dwc_ep;
51289 +       dctl_data_t dctl = {.d32 = 0 };
51290 +       gintmsk_data_t gintmsk = {.d32 = 0 };
51291 +
51292 +
51293 +       DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
51294 +
51295 +       /* Read in the device interrupt bits */
51296 +       ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
51297 +
51298 +       while (ep_intr) {
51299 +               if (ep_intr & 0x1) {
51300 +                       /* Get EP pointer */
51301 +                       ep = get_out_ep(pcd, epnum);
51302 +                       dwc_ep = &ep->dwc_ep;
51303 +
51304 +#ifdef VERBOSE
51305 +                       DWC_DEBUGPL(DBG_PCDV,
51306 +                                   "EP%d-%s: type=%d, mps=%d\n",
51307 +                                   dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
51308 +                                   dwc_ep->type, dwc_ep->maxpacket);
51309 +#endif
51310 +                       doepint.d32 =
51311 +                           dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
51312 +                       /* Moved this interrupt upper due to core deffect of asserting
51313 +                        * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
51314 +                       if (doepint.b.stsphsercvd) {
51315 +                               deptsiz0_data_t deptsiz;
51316 +                               CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
51317 +                               deptsiz.d32 =
51318 +                                   DWC_READ_REG32(&core_if->dev_if->
51319 +                                                  out_ep_regs[0]->doeptsiz);
51320 +                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51321 +                                   && core_if->dma_enable
51322 +                                   && core_if->dma_desc_enable == 0
51323 +                                   && doepint.b.xfercompl
51324 +                                   && deptsiz.b.xfersize == 24) {
51325 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51326 +                                                         xfercompl);
51327 +                                       doepint.b.xfercompl = 0;
51328 +                                       ep0_out_start(core_if, pcd);
51329 +                               }
51330 +                               if ((core_if->dma_desc_enable) ||
51331 +                                   (core_if->dma_enable
51332 +                                    && core_if->snpsid >=
51333 +                                    OTG_CORE_REV_3_00a)) {
51334 +                                       do_setup_in_status_phase(pcd);
51335 +                               }
51336 +                       }
51337 +                       /* Transfer complete */
51338 +                       if (doepint.b.xfercompl) {
51339 +
51340 +                               if (epnum == 0) {
51341 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51342 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51343 +                                       if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
51344 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51345 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
51346 +                                                       doepint.d32);
51347 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
51348 +                                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
51349 +
51350 +                                               if (core_if->snpsid >= OTG_CORE_REV_3_00a
51351 +                                                       && core_if->dma_enable == 0) {
51352 +                                                       doepint_data_t doepint;
51353 +                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51354 +                                                                                                               out_ep_regs[0]->doepint);
51355 +                                                       if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
51356 +                                                               CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51357 +                                                               goto exit_xfercompl;
51358 +                                                       }
51359 +                                               }
51360 +                                               /* In case of DDMA  look at SR bit to go to the Data Stage */
51361 +                                               if (core_if->dma_desc_enable) {
51362 +                                                       dev_dma_desc_sts_t status = {.d32 = 0};
51363 +                                                       if (pcd->ep0state == EP0_IDLE) {
51364 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51365 +                                                                                       dev_if->setup_desc_index]->status.d32;
51366 +                                                               if(pcd->data_terminated) {
51367 +                                                                        pcd->data_terminated = 0;
51368 +                                                                        status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51369 +                                                                        dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
51370 +                                                               }
51371 +                                                               if (status.b.sr) {
51372 +                                                                       if (doepint.b.setup) {
51373 +                                                                               DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
51374 +                                                                               /* Already started data stage, clear setup */
51375 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51376 +                                                                               doepint.b.setup = 0;
51377 +                                                                               handle_ep0(pcd);
51378 +                                                                               /* Prepare for more setup packets */
51379 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51380 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51381 +                                                                                       ep0_out_start(core_if, pcd);
51382 +                                                                               }
51383 +
51384 +                                                                               goto exit_xfercompl;
51385 +                                                                       } else {
51386 +                                                                               /* Prepare for more setup packets */
51387 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51388 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51389 +                                                                               ep0_out_start(core_if, pcd);
51390 +                                                                       }
51391 +                                                               }
51392 +                                                       } else {
51393 +                                                               dwc_otg_pcd_request_t *req;
51394 +                                                               dev_dma_desc_sts_t status = {.d32 = 0};
51395 +                                                               diepint_data_t diepint0;
51396 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51397 +                                                                                                                       in_ep_regs[0]->diepint);
51398 +
51399 +                                                               if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
51400 +                                                                       DWC_ERROR("EP0 is stalled/disconnected\n");
51401 +                                                               }
51402 +
51403 +                                                               /* Clear IN xfercompl if set */
51404 +                                                               if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
51405 +                                                                       || pcd->ep0state == EP0_IN_DATA_PHASE)) {
51406 +                                                                       DWC_WRITE_REG32(&core_if->dev_if->
51407 +                                                                               in_ep_regs[0]->diepint, diepint0.d32);
51408 +                                                               }
51409 +
51410 +                                                               status.d32 = core_if->dev_if->setup_desc_addr[core_if->
51411 +                                                                       dev_if->setup_desc_index]->status.d32;
51412 +
51413 +                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
51414 +                                                                       && (pcd->ep0state == EP0_OUT_DATA_PHASE))
51415 +                                                                       status.d32 = core_if->dev_if->out_desc_addr->status.d32;
51416 +                                                               if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
51417 +                                                                       status.d32 = status.d32 = core_if->dev_if->
51418 +                                                                       out_desc_addr->status.d32;
51419 +
51420 +                                                               if (status.b.sr) {
51421 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51422 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51423 +                                                                       } else {
51424 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51425 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51426 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51427 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51428 +                                                                                               /* Read arrived setup packet from req->buf */
51429 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51430 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51431 +                                                                               }
51432 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51433 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51434 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51435 +                                                                               ep->dwc_ep.xfer_buff = 0;
51436 +                                                                               ep->dwc_ep.xfer_len = 0;
51437 +                                                                       }
51438 +                                                                       pcd->ep0state = EP0_IDLE;
51439 +                                                                       if (doepint.b.setup) {
51440 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51441 +                                                                               /* Data stage started, clear setup */
51442 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51443 +                                                                               doepint.b.setup = 0;
51444 +                                                                               handle_ep0(pcd);
51445 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51446 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51447 +                                                                                       ep0_out_start(core_if, pcd);
51448 +                                                                               }
51449 +
51450 +                                                                               goto exit_xfercompl;
51451 +                                                                       } else {
51452 +                                                                               /* Prepare for more setup packets */
51453 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51454 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51455 +                                                                               ep0_out_start(core_if, pcd);
51456 +                                                                       }
51457 +                                                               }
51458 +                                                       }
51459 +                                               }
51460 +                                               if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
51461 +                                                       && core_if->dma_desc_enable == 0) {
51462 +                                                       doepint_data_t doepint_temp = {.d32 = 0};
51463 +                                                       deptsiz0_data_t doeptsize0 = {.d32 = 0 };
51464 +                                                       doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51465 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doepint);
51466 +                                                       doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
51467 +                                                                                                                       out_ep_regs[ep->dwc_ep.num]->doeptsiz);
51468 +                                                       if (pcd->ep0state == EP0_IDLE) {
51469 +                                                               if (doepint_temp.b.sr) {
51470 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51471 +                                                               }
51472 +                                                                       doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51473 +                                                                                                                                       out_ep_regs[0]->doepint);
51474 +                                                                       if (doeptsize0.b.supcnt == 3) {
51475 +                                                                               DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
51476 +                                                                               ep->dwc_ep.stp_rollover = 1;
51477 +                                                                       }
51478 +                                                                       if (doepint.b.setup) {
51479 +retry:
51480 +                                                                               /* Already started data stage, clear setup */
51481 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51482 +                                                                               doepint.b.setup = 0;
51483 +                                                                               handle_ep0(pcd);
51484 +                                                                               ep->dwc_ep.stp_rollover = 0;
51485 +                                                                               /* Prepare for more setup packets */
51486 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
51487 +                                                                                       pcd->ep0state == EP0_IN_DATA_PHASE) {
51488 +                                                                                       ep0_out_start(core_if, pcd);
51489 +                                                                               }
51490 +                                                                               goto exit_xfercompl;
51491 +                                                                       } else {
51492 +                                                                               /* Prepare for more setup packets */
51493 +                                                                               DWC_DEBUGPL(DBG_ANY,
51494 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes\n");
51495 +                                                                               doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51496 +                                                                                                                                       out_ep_regs[0]->doepint);
51497 +                                                                               if(doepint.b.setup)
51498 +                                                                                       goto retry;
51499 +                                                                               ep0_out_start(core_if, pcd);
51500 +                                                                       }
51501 +                                                       } else {
51502 +                                                               dwc_otg_pcd_request_t *req;
51503 +                                                               diepint_data_t diepint0 = {.d32 = 0};
51504 +                                                               doepint_data_t doepint_temp = {.d32 = 0};
51505 +                                                               depctl_data_t diepctl0;
51506 +                                                               diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
51507 +                                                                                                                               in_ep_regs[0]->diepint);
51508 +                                                               diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
51509 +                                                                                                                               in_ep_regs[0]->diepctl);
51510 +
51511 +                                                               if (pcd->ep0state == EP0_IN_DATA_PHASE
51512 +                                                                       || pcd->ep0state == EP0_IN_STATUS_PHASE) {
51513 +                                                                       if (diepint0.b.xfercompl) {
51514 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51515 +                                                                                       in_ep_regs[0]->diepint, diepint0.d32);
51516 +                                                                       }
51517 +                                                                       if (diepctl0.b.epena) {
51518 +                                                                               diepint_data_t diepint = {.d32 = 0};
51519 +                                                                               diepctl0.b.snak = 1;
51520 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51521 +                                                                                                               in_ep_regs[0]->diepctl, diepctl0.d32);
51522 +                                                                               do {
51523 +                                                                                       dwc_udelay(10);
51524 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51525 +                                                                                               in_ep_regs[0]->diepint);
51526 +                                                                               } while (!diepint.b.inepnakeff);
51527 +                                                                               diepint.b.inepnakeff = 1;
51528 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->
51529 +                                                                                       in_ep_regs[0]->diepint, diepint.d32);
51530 +                                                                               diepctl0.d32 = 0;
51531 +                                                                               diepctl0.b.epdis = 1;
51532 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
51533 +                                                                                                               diepctl0.d32);
51534 +                                                                               do {
51535 +                                                                                       dwc_udelay(10);
51536 +                                                                                       diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
51537 +                                                                                               in_ep_regs[0]->diepint);
51538 +                                                                               } while (!diepint.b.epdisabled);
51539 +                                                                               diepint.b.epdisabled = 1;
51540 +                                                                               DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
51541 +                                                                                                                       diepint.d32);
51542 +                                                                       }
51543 +                                                               }
51544 +                                                               doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
51545 +                                                                                                                               out_ep_regs[ep->dwc_ep.num]->doepint);
51546 +                                                               if (doepint_temp.b.sr) {
51547 +                                                                       CLEAR_OUT_EP_INTR(core_if, epnum, sr);
51548 +                                                                       if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51549 +                                                                               DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
51550 +                                                                       } else {
51551 +                                                                               DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
51552 +                                                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51553 +                                                                               if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
51554 +                                                                                       pcd->ep0state == EP0_OUT_DATA_PHASE) {
51555 +                                                                                               /* Read arrived setup packet from req->buf */
51556 +                                                                                               dwc_memcpy(&pcd->setup_pkt->req,
51557 +                                                                                                       req->buf + ep->dwc_ep.xfer_count, 8);
51558 +                                                                               }
51559 +                                                                               req->actual = ep->dwc_ep.xfer_count;
51560 +                                                                               dwc_otg_request_done(ep, req, -ECONNRESET);
51561 +                                                                               ep->dwc_ep.start_xfer_buff = 0;
51562 +                                                                               ep->dwc_ep.xfer_buff = 0;
51563 +                                                                               ep->dwc_ep.xfer_len = 0;
51564 +                                                                       }
51565 +                                                                       pcd->ep0state = EP0_IDLE;
51566 +                                                                       if (doepint.b.setup) {
51567 +                                                                               DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
51568 +                                                                               /* Data stage started, clear setup */
51569 +                                                                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51570 +                                                                               doepint.b.setup = 0;
51571 +                                                                               handle_ep0(pcd);
51572 +                                                                               /* Prepare for setup packets if ep0in was enabled*/
51573 +                                                                               if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
51574 +                                                                                       ep0_out_start(core_if, pcd);
51575 +                                                                               }
51576 +                                                                               goto exit_xfercompl;
51577 +                                                                       } else {
51578 +                                                                               /* Prepare for more setup packets */
51579 +                                                                               DWC_DEBUGPL(DBG_PCDV,
51580 +                                                                                       "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
51581 +                                                                               ep0_out_start(core_if, pcd);
51582 +                                                                       }
51583 +                                                               }
51584 +                                                       }
51585 +                                               }
51586 +                                               if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
51587 +                                                       handle_ep0(pcd);
51588 +exit_xfercompl:
51589 +                                               DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
51590 +                                                       dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
51591 +                                       } else {
51592 +                                       if (core_if->dma_desc_enable == 0
51593 +                                           || pcd->ep0state != EP0_IDLE)
51594 +                                               handle_ep0(pcd);
51595 +                                       }
51596 +#ifdef DWC_EN_ISOC
51597 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51598 +                                       if (doepint.b.pktdrpsts == 0) {
51599 +                                               /* Clear the bit in DOEPINTn for this interrupt */
51600 +                                               CLEAR_OUT_EP_INTR(core_if,
51601 +                                                                 epnum,
51602 +                                                                 xfercompl);
51603 +                                               complete_iso_ep(pcd, ep);
51604 +                                       } else {
51605 +
51606 +                                               doepint_data_t doepint = {.d32 = 0 };
51607 +                                               doepint.b.xfercompl = 1;
51608 +                                               doepint.b.pktdrpsts = 1;
51609 +                                               DWC_WRITE_REG32
51610 +                                                   (&core_if->dev_if->out_ep_regs
51611 +                                                    [epnum]->doepint,
51612 +                                                    doepint.d32);
51613 +                                               if (handle_iso_out_pkt_dropped
51614 +                                                   (core_if, dwc_ep)) {
51615 +                                                       complete_iso_ep(pcd,
51616 +                                                                       ep);
51617 +                                               }
51618 +                                       }
51619 +#endif /* DWC_EN_ISOC */
51620 +#ifdef DWC_UTE_PER_IO
51621 +                               } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51622 +                                       CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
51623 +                                       if (!ep->stopped)
51624 +                                               complete_xiso_ep(ep);
51625 +#endif /* DWC_UTE_PER_IO */
51626 +                               } else {
51627 +                                       /* Clear the bit in DOEPINTn for this interrupt */
51628 +                                       CLEAR_OUT_EP_INTR(core_if, epnum,
51629 +                                                         xfercompl);
51630 +
51631 +                                       if (core_if->core_params->dev_out_nak) {
51632 +                                               DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
51633 +                                               pcd->core_if->ep_xfer_info[epnum].state = 0;
51634 +#ifdef DEBUG
51635 +                                               print_memory_payload(pcd, dwc_ep);
51636 +#endif
51637 +                                       }
51638 +                                       complete_ep(ep);
51639 +                               }
51640 +
51641 +                       }
51642 +
51643 +                       /* Endpoint disable      */
51644 +                       if (doepint.b.epdisabled) {
51645 +
51646 +                               /* Clear the bit in DOEPINTn for this interrupt */
51647 +                               CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
51648 +                               if (core_if->core_params->dev_out_nak) {
51649 +#ifdef DEBUG
51650 +                                       print_memory_payload(pcd, dwc_ep);
51651 +#endif
51652 +                                       /* In case of timeout condition */
51653 +                                       if (core_if->ep_xfer_info[epnum].state == 2) {
51654 +                                               dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51655 +                                                                               dev_global_regs->dctl);
51656 +                                               dctl.b.cgoutnak = 1;
51657 +                                               DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51658 +                                                                                                                               dctl.d32);
51659 +                                               /* Unmask goutnakeff interrupt which was masked
51660 +                                                * during handle nak out interrupt */
51661 +                                               gintmsk.b.goutnakeff = 1;
51662 +                                               DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
51663 +                                                                                                                               0, gintmsk.d32);
51664 +
51665 +                                               complete_ep(ep);
51666 +                                       }
51667 +                               }
51668 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
51669 +                               {
51670 +                                       dctl_data_t dctl;
51671 +                                       gintmsk_data_t intr_mask = {.d32 = 0};
51672 +                                       dwc_otg_pcd_request_t *req = 0;
51673 +
51674 +                                       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51675 +                                               dev_global_regs->dctl);
51676 +                                       dctl.b.cgoutnak = 1;
51677 +                                       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
51678 +                                               dctl.d32);
51679 +
51680 +                                       intr_mask.d32 = 0;
51681 +                                       intr_mask.b.incomplisoout = 1;
51682 +
51683 +                                       /* Get any pending requests */
51684 +                                       if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
51685 +                                               req = DWC_CIRCLEQ_FIRST(&ep->queue);
51686 +                                               if (!req) {
51687 +                                                       DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
51688 +                                               } else {
51689 +                                                       dwc_otg_request_done(ep, req, 0);
51690 +                                                       start_next_request(ep);
51691 +                                               }
51692 +                                       } else {
51693 +                                               DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
51694 +                                       }
51695 +                               }
51696 +                       }
51697 +                       /* AHB Error */
51698 +                       if (doepint.b.ahberr) {
51699 +                               DWC_ERROR("EP%d OUT AHB Error\n", epnum);
51700 +                               DWC_ERROR("EP%d DEPDMA=0x%08x \n",
51701 +                                         epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
51702 +                               CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
51703 +                       }
51704 +                       /* Setup Phase Done (contorl EPs) */
51705 +                       if (doepint.b.setup) {
51706 +#ifdef DEBUG_EP0
51707 +                               DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
51708 +#endif
51709 +                               CLEAR_OUT_EP_INTR(core_if, epnum, setup);
51710 +
51711 +                               handle_ep0(pcd);
51712 +                       }
51713 +
51714 +                       /** OUT EP BNA Intr */
51715 +                       if (doepint.b.bna) {
51716 +                               CLEAR_OUT_EP_INTR(core_if, epnum, bna);
51717 +                               if (core_if->dma_desc_enable) {
51718 +#ifdef DWC_EN_ISOC
51719 +                                       if (dwc_ep->type ==
51720 +                                           DWC_OTG_EP_TYPE_ISOC) {
51721 +                                               /*
51722 +                                                * This checking is performed to prevent first "false" BNA
51723 +                                                * handling occuring right after reconnect
51724 +                                                */
51725 +                                               if (dwc_ep->next_frame !=
51726 +                                                   0xffffffff)
51727 +                                                       dwc_otg_pcd_handle_iso_bna(ep);
51728 +                                       } else
51729 +#endif                         /* DWC_EN_ISOC */
51730 +                                       {
51731 +                                               dwc_otg_pcd_handle_noniso_bna(ep);
51732 +                                       }
51733 +                               }
51734 +                       }
51735 +                       /* Babble Interrupt */
51736 +                       if (doepint.b.babble) {
51737 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
51738 +                                           epnum);
51739 +                               handle_out_ep_babble_intr(pcd, epnum);
51740 +
51741 +                               CLEAR_OUT_EP_INTR(core_if, epnum, babble);
51742 +                       }
51743 +                       if (doepint.b.outtknepdis) {
51744 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
51745 +                                       disabled\n",epnum);
51746 +                               if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51747 +                                       doepmsk_data_t doepmsk = {.d32 = 0};
51748 +                                       ep->dwc_ep.frame_num = core_if->frame_num;
51749 +                                       if (ep->dwc_ep.bInterval > 1) {
51750 +                                               depctl_data_t depctl;
51751 +                                               depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
51752 +                                                                                                       out_ep_regs[epnum]->doepctl);
51753 +                                               if (ep->dwc_ep.frame_num & 0x1) {
51754 +                                                       depctl.b.setd1pid = 1;
51755 +                                                       depctl.b.setd0pid = 0;
51756 +                                               } else {
51757 +                                                       depctl.b.setd0pid = 1;
51758 +                                                       depctl.b.setd1pid = 0;
51759 +                                               }
51760 +                                               DWC_WRITE_REG32(&core_if->dev_if->
51761 +                                                                               out_ep_regs[epnum]->doepctl, depctl.d32);
51762 +                                       }
51763 +                                       start_next_request(ep);
51764 +                                       doepmsk.b.outtknepdis = 1;
51765 +                                       DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
51766 +                                                                doepmsk.d32, 0);
51767 +                               }
51768 +                               CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
51769 +                       }
51770 +
51771 +                       /* NAK Interrutp */
51772 +                       if (doepint.b.nak) {
51773 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
51774 +                               handle_out_ep_nak_intr(pcd, epnum);
51775 +
51776 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nak);
51777 +                       }
51778 +                       /* NYET Interrutp */
51779 +                       if (doepint.b.nyet) {
51780 +                               DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
51781 +                               handle_out_ep_nyet_intr(pcd, epnum);
51782 +
51783 +                               CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
51784 +                       }
51785 +               }
51786 +
51787 +               epnum++;
51788 +               ep_intr >>= 1;
51789 +       }
51790 +
51791 +       return 1;
51792 +
51793 +#undef CLEAR_OUT_EP_INTR
51794 +}
51795 +static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
51796 +{
51797 +       int retval = 0;
51798 +       if(!frm_overrun && curr_fr >= trgt_fr)
51799 +               retval = 1;
51800 +       else if (frm_overrun
51801 +                && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
51802 +               retval = 1;
51803 +       return retval;
51804 +}
51805 +/**
51806 + * Incomplete ISO IN Transfer Interrupt.
51807 + * This interrupt indicates one of the following conditions occurred
51808 + * while transmitting an ISOC transaction.
51809 + * - Corrupted IN Token for ISOC EP.
51810 + * - Packet not complete in FIFO.
51811 + * The follow actions will be taken:
51812 + *     -#      Determine the EP
51813 + *     -#      Set incomplete flag in dwc_ep structure
51814 + *     -#      Disable EP; when "Endpoint Disabled" interrupt is received
51815 + *             Flush FIFO
51816 + */
51817 +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
51818 +{
51819 +       gintsts_data_t gintsts;
51820 +
51821 +#ifdef DWC_EN_ISOC
51822 +       dwc_otg_dev_if_t *dev_if;
51823 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51824 +       depctl_data_t depctl = {.d32 = 0 };
51825 +       dsts_data_t dsts = {.d32 = 0 };
51826 +       dwc_ep_t *dwc_ep;
51827 +       int i;
51828 +
51829 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51830 +
51831 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
51832 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
51833 +               if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51834 +                       deptsiz.d32 =
51835 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
51836 +                       depctl.d32 =
51837 +                           DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51838 +
51839 +                       if (depctl.b.epdis && deptsiz.d32) {
51840 +                               set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
51841 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
51842 +                                       dwc_ep->cur_pkt = 0;
51843 +                                       dwc_ep->proc_buf_num =
51844 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
51845 +
51846 +                                       if (dwc_ep->proc_buf_num) {
51847 +                                               dwc_ep->cur_pkt_addr =
51848 +                                                   dwc_ep->xfer_buff1;
51849 +                                               dwc_ep->cur_pkt_dma_addr =
51850 +                                                   dwc_ep->dma_addr1;
51851 +                                       } else {
51852 +                                               dwc_ep->cur_pkt_addr =
51853 +                                                   dwc_ep->xfer_buff0;
51854 +                                               dwc_ep->cur_pkt_dma_addr =
51855 +                                                   dwc_ep->dma_addr0;
51856 +                                       }
51857 +
51858 +                               }
51859 +
51860 +                               dsts.d32 =
51861 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
51862 +                                                  dev_global_regs->dsts);
51863 +                               dwc_ep->next_frame = dsts.b.soffn;
51864 +
51865 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
51866 +                                                                 (pcd),
51867 +                                                                 dwc_ep);
51868 +                       }
51869 +               }
51870 +       }
51871 +
51872 +#else
51873 +       depctl_data_t depctl = {.d32 = 0 };
51874 +       dwc_ep_t *dwc_ep;
51875 +       dwc_otg_dev_if_t *dev_if;
51876 +       int i;
51877 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51878 +
51879 +       DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
51880 +
51881 +       for (i = 1; i <= dev_if->num_in_eps; ++i) {
51882 +               dwc_ep = &pcd->in_ep[i-1].dwc_ep;
51883 +               depctl.d32 =
51884 +                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51885 +               if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
51886 +                       if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,
51887 +                                                       dwc_ep->frm_overrun))
51888 +                       {
51889 +                               depctl.d32 =
51890 +                                       DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
51891 +                               depctl.b.snak = 1;
51892 +                               depctl.b.epdis = 1;
51893 +                               DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
51894 +                       }
51895 +               }
51896 +       }
51897 +
51898 +       /*intr_mask.b.incomplisoin = 1;
51899 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
51900 +                        intr_mask.d32, 0);      */
51901 +#endif                         //DWC_EN_ISOC
51902 +
51903 +       /* Clear interrupt */
51904 +       gintsts.d32 = 0;
51905 +       gintsts.b.incomplisoin = 1;
51906 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
51907 +                       gintsts.d32);
51908 +
51909 +       return 1;
51910 +}
51911 +
51912 +/**
51913 + * Incomplete ISO OUT Transfer Interrupt.
51914 + *
51915 + * This interrupt indicates that the core has dropped an ISO OUT
51916 + * packet. The following conditions can be the cause:
51917 + * - FIFO Full, the entire packet would not fit in the FIFO.
51918 + * - CRC Error
51919 + * - Corrupted Token
51920 + * The follow actions will be taken:
51921 + *     -#      Determine the EP
51922 + *     -#      Set incomplete flag in dwc_ep structure
51923 + *     -#      Read any data from the FIFO
51924 + *     -#      Disable EP. When "Endpoint Disabled" interrupt is received
51925 + *             re-enable EP.
51926 + */
51927 +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
51928 +{
51929 +
51930 +       gintsts_data_t gintsts;
51931 +
51932 +#ifdef DWC_EN_ISOC
51933 +       dwc_otg_dev_if_t *dev_if;
51934 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51935 +       depctl_data_t depctl = {.d32 = 0 };
51936 +       dsts_data_t dsts = {.d32 = 0 };
51937 +       dwc_ep_t *dwc_ep;
51938 +       int i;
51939 +
51940 +       dev_if = GET_CORE_IF(pcd)->dev_if;
51941 +
51942 +       for (i = 1; i <= dev_if->num_out_eps; ++i) {
51943 +               dwc_ep = &pcd->in_ep[i].dwc_ep;
51944 +               if (pcd->out_ep[i].dwc_ep.active &&
51945 +                   pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
51946 +                       deptsiz.d32 =
51947 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
51948 +                       depctl.d32 =
51949 +                           DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
51950 +
51951 +                       if (depctl.b.epdis && deptsiz.d32) {
51952 +                               set_current_pkt_info(GET_CORE_IF(pcd),
51953 +                                                    &pcd->out_ep[i].dwc_ep);
51954 +                               if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
51955 +                                       dwc_ep->cur_pkt = 0;
51956 +                                       dwc_ep->proc_buf_num =
51957 +                                           (dwc_ep->proc_buf_num ^ 1) & 0x1;
51958 +
51959 +                                       if (dwc_ep->proc_buf_num) {
51960 +                                               dwc_ep->cur_pkt_addr =
51961 +                                                   dwc_ep->xfer_buff1;
51962 +                                               dwc_ep->cur_pkt_dma_addr =
51963 +                                                   dwc_ep->dma_addr1;
51964 +                                       } else {
51965 +                                               dwc_ep->cur_pkt_addr =
51966 +                                                   dwc_ep->xfer_buff0;
51967 +                                               dwc_ep->cur_pkt_dma_addr =
51968 +                                                   dwc_ep->dma_addr0;
51969 +                                       }
51970 +
51971 +                               }
51972 +
51973 +                               dsts.d32 =
51974 +                                   DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
51975 +                                                  dev_global_regs->dsts);
51976 +                               dwc_ep->next_frame = dsts.b.soffn;
51977 +
51978 +                               dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
51979 +                                                                 (pcd),
51980 +                                                                 dwc_ep);
51981 +                       }
51982 +               }
51983 +       }
51984 +#else
51985 +       /** @todo implement ISR */
51986 +       gintmsk_data_t intr_mask = {.d32 = 0 };
51987 +       dwc_otg_core_if_t *core_if;
51988 +       deptsiz_data_t deptsiz = {.d32 = 0 };
51989 +       depctl_data_t depctl = {.d32 = 0 };
51990 +       dctl_data_t dctl = {.d32 = 0 };
51991 +       dwc_ep_t *dwc_ep = NULL;
51992 +       int i;
51993 +       core_if = GET_CORE_IF(pcd);
51994 +
51995 +       for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
51996 +               dwc_ep = &pcd->out_ep[i].dwc_ep;
51997 +               depctl.d32 =
51998 +                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
51999 +               if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
52000 +                       core_if->dev_if->isoc_ep = dwc_ep;
52001 +                       deptsiz.d32 =
52002 +                                       DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
52003 +                               break;
52004 +               }
52005 +       }
52006 +       dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
52007 +       gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
52008 +       intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
52009 +
52010 +       if (!intr_mask.b.goutnakeff) {
52011 +               /* Unmask it */
52012 +               intr_mask.b.goutnakeff = 1;
52013 +               DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
52014 +       }
52015 +       if (!gintsts.b.goutnakeff) {
52016 +               dctl.b.sgoutnak = 1;
52017 +       }
52018 +       DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
52019 +
52020 +       depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
52021 +       if (depctl.b.epena) {
52022 +               depctl.b.epdis = 1;
52023 +               depctl.b.snak = 1;
52024 +       }
52025 +       DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
52026 +
52027 +       intr_mask.d32 = 0;
52028 +       intr_mask.b.incomplisoout = 1;
52029 +
52030 +#endif /* DWC_EN_ISOC */
52031 +
52032 +       /* Clear interrupt */
52033 +       gintsts.d32 = 0;
52034 +       gintsts.b.incomplisoout = 1;
52035 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52036 +                       gintsts.d32);
52037 +
52038 +       return 1;
52039 +}
52040 +
52041 +/**
52042 + * This function handles the Global IN NAK Effective interrupt.
52043 + *
52044 + */
52045 +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
52046 +{
52047 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52048 +       depctl_data_t diepctl = {.d32 = 0 };
52049 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52050 +       gintsts_data_t gintsts;
52051 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52052 +       int i;
52053 +
52054 +       DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
52055 +
52056 +       /* Disable all active IN EPs */
52057 +       for (i = 0; i <= dev_if->num_in_eps; i++) {
52058 +               diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
52059 +               if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
52060 +                       if (core_if->start_predict > 0)
52061 +                               core_if->start_predict++;
52062 +                       diepctl.b.epdis = 1;
52063 +                       diepctl.b.snak = 1;
52064 +                       DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
52065 +               }
52066 +       }
52067 +
52068 +
52069 +       /* Disable the Global IN NAK Effective Interrupt */
52070 +       intr_mask.b.ginnakeff = 1;
52071 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52072 +                        intr_mask.d32, 0);
52073 +
52074 +       /* Clear interrupt */
52075 +       gintsts.d32 = 0;
52076 +       gintsts.b.ginnakeff = 1;
52077 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52078 +                       gintsts.d32);
52079 +
52080 +       return 1;
52081 +}
52082 +
52083 +/**
52084 + * OUT NAK Effective.
52085 + *
52086 + */
52087 +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
52088 +{
52089 +       dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
52090 +       gintmsk_data_t intr_mask = {.d32 = 0 };
52091 +       gintsts_data_t gintsts;
52092 +       depctl_data_t doepctl;
52093 +       int i;
52094 +
52095 +       /* Disable the Global OUT NAK Effective Interrupt */
52096 +       intr_mask.b.goutnakeff = 1;
52097 +       DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
52098 +               intr_mask.d32, 0);
52099 +
52100 +       /* If DEV OUT NAK enabled*/
52101 +       if (pcd->core_if->core_params->dev_out_nak) {
52102 +               /* Run over all out endpoints to determine the ep number on
52103 +                * which the timeout has happened
52104 +                */
52105 +               for (i = 0; i <= dev_if->num_out_eps; i++) {
52106 +                       if ( pcd->core_if->ep_xfer_info[i].state == 2 )
52107 +                               break;
52108 +               }
52109 +               if (i > dev_if->num_out_eps) {
52110 +                       dctl_data_t dctl;
52111 +                       dctl.d32 =
52112 +                           DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
52113 +                       dctl.b.cgoutnak = 1;
52114 +                       DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
52115 +                               dctl.d32);
52116 +                       goto out;
52117 +               }
52118 +
52119 +               /* Disable the endpoint */
52120 +               doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
52121 +               if (doepctl.b.epena) {
52122 +                       doepctl.b.epdis = 1;
52123 +                       doepctl.b.snak = 1;
52124 +               }
52125 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
52126 +               return 1;
52127 +       }
52128 +       /* We come here from Incomplete ISO OUT handler */
52129 +       if (dev_if->isoc_ep) {
52130 +               dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
52131 +               uint32_t epnum = dwc_ep->num;
52132 +               doepint_data_t doepint;
52133 +               doepint.d32 =
52134 +                   DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
52135 +               dev_if->isoc_ep = NULL;
52136 +               doepctl.d32 =
52137 +                   DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
52138 +               DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
52139 +               if (doepctl.b.epena) {
52140 +                       doepctl.b.epdis = 1;
52141 +                       doepctl.b.snak = 1;
52142 +               }
52143 +               DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
52144 +                               doepctl.d32);
52145 +               return 1;
52146 +       } else
52147 +               DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
52148 +                          "Global OUT NAK Effective\n");
52149 +
52150 +out:
52151 +       /* Clear interrupt */
52152 +       gintsts.d32 = 0;
52153 +       gintsts.b.goutnakeff = 1;
52154 +       DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
52155 +                       gintsts.d32);
52156 +
52157 +       return 1;
52158 +}
52159 +
52160 +/**
52161 + * PCD interrupt handler.
52162 + *
52163 + * The PCD handles the device interrupts.  Many conditions can cause a
52164 + * device interrupt. When an interrupt occurs, the device interrupt
52165 + * service routine determines the cause of the interrupt and
52166 + * dispatches handling to the appropriate function. These interrupt
52167 + * handling functions are described below.
52168 + *
52169 + * All interrupt registers are processed from LSB to MSB.
52170 + *
52171 + */
52172 +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
52173 +{
52174 +       dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
52175 +#ifdef VERBOSE
52176 +       dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
52177 +#endif
52178 +       gintsts_data_t gintr_status;
52179 +       int32_t retval = 0;
52180 +
52181 +       /* Exit from ISR if core is hibernated */
52182 +       if (core_if->hibernation_suspend == 1) {
52183 +               return retval;
52184 +       }
52185 +#ifdef VERBOSE
52186 +       DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x  gintmsk=%08x\n",
52187 +                   __func__,
52188 +                   DWC_READ_REG32(&global_regs->gintsts),
52189 +                   DWC_READ_REG32(&global_regs->gintmsk));
52190 +#endif
52191 +
52192 +       if (dwc_otg_is_device_mode(core_if)) {
52193 +               DWC_SPINLOCK(pcd->lock);
52194 +#ifdef VERBOSE
52195 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x  gintmsk=%08x\n",
52196 +                           __func__,
52197 +                           DWC_READ_REG32(&global_regs->gintsts),
52198 +                           DWC_READ_REG32(&global_regs->gintmsk));
52199 +#endif
52200 +
52201 +               gintr_status.d32 = dwc_otg_read_core_intr(core_if);
52202 +
52203 +               DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
52204 +                           __func__, gintr_status.d32);
52205 +
52206 +               if (gintr_status.b.sofintr) {
52207 +                       retval |= dwc_otg_pcd_handle_sof_intr(pcd);
52208 +               }
52209 +               if (gintr_status.b.rxstsqlvl) {
52210 +                       retval |=
52211 +                           dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
52212 +               }
52213 +               if (gintr_status.b.nptxfempty) {
52214 +                       retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
52215 +               }
52216 +               if (gintr_status.b.goutnakeff) {
52217 +                       retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
52218 +               }
52219 +               if (gintr_status.b.i2cintr) {
52220 +                       retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
52221 +               }
52222 +               if (gintr_status.b.erlysuspend) {
52223 +                       retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
52224 +               }
52225 +               if (gintr_status.b.usbreset) {
52226 +                       retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
52227 +               }
52228 +               if (gintr_status.b.enumdone) {
52229 +                       retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
52230 +               }
52231 +               if (gintr_status.b.isooutdrop) {
52232 +                       retval |=
52233 +                           dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
52234 +                           (pcd);
52235 +               }
52236 +               if (gintr_status.b.eopframe) {
52237 +                       retval |=
52238 +                           dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
52239 +               }
52240 +               if (gintr_status.b.inepint) {
52241 +                       if (!core_if->multiproc_int_enable) {
52242 +                               retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52243 +                       }
52244 +               }
52245 +               if (gintr_status.b.outepintr) {
52246 +                       if (!core_if->multiproc_int_enable) {
52247 +                               retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52248 +                       }
52249 +               }
52250 +               if (gintr_status.b.epmismatch) {
52251 +                       retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
52252 +               }
52253 +               if (gintr_status.b.fetsusp) {
52254 +                       retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
52255 +               }
52256 +               if (gintr_status.b.ginnakeff) {
52257 +                       retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
52258 +               }
52259 +               if (gintr_status.b.incomplisoin) {
52260 +                       retval |=
52261 +                           dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
52262 +               }
52263 +               if (gintr_status.b.incomplisoout) {
52264 +                       retval |=
52265 +                           dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
52266 +               }
52267 +
52268 +               /* In MPI mode Device Endpoints interrupts are asserted
52269 +                * without setting outepintr and inepint bits set, so these
52270 +                * Interrupt handlers are called without checking these bit-fields
52271 +                */
52272 +               if (core_if->multiproc_int_enable) {
52273 +                       retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
52274 +                       retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
52275 +               }
52276 +#ifdef VERBOSE
52277 +               DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
52278 +                           DWC_READ_REG32(&global_regs->gintsts));
52279 +#endif
52280 +               DWC_SPINUNLOCK(pcd->lock);
52281 +       }
52282 +       return retval;
52283 +}
52284 +
52285 +#endif /* DWC_HOST_ONLY */
52286 --- /dev/null
52287 +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
52288 @@ -0,0 +1,1358 @@
52289 + /* ==========================================================================
52290 +  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
52291 +  * $Revision: #21 $
52292 +  * $Date: 2012/08/10 $
52293 +  * $Change: 2047372 $
52294 +  *
52295 +  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
52296 +  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
52297 +  * otherwise expressly agreed to in writing between Synopsys and you.
52298 +  *
52299 +  * The Software IS NOT an item of Licensed Software or Licensed Product under
52300 +  * any End User Software License Agreement or Agreement for Licensed Product
52301 +  * with Synopsys or any supplement thereto. You are permitted to use and
52302 +  * redistribute this Software in source and binary forms, with or without
52303 +  * modification, provided that redistributions of source code must retain this
52304 +  * notice. You may not view, use, disclose, copy or distribute this file or
52305 +  * any information contained herein except pursuant to this license grant from
52306 +  * Synopsys. If you do not agree with this notice, including the disclaimer
52307 +  * below, then you are not authorized to use the Software.
52308 +  *
52309 +  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
52310 +  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52311 +  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52312 +  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
52313 +  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52314 +  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
52315 +  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
52316 +  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52317 +  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52318 +  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
52319 +  * DAMAGE.
52320 +  * ========================================================================== */
52321 +#ifndef DWC_HOST_ONLY
52322 +
52323 +/** @file
52324 + * This file implements the Peripheral Controller Driver.
52325 + *
52326 + * The Peripheral Controller Driver (PCD) is responsible for
52327 + * translating requests from the Function Driver into the appropriate
52328 + * actions on the DWC_otg controller. It isolates the Function Driver
52329 + * from the specifics of the controller by providing an API to the
52330 + * Function Driver.
52331 + *
52332 + * The Peripheral Controller Driver for Linux will implement the
52333 + * Gadget API, so that the existing Gadget drivers can be used.
52334 + * (Gadget Driver is the Linux terminology for a Function Driver.)
52335 + *
52336 + * The Linux Gadget API is defined in the header file
52337 + * <code><linux/usb_gadget.h></code>.  The USB EP operations API is
52338 + * defined in the structure <code>usb_ep_ops</code> and the USB
52339 + * Controller API is defined in the structure
52340 + * <code>usb_gadget_ops</code>.
52341 + *
52342 + */
52343 +
52344 +#include "dwc_otg_os_dep.h"
52345 +#include "dwc_otg_pcd_if.h"
52346 +#include "dwc_otg_pcd.h"
52347 +#include "dwc_otg_driver.h"
52348 +#include "dwc_otg_dbg.h"
52349 +
52350 +static struct gadget_wrapper {
52351 +       dwc_otg_pcd_t *pcd;
52352 +
52353 +       struct usb_gadget gadget;
52354 +       struct usb_gadget_driver *driver;
52355 +
52356 +       struct usb_ep ep0;
52357 +       struct usb_ep in_ep[16];
52358 +       struct usb_ep out_ep[16];
52359 +
52360 +} *gadget_wrapper;
52361 +
52362 +/* Display the contents of the buffer */
52363 +extern void dump_msg(const u8 * buf, unsigned int length);
52364 +/**
52365 + * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
52366 + * if the endpoint is not found
52367 + */
52368 +static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
52369 +{
52370 +       int i;
52371 +       if (pcd->ep0.priv == handle) {
52372 +               return &pcd->ep0;
52373 +       }
52374 +
52375 +       for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
52376 +               if (pcd->in_ep[i].priv == handle)
52377 +                       return &pcd->in_ep[i];
52378 +               if (pcd->out_ep[i].priv == handle)
52379 +                       return &pcd->out_ep[i];
52380 +       }
52381 +
52382 +       return NULL;
52383 +}
52384 +
52385 +/* USB Endpoint Operations */
52386 +/*
52387 + * The following sections briefly describe the behavior of the Gadget
52388 + * API endpoint operations implemented in the DWC_otg driver
52389 + * software. Detailed descriptions of the generic behavior of each of
52390 + * these functions can be found in the Linux header file
52391 + * include/linux/usb_gadget.h.
52392 + *
52393 + * The Gadget API provides wrapper functions for each of the function
52394 + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
52395 + * function, which then calls the underlying PCD function. The
52396 + * following sections are named according to the wrapper
52397 + * functions. Within each section, the corresponding DWC_otg PCD
52398 + * function name is specified.
52399 + *
52400 + */
52401 +
52402 +/**
52403 + * This function is called by the Gadget Driver for each EP to be
52404 + * configured for the current configuration (SET_CONFIGURATION).
52405 + *
52406 + * This function initializes the dwc_otg_ep_t data structure, and then
52407 + * calls dwc_otg_ep_activate.
52408 + */
52409 +static int ep_enable(struct usb_ep *usb_ep,
52410 +                    const struct usb_endpoint_descriptor *ep_desc)
52411 +{
52412 +       int retval;
52413 +
52414 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
52415 +
52416 +       if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
52417 +               DWC_WARN("%s, bad ep or descriptor\n", __func__);
52418 +               return -EINVAL;
52419 +       }
52420 +       if (usb_ep == &gadget_wrapper->ep0) {
52421 +               DWC_WARN("%s, bad ep(0)\n", __func__);
52422 +               return -EINVAL;
52423 +       }
52424 +
52425 +       /* Check FIFO size? */
52426 +       if (!ep_desc->wMaxPacketSize) {
52427 +               DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
52428 +               return -ERANGE;
52429 +       }
52430 +
52431 +       if (!gadget_wrapper->driver ||
52432 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52433 +               DWC_WARN("%s, bogus device state\n", __func__);
52434 +               return -ESHUTDOWN;
52435 +       }
52436 +
52437 +       /* Delete after check - MAS */
52438 +#if 0
52439 +       nat = (uint32_t) ep_desc->wMaxPacketSize;
52440 +       printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
52441 +       nat = (nat >> 11) & 0x03;
52442 +       printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
52443 +#endif
52444 +       retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
52445 +                                      (const uint8_t *)ep_desc,
52446 +                                      (void *)usb_ep);
52447 +       if (retval) {
52448 +               DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
52449 +               return -EINVAL;
52450 +       }
52451 +
52452 +       usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
52453 +
52454 +       return 0;
52455 +}
52456 +
52457 +/**
52458 + * This function is called when an EP is disabled due to disconnect or
52459 + * change in configuration. Any pending requests will terminate with a
52460 + * status of -ESHUTDOWN.
52461 + *
52462 + * This function modifies the dwc_otg_ep_t data structure for this EP,
52463 + * and then calls dwc_otg_ep_deactivate.
52464 + */
52465 +static int ep_disable(struct usb_ep *usb_ep)
52466 +{
52467 +       int retval;
52468 +
52469 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
52470 +       if (!usb_ep) {
52471 +               DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
52472 +                           usb_ep ? usb_ep->name : NULL);
52473 +               return -EINVAL;
52474 +       }
52475 +
52476 +       retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
52477 +       if (retval) {
52478 +               retval = -EINVAL;
52479 +       }
52480 +
52481 +       return retval;
52482 +}
52483 +
52484 +/**
52485 + * This function allocates a request object to use with the specified
52486 + * endpoint.
52487 + *
52488 + * @param ep The endpoint to be used with with the request
52489 + * @param gfp_flags the GFP_* flags to use.
52490 + */
52491 +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
52492 +                                                    gfp_t gfp_flags)
52493 +{
52494 +       struct usb_request *usb_req;
52495 +
52496 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
52497 +       if (0 == ep) {
52498 +               DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
52499 +               return 0;
52500 +       }
52501 +       usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
52502 +       if (0 == usb_req) {
52503 +               DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
52504 +               return 0;
52505 +       }
52506 +       memset(usb_req, 0, sizeof(*usb_req));
52507 +       usb_req->dma = DWC_DMA_ADDR_INVALID;
52508 +
52509 +       return usb_req;
52510 +}
52511 +
52512 +/**
52513 + * This function frees a request object.
52514 + *
52515 + * @param ep The endpoint associated with the request
52516 + * @param req The request being freed
52517 + */
52518 +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
52519 +{
52520 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
52521 +
52522 +       if (0 == ep || 0 == req) {
52523 +               DWC_WARN("%s() %s\n", __func__,
52524 +                        "Invalid ep or req argument!\n");
52525 +               return;
52526 +       }
52527 +
52528 +       kfree(req);
52529 +}
52530 +
52531 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52532 +/**
52533 + * This function allocates an I/O buffer to be used for a transfer
52534 + * to/from the specified endpoint.
52535 + *
52536 + * @param usb_ep The endpoint to be used with with the request
52537 + * @param bytes The desired number of bytes for the buffer
52538 + * @param dma Pointer to the buffer's DMA address; must be valid
52539 + * @param gfp_flags the GFP_* flags to use.
52540 + * @return address of a new buffer or null is buffer could not be allocated.
52541 + */
52542 +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
52543 +                                     dma_addr_t * dma, gfp_t gfp_flags)
52544 +{
52545 +       void *buf;
52546 +       dwc_otg_pcd_t *pcd = 0;
52547 +
52548 +       pcd = gadget_wrapper->pcd;
52549 +
52550 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
52551 +                   dma, gfp_flags);
52552 +
52553 +       /* Check dword alignment */
52554 +       if ((bytes & 0x3UL) != 0) {
52555 +               DWC_WARN("%s() Buffer size is not a multiple of"
52556 +                        "DWORD size (%d)", __func__, bytes);
52557 +       }
52558 +
52559 +       buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
52560 +
52561 +       /* Check dword alignment */
52562 +       if (((int)buf & 0x3UL) != 0) {
52563 +               DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
52564 +                        __func__, buf);
52565 +       }
52566 +
52567 +       return buf;
52568 +}
52569 +
52570 +/**
52571 + * This function frees an I/O buffer that was allocated by alloc_buffer.
52572 + *
52573 + * @param usb_ep the endpoint associated with the buffer
52574 + * @param buf address of the buffer
52575 + * @param dma The buffer's DMA address
52576 + * @param bytes The number of bytes of the buffer
52577 + */
52578 +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
52579 +                                   dma_addr_t dma, unsigned bytes)
52580 +{
52581 +       dwc_otg_pcd_t *pcd = 0;
52582 +
52583 +       pcd = gadget_wrapper->pcd;
52584 +
52585 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
52586 +
52587 +       dma_free_coherent(NULL, bytes, buf, dma);
52588 +}
52589 +#endif
52590 +
52591 +/**
52592 + * This function is used to submit an I/O Request to an EP.
52593 + *
52594 + *     - When the request completes the request's completion callback
52595 + *       is called to return the request to the driver.
52596 + *     - An EP, except control EPs, may have multiple requests
52597 + *       pending.
52598 + *     - Once submitted the request cannot be examined or modified.
52599 + *     - Each request is turned into one or more packets.
52600 + *     - A BULK EP can queue any amount of data; the transfer is
52601 + *       packetized.
52602 + *     - Zero length Packets are specified with the request 'zero'
52603 + *       flag.
52604 + */
52605 +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
52606 +                   gfp_t gfp_flags)
52607 +{
52608 +       dwc_otg_pcd_t *pcd;
52609 +       struct dwc_otg_pcd_ep *ep = NULL;
52610 +       int retval = 0, is_isoc_ep = 0;
52611 +       dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
52612 +
52613 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
52614 +                   __func__, usb_ep, usb_req, gfp_flags);
52615 +
52616 +       if (!usb_req || !usb_req->complete || !usb_req->buf) {
52617 +               DWC_WARN("bad params\n");
52618 +               return -EINVAL;
52619 +       }
52620 +
52621 +       if (!usb_ep) {
52622 +               DWC_WARN("bad ep\n");
52623 +               return -EINVAL;
52624 +       }
52625 +
52626 +       pcd = gadget_wrapper->pcd;
52627 +       if (!gadget_wrapper->driver ||
52628 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52629 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52630 +                           gadget_wrapper->gadget.speed);
52631 +               DWC_WARN("bogus device state\n");
52632 +               return -ESHUTDOWN;
52633 +       }
52634 +
52635 +       DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
52636 +                   usb_ep->name, usb_req, usb_req->length, usb_req->buf);
52637 +
52638 +       usb_req->status = -EINPROGRESS;
52639 +       usb_req->actual = 0;
52640 +
52641 +       ep = ep_from_handle(pcd, usb_ep);
52642 +       if (ep == NULL)
52643 +               is_isoc_ep = 0;
52644 +       else
52645 +               is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
52646 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52647 +       dma_addr = usb_req->dma;
52648 +#else
52649 +       if (GET_CORE_IF(pcd)->dma_enable) {
52650 +                dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
52651 +                struct device *dev = NULL;
52652 +
52653 +                if (otg_dev != NULL)
52654 +                        dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
52655 +
52656 +               if (usb_req->length != 0 &&
52657 +                    usb_req->dma == DWC_DMA_ADDR_INVALID) {
52658 +                        dma_addr = dma_map_single(dev, usb_req->buf,
52659 +                                                  usb_req->length,
52660 +                                                  ep->dwc_ep.is_in ?
52661 +                                                        DMA_TO_DEVICE:
52662 +                                                        DMA_FROM_DEVICE);
52663 +               }
52664 +       }
52665 +#endif
52666 +
52667 +#ifdef DWC_UTE_PER_IO
52668 +       if (is_isoc_ep == 1) {
52669 +               retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52670 +                       usb_req->length, usb_req->zero, usb_req,
52671 +                       gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
52672 +               if (retval)
52673 +                       return -EINVAL;
52674 +
52675 +               return 0;
52676 +       }
52677 +#endif
52678 +       retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
52679 +                                     usb_req->length, usb_req->zero, usb_req,
52680 +                                     gfp_flags == GFP_ATOMIC ? 1 : 0);
52681 +       if (retval) {
52682 +               return -EINVAL;
52683 +       }
52684 +
52685 +       return 0;
52686 +}
52687 +
52688 +/**
52689 + * This function cancels an I/O request from an EP.
52690 + */
52691 +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
52692 +{
52693 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
52694 +
52695 +       if (!usb_ep || !usb_req) {
52696 +               DWC_WARN("bad argument\n");
52697 +               return -EINVAL;
52698 +       }
52699 +       if (!gadget_wrapper->driver ||
52700 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52701 +               DWC_WARN("bogus device state\n");
52702 +               return -ESHUTDOWN;
52703 +       }
52704 +       if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
52705 +               return -EINVAL;
52706 +       }
52707 +
52708 +       return 0;
52709 +}
52710 +
52711 +/**
52712 + * usb_ep_set_halt stalls an endpoint.
52713 + *
52714 + * usb_ep_clear_halt clears an endpoint halt and resets its data
52715 + * toggle.
52716 + *
52717 + * Both of these functions are implemented with the same underlying
52718 + * function. The behavior depends on the value argument.
52719 + *
52720 + * @param[in] usb_ep the Endpoint to halt or clear halt.
52721 + * @param[in] value
52722 + *     - 0 means clear_halt.
52723 + *     - 1 means set_halt,
52724 + *     - 2 means clear stall lock flag.
52725 + *     - 3 means set  stall lock flag.
52726 + */
52727 +static int ep_halt(struct usb_ep *usb_ep, int value)
52728 +{
52729 +       int retval = 0;
52730 +
52731 +       DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
52732 +
52733 +       if (!usb_ep) {
52734 +               DWC_WARN("bad ep\n");
52735 +               return -EINVAL;
52736 +       }
52737 +
52738 +       retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
52739 +       if (retval == -DWC_E_AGAIN) {
52740 +               return -EAGAIN;
52741 +       } else if (retval) {
52742 +               retval = -EINVAL;
52743 +       }
52744 +
52745 +       return retval;
52746 +}
52747 +
52748 +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
52749 +#if 0
52750 +/**
52751 + * ep_wedge: sets the halt feature and ignores clear requests
52752 + *
52753 + * @usb_ep: the endpoint being wedged
52754 + *
52755 + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
52756 + * requests. If the gadget driver clears the halt status, it will
52757 + * automatically unwedge the endpoint.
52758 + *
52759 + * Returns zero on success, else negative errno. *
52760 + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
52761 + */
52762 +static int ep_wedge(struct usb_ep *usb_ep)
52763 +{
52764 +       int retval = 0;
52765 +
52766 +       DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
52767 +
52768 +       if (!usb_ep) {
52769 +               DWC_WARN("bad ep\n");
52770 +               return -EINVAL;
52771 +       }
52772 +
52773 +       retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
52774 +       if (retval == -DWC_E_AGAIN) {
52775 +               retval = -EAGAIN;
52776 +       } else if (retval) {
52777 +               retval = -EINVAL;
52778 +       }
52779 +
52780 +       return retval;
52781 +}
52782 +#endif
52783 +
52784 +#ifdef DWC_EN_ISOC
52785 +/**
52786 + * This function is used to submit an ISOC Transfer Request to an EP.
52787 + *
52788 + *     - Every time a sync period completes the request's completion callback
52789 + *       is called to provide data to the gadget driver.
52790 + *     - Once submitted the request cannot be modified.
52791 + *     - Each request is turned into periodic data packets untill ISO
52792 + *       Transfer is stopped..
52793 + */
52794 +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
52795 +                       gfp_t gfp_flags)
52796 +{
52797 +       int retval = 0;
52798 +
52799 +       if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
52800 +               DWC_WARN("bad params\n");
52801 +               return -EINVAL;
52802 +       }
52803 +
52804 +       if (!usb_ep) {
52805 +               DWC_PRINTF("bad params\n");
52806 +               return -EINVAL;
52807 +       }
52808 +
52809 +       req->status = -EINPROGRESS;
52810 +
52811 +       retval =
52812 +           dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
52813 +                                    req->buf1, req->dma0, req->dma1,
52814 +                                    req->sync_frame, req->data_pattern_frame,
52815 +                                    req->data_per_frame,
52816 +                                    req->
52817 +                                    flags & USB_REQ_ISO_ASAP ? -1 :
52818 +                                    req->start_frame, req->buf_proc_intrvl,
52819 +                                    req, gfp_flags == GFP_ATOMIC ? 1 : 0);
52820 +
52821 +       if (retval) {
52822 +               return -EINVAL;
52823 +       }
52824 +
52825 +       return retval;
52826 +}
52827 +
52828 +/**
52829 + * This function stops ISO EP Periodic Data Transfer.
52830 + */
52831 +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
52832 +{
52833 +       int retval = 0;
52834 +       if (!usb_ep) {
52835 +               DWC_WARN("bad ep\n");
52836 +       }
52837 +
52838 +       if (!gadget_wrapper->driver ||
52839 +           gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
52840 +               DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
52841 +                           gadget_wrapper->gadget.speed);
52842 +               DWC_WARN("bogus device state\n");
52843 +       }
52844 +
52845 +       dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
52846 +       if (retval) {
52847 +               retval = -EINVAL;
52848 +       }
52849 +
52850 +       return retval;
52851 +}
52852 +
52853 +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
52854 +                                                int packets, gfp_t gfp_flags)
52855 +{
52856 +       struct usb_iso_request *pReq = NULL;
52857 +       uint32_t req_size;
52858 +
52859 +       req_size = sizeof(struct usb_iso_request);
52860 +       req_size +=
52861 +           (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
52862 +
52863 +       pReq = kmalloc(req_size, gfp_flags);
52864 +       if (!pReq) {
52865 +               DWC_WARN("Can't allocate Iso Request\n");
52866 +               return 0;
52867 +       }
52868 +       pReq->iso_packet_desc0 = (void *)(pReq + 1);
52869 +
52870 +       pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
52871 +
52872 +       return pReq;
52873 +}
52874 +
52875 +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
52876 +{
52877 +       kfree(req);
52878 +}
52879 +
52880 +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
52881 +       .ep_ops = {
52882 +                  .enable = ep_enable,
52883 +                  .disable = ep_disable,
52884 +
52885 +                  .alloc_request = dwc_otg_pcd_alloc_request,
52886 +                  .free_request = dwc_otg_pcd_free_request,
52887 +
52888 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52889 +                  .alloc_buffer = dwc_otg_pcd_alloc_buffer,
52890 +                  .free_buffer = dwc_otg_pcd_free_buffer,
52891 +#endif
52892 +
52893 +                  .queue = ep_queue,
52894 +                  .dequeue = ep_dequeue,
52895 +
52896 +                  .set_halt = ep_halt,
52897 +                  .fifo_status = 0,
52898 +                  .fifo_flush = 0,
52899 +                  },
52900 +       .iso_ep_start = iso_ep_start,
52901 +       .iso_ep_stop = iso_ep_stop,
52902 +       .alloc_iso_request = alloc_iso_request,
52903 +       .free_iso_request = free_iso_request,
52904 +};
52905 +
52906 +#else
52907 +
52908 +       int (*enable) (struct usb_ep *ep,
52909 +               const struct usb_endpoint_descriptor *desc);
52910 +       int (*disable) (struct usb_ep *ep);
52911 +
52912 +       struct usb_request *(*alloc_request) (struct usb_ep *ep,
52913 +               gfp_t gfp_flags);
52914 +       void (*free_request) (struct usb_ep *ep, struct usb_request *req);
52915 +
52916 +       int (*queue) (struct usb_ep *ep, struct usb_request *req,
52917 +               gfp_t gfp_flags);
52918 +       int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
52919 +
52920 +       int (*set_halt) (struct usb_ep *ep, int value);
52921 +       int (*set_wedge) (struct usb_ep *ep);
52922 +
52923 +       int (*fifo_status) (struct usb_ep *ep);
52924 +       void (*fifo_flush) (struct usb_ep *ep);
52925 +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
52926 +       .enable = ep_enable,
52927 +       .disable = ep_disable,
52928 +
52929 +       .alloc_request = dwc_otg_pcd_alloc_request,
52930 +       .free_request = dwc_otg_pcd_free_request,
52931 +
52932 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
52933 +       .alloc_buffer = dwc_otg_pcd_alloc_buffer,
52934 +       .free_buffer = dwc_otg_pcd_free_buffer,
52935 +#else
52936 +       /* .set_wedge = ep_wedge, */
52937 +        .set_wedge = NULL, /* uses set_halt instead */
52938 +#endif
52939 +
52940 +       .queue = ep_queue,
52941 +       .dequeue = ep_dequeue,
52942 +
52943 +       .set_halt = ep_halt,
52944 +       .fifo_status = 0,
52945 +       .fifo_flush = 0,
52946 +
52947 +};
52948 +
52949 +#endif /* _EN_ISOC_ */
52950 +/*     Gadget Operations */
52951 +/**
52952 + * The following gadget operations will be implemented in the DWC_otg
52953 + * PCD. Functions in the API that are not described below are not
52954 + * implemented.
52955 + *
52956 + * The Gadget API provides wrapper functions for each of the function
52957 + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
52958 + * wrapper function, which then calls the underlying PCD function. The
52959 + * following sections are named according to the wrapper functions
52960 + * (except for ioctl, which doesn't have a wrapper function). Within
52961 + * each section, the corresponding DWC_otg PCD function name is
52962 + * specified.
52963 + *
52964 + */
52965 +
52966 +/**
52967 + *Gets the USB Frame number of the last SOF.
52968 + */
52969 +static int get_frame_number(struct usb_gadget *gadget)
52970 +{
52971 +       struct gadget_wrapper *d;
52972 +
52973 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
52974 +
52975 +       if (gadget == 0) {
52976 +               return -ENODEV;
52977 +       }
52978 +
52979 +       d = container_of(gadget, struct gadget_wrapper, gadget);
52980 +       return dwc_otg_pcd_get_frame_number(d->pcd);
52981 +}
52982 +
52983 +#ifdef CONFIG_USB_DWC_OTG_LPM
52984 +static int test_lpm_enabled(struct usb_gadget *gadget)
52985 +{
52986 +       struct gadget_wrapper *d;
52987 +
52988 +       d = container_of(gadget, struct gadget_wrapper, gadget);
52989 +
52990 +       return dwc_otg_pcd_is_lpm_enabled(d->pcd);
52991 +}
52992 +#endif
52993 +
52994 +/**
52995 + * Initiates Session Request Protocol (SRP) to wakeup the host if no
52996 + * session is in progress. If a session is already in progress, but
52997 + * the device is suspended, remote wakeup signaling is started.
52998 + *
52999 + */
53000 +static int wakeup(struct usb_gadget *gadget)
53001 +{
53002 +       struct gadget_wrapper *d;
53003 +
53004 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
53005 +
53006 +       if (gadget == 0) {
53007 +               return -ENODEV;
53008 +       } else {
53009 +               d = container_of(gadget, struct gadget_wrapper, gadget);
53010 +       }
53011 +       dwc_otg_pcd_wakeup(d->pcd);
53012 +       return 0;
53013 +}
53014 +
53015 +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
53016 +       .get_frame = get_frame_number,
53017 +       .wakeup = wakeup,
53018 +#ifdef CONFIG_USB_DWC_OTG_LPM
53019 +       .lpm_support = test_lpm_enabled,
53020 +#endif
53021 +       // current versions must always be self-powered
53022 +};
53023 +
53024 +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
53025 +{
53026 +       int retval = -DWC_E_NOT_SUPPORTED;
53027 +       if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
53028 +               retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
53029 +                                                      (struct usb_ctrlrequest
53030 +                                                       *)bytes);
53031 +       }
53032 +
53033 +       if (retval == -ENOTSUPP) {
53034 +               retval = -DWC_E_NOT_SUPPORTED;
53035 +       } else if (retval < 0) {
53036 +               retval = -DWC_E_INVALID;
53037 +       }
53038 +
53039 +       return retval;
53040 +}
53041 +
53042 +#ifdef DWC_EN_ISOC
53043 +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53044 +                         void *req_handle, int proc_buf_num)
53045 +{
53046 +       int i, packet_count;
53047 +       struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
53048 +       struct usb_iso_request *iso_req = req_handle;
53049 +
53050 +       if (proc_buf_num) {
53051 +               iso_packet = iso_req->iso_packet_desc1;
53052 +       } else {
53053 +               iso_packet = iso_req->iso_packet_desc0;
53054 +       }
53055 +       packet_count =
53056 +           dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
53057 +       for (i = 0; i < packet_count; ++i) {
53058 +               int status;
53059 +               int actual;
53060 +               int offset;
53061 +               dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
53062 +                                                 i, &status, &actual, &offset);
53063 +               switch (status) {
53064 +               case -DWC_E_NO_DATA:
53065 +                       status = -ENODATA;
53066 +                       break;
53067 +               default:
53068 +                       if (status) {
53069 +                               DWC_PRINTF("unknown status in isoc packet\n");
53070 +                       }
53071 +
53072 +               }
53073 +               iso_packet[i].status = status;
53074 +               iso_packet[i].offset = offset;
53075 +               iso_packet[i].actual_length = actual;
53076 +       }
53077 +
53078 +       iso_req->status = 0;
53079 +       iso_req->process_buffer(ep_handle, iso_req);
53080 +
53081 +       return 0;
53082 +}
53083 +#endif /* DWC_EN_ISOC */
53084 +
53085 +#ifdef DWC_UTE_PER_IO
53086 +/**
53087 + * Copy the contents of the extended request to the Linux usb_request's
53088 + * extended part and call the gadget's completion.
53089 + *
53090 + * @param pcd                  Pointer to the pcd structure
53091 + * @param ep_handle            Void pointer to the usb_ep structure
53092 + * @param req_handle   Void pointer to the usb_request structure
53093 + * @param status               Request status returned from the portable logic
53094 + * @param ereq_port            Void pointer to the extended request structure
53095 + *                                             created in the the portable part that contains the
53096 + *                                             results of the processed iso packets.
53097 + */
53098 +static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53099 +                          void *req_handle, int32_t status, void *ereq_port)
53100 +{
53101 +       struct dwc_ute_iso_req_ext *ereqorg = NULL;
53102 +       struct dwc_iso_xreq_port *ereqport = NULL;
53103 +       struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
53104 +       int i;
53105 +       struct usb_request *req;
53106 +       //struct dwc_ute_iso_packet_descriptor *
53107 +       //int status = 0;
53108 +
53109 +       req = (struct usb_request *)req_handle;
53110 +       ereqorg = &req->ext_req;
53111 +       ereqport = (struct dwc_iso_xreq_port *)ereq_port;
53112 +       desc_org = ereqorg->per_io_frame_descs;
53113 +
53114 +       if (req && req->complete) {
53115 +               /* Copy the request data from the portable logic to our request */
53116 +               for (i = 0; i < ereqport->pio_pkt_count; i++) {
53117 +                       desc_org[i].actual_length =
53118 +                           ereqport->per_io_frame_descs[i].actual_length;
53119 +                       desc_org[i].status =
53120 +                           ereqport->per_io_frame_descs[i].status;
53121 +               }
53122 +
53123 +               switch (status) {
53124 +               case -DWC_E_SHUTDOWN:
53125 +                       req->status = -ESHUTDOWN;
53126 +                       break;
53127 +               case -DWC_E_RESTART:
53128 +                       req->status = -ECONNRESET;
53129 +                       break;
53130 +               case -DWC_E_INVALID:
53131 +                       req->status = -EINVAL;
53132 +                       break;
53133 +               case -DWC_E_TIMEOUT:
53134 +                       req->status = -ETIMEDOUT;
53135 +                       break;
53136 +               default:
53137 +                       req->status = status;
53138 +               }
53139 +
53140 +               /* And call the gadget's completion */
53141 +               req->complete(ep_handle, req);
53142 +       }
53143 +
53144 +       return 0;
53145 +}
53146 +#endif /* DWC_UTE_PER_IO */
53147 +
53148 +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
53149 +                    void *req_handle, int32_t status, uint32_t actual)
53150 +{
53151 +       struct usb_request *req = (struct usb_request *)req_handle;
53152 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53153 +       struct dwc_otg_pcd_ep *ep = NULL;
53154 +#endif
53155 +
53156 +       if (req && req->complete) {
53157 +               switch (status) {
53158 +               case -DWC_E_SHUTDOWN:
53159 +                       req->status = -ESHUTDOWN;
53160 +                       break;
53161 +               case -DWC_E_RESTART:
53162 +                       req->status = -ECONNRESET;
53163 +                       break;
53164 +               case -DWC_E_INVALID:
53165 +                       req->status = -EINVAL;
53166 +                       break;
53167 +               case -DWC_E_TIMEOUT:
53168 +                       req->status = -ETIMEDOUT;
53169 +                       break;
53170 +               default:
53171 +                       req->status = status;
53172 +
53173 +               }
53174 +
53175 +               req->actual = actual;
53176 +               DWC_SPINUNLOCK(pcd->lock);
53177 +               req->complete(ep_handle, req);
53178 +               DWC_SPINLOCK(pcd->lock);
53179 +       }
53180 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
53181 +       ep = ep_from_handle(pcd, ep_handle);
53182 +       if (GET_CORE_IF(pcd)->dma_enable) {
53183 +                if (req->length != 0) {
53184 +                        dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
53185 +                        struct device *dev = NULL;
53186 +
53187 +                        if (otg_dev != NULL)
53188 +                                  dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
53189 +
53190 +                       dma_unmap_single(dev, req->dma, req->length,
53191 +                                         ep->dwc_ep.is_in ?
53192 +                                                DMA_TO_DEVICE: DMA_FROM_DEVICE);
53193 +                }
53194 +       }
53195 +#endif
53196 +
53197 +       return 0;
53198 +}
53199 +
53200 +static int _connect(dwc_otg_pcd_t * pcd, int speed)
53201 +{
53202 +       gadget_wrapper->gadget.speed = speed;
53203 +       return 0;
53204 +}
53205 +
53206 +static int _disconnect(dwc_otg_pcd_t * pcd)
53207 +{
53208 +       if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
53209 +               gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
53210 +       }
53211 +       return 0;
53212 +}
53213 +
53214 +static int _resume(dwc_otg_pcd_t * pcd)
53215 +{
53216 +       if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
53217 +               gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
53218 +       }
53219 +
53220 +       return 0;
53221 +}
53222 +
53223 +static int _suspend(dwc_otg_pcd_t * pcd)
53224 +{
53225 +       if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
53226 +               gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
53227 +       }
53228 +       return 0;
53229 +}
53230 +
53231 +/**
53232 + * This function updates the otg values in the gadget structure.
53233 + */
53234 +static int _hnp_changed(dwc_otg_pcd_t * pcd)
53235 +{
53236 +
53237 +       if (!gadget_wrapper->gadget.is_otg)
53238 +               return 0;
53239 +
53240 +       gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
53241 +       gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
53242 +       gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
53243 +       return 0;
53244 +}
53245 +
53246 +static int _reset(dwc_otg_pcd_t * pcd)
53247 +{
53248 +       return 0;
53249 +}
53250 +
53251 +#ifdef DWC_UTE_CFI
53252 +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
53253 +{
53254 +       int retval = -DWC_E_INVALID;
53255 +       if (gadget_wrapper->driver->cfi_feature_setup) {
53256 +               retval =
53257 +                   gadget_wrapper->driver->
53258 +                   cfi_feature_setup(&gadget_wrapper->gadget,
53259 +                                     (struct cfi_usb_ctrlrequest *)cfi_req);
53260 +       }
53261 +
53262 +       return retval;
53263 +}
53264 +#endif
53265 +
53266 +static const struct dwc_otg_pcd_function_ops fops = {
53267 +       .complete = _complete,
53268 +#ifdef DWC_EN_ISOC
53269 +       .isoc_complete = _isoc_complete,
53270 +#endif
53271 +       .setup = _setup,
53272 +       .disconnect = _disconnect,
53273 +       .connect = _connect,
53274 +       .resume = _resume,
53275 +       .suspend = _suspend,
53276 +       .hnp_changed = _hnp_changed,
53277 +       .reset = _reset,
53278 +#ifdef DWC_UTE_CFI
53279 +       .cfi_setup = _cfi_setup,
53280 +#endif
53281 +#ifdef DWC_UTE_PER_IO
53282 +       .xisoc_complete = _xisoc_complete,
53283 +#endif
53284 +};
53285 +
53286 +/**
53287 + * This function is the top level PCD interrupt handler.
53288 + */
53289 +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
53290 +{
53291 +       dwc_otg_pcd_t *pcd = dev;
53292 +       int32_t retval = IRQ_NONE;
53293 +
53294 +       retval = dwc_otg_pcd_handle_intr(pcd);
53295 +       if (retval != 0) {
53296 +               S3C2410X_CLEAR_EINTPEND();
53297 +       }
53298 +       return IRQ_RETVAL(retval);
53299 +}
53300 +
53301 +/**
53302 + * This function initialized the usb_ep structures to there default
53303 + * state.
53304 + *
53305 + * @param d Pointer on gadget_wrapper.
53306 + */
53307 +void gadget_add_eps(struct gadget_wrapper *d)
53308 +{
53309 +       static const char *names[] = {
53310 +
53311 +               "ep0",
53312 +               "ep1in",
53313 +               "ep2in",
53314 +               "ep3in",
53315 +               "ep4in",
53316 +               "ep5in",
53317 +               "ep6in",
53318 +               "ep7in",
53319 +               "ep8in",
53320 +               "ep9in",
53321 +               "ep10in",
53322 +               "ep11in",
53323 +               "ep12in",
53324 +               "ep13in",
53325 +               "ep14in",
53326 +               "ep15in",
53327 +               "ep1out",
53328 +               "ep2out",
53329 +               "ep3out",
53330 +               "ep4out",
53331 +               "ep5out",
53332 +               "ep6out",
53333 +               "ep7out",
53334 +               "ep8out",
53335 +               "ep9out",
53336 +               "ep10out",
53337 +               "ep11out",
53338 +               "ep12out",
53339 +               "ep13out",
53340 +               "ep14out",
53341 +               "ep15out"
53342 +       };
53343 +
53344 +       int i;
53345 +       struct usb_ep *ep;
53346 +       int8_t dev_endpoints;
53347 +
53348 +       DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
53349 +
53350 +       INIT_LIST_HEAD(&d->gadget.ep_list);
53351 +       d->gadget.ep0 = &d->ep0;
53352 +       d->gadget.speed = USB_SPEED_UNKNOWN;
53353 +
53354 +       INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
53355 +
53356 +       /**
53357 +        * Initialize the EP0 structure.
53358 +        */
53359 +       ep = &d->ep0;
53360 +
53361 +       /* Init the usb_ep structure. */
53362 +       ep->name = names[0];
53363 +       ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53364 +
53365 +       /**
53366 +        * @todo NGS: What should the max packet size be set to
53367 +        * here?  Before EP type is set?
53368 +        */
53369 +       ep->maxpacket = MAX_PACKET_SIZE;
53370 +       dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
53371 +
53372 +       list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53373 +
53374 +       /**
53375 +        * Initialize the EP structures.
53376 +        */
53377 +       dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
53378 +
53379 +       for (i = 0; i < dev_endpoints; i++) {
53380 +               ep = &d->in_ep[i];
53381 +
53382 +               /* Init the usb_ep structure. */
53383 +               ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
53384 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53385 +
53386 +               /**
53387 +                * @todo NGS: What should the max packet size be set to
53388 +                * here?  Before EP type is set?
53389 +                */
53390 +               ep->maxpacket = MAX_PACKET_SIZE;
53391 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53392 +       }
53393 +
53394 +       dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
53395 +
53396 +       for (i = 0; i < dev_endpoints; i++) {
53397 +               ep = &d->out_ep[i];
53398 +
53399 +               /* Init the usb_ep structure. */
53400 +               ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
53401 +               ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
53402 +
53403 +               /**
53404 +                * @todo NGS: What should the max packet size be set to
53405 +                * here?  Before EP type is set?
53406 +                */
53407 +               ep->maxpacket = MAX_PACKET_SIZE;
53408 +
53409 +               list_add_tail(&ep->ep_list, &d->gadget.ep_list);
53410 +       }
53411 +
53412 +       /* remove ep0 from the list.  There is a ep0 pointer. */
53413 +       list_del_init(&d->ep0.ep_list);
53414 +
53415 +       d->ep0.maxpacket = MAX_EP0_SIZE;
53416 +}
53417 +
53418 +/**
53419 + * This function releases the Gadget device.
53420 + * required by device_unregister().
53421 + *
53422 + * @todo Should this do something?     Should it free the PCD?
53423 + */
53424 +static void dwc_otg_pcd_gadget_release(struct device *dev)
53425 +{
53426 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
53427 +}
53428 +
53429 +static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)
53430 +{
53431 +       static char pcd_name[] = "dwc_otg_pcd";
53432 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53433 +       struct gadget_wrapper *d;
53434 +       int retval;
53435 +
53436 +       d = DWC_ALLOC(sizeof(*d));
53437 +       if (d == NULL) {
53438 +               return NULL;
53439 +       }
53440 +
53441 +       memset(d, 0, sizeof(*d));
53442 +
53443 +       d->gadget.name = pcd_name;
53444 +       d->pcd = otg_dev->pcd;
53445 +
53446 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
53447 +       strcpy(d->gadget.dev.bus_id, "gadget");
53448 +#else
53449 +       dev_set_name(&d->gadget.dev, "%s", "gadget");
53450 +#endif
53451 +
53452 +       d->gadget.dev.parent = &_dev->dev;
53453 +       d->gadget.dev.release = dwc_otg_pcd_gadget_release;
53454 +       d->gadget.ops = &dwc_otg_pcd_ops;
53455 +       d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;
53456 +       d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
53457 +
53458 +       d->driver = 0;
53459 +       /* Register the gadget device */
53460 +       retval = device_register(&d->gadget.dev);
53461 +       if (retval != 0) {
53462 +               DWC_ERROR("device_register failed\n");
53463 +               DWC_FREE(d);
53464 +               return NULL;
53465 +       }
53466 +
53467 +       return d;
53468 +}
53469 +
53470 +static void free_wrapper(struct gadget_wrapper *d)
53471 +{
53472 +       if (d->driver) {
53473 +               /* should have been done already by driver model core */
53474 +               DWC_WARN("driver '%s' is still registered\n",
53475 +                        d->driver->driver.name);
53476 +               usb_gadget_unregister_driver(d->driver);
53477 +       }
53478 +
53479 +       device_unregister(&d->gadget.dev);
53480 +       DWC_FREE(d);
53481 +}
53482 +
53483 +/**
53484 + * This function initialized the PCD portion of the driver.
53485 + *
53486 + */
53487 +int pcd_init(dwc_bus_dev_t *_dev)
53488 +{
53489 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53490 +       int retval = 0;
53491 +
53492 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
53493 +
53494 +       otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
53495 +
53496 +       if (!otg_dev->pcd) {
53497 +               DWC_ERROR("dwc_otg_pcd_init failed\n");
53498 +               return -ENOMEM;
53499 +       }
53500 +
53501 +       otg_dev->pcd->otg_dev = otg_dev;
53502 +       gadget_wrapper = alloc_wrapper(_dev);
53503 +
53504 +       /*
53505 +        * Initialize EP structures
53506 +        */
53507 +       gadget_add_eps(gadget_wrapper);
53508 +       /*
53509 +        * Setup interupt handler
53510 +        */
53511 +#ifdef PLATFORM_INTERFACE
53512 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53513 +                    platform_get_irq(_dev, 0));
53514 +       retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
53515 +                            IRQF_SHARED, gadget_wrapper->gadget.name,
53516 +                            otg_dev->pcd);
53517 +       if (retval != 0) {
53518 +               DWC_ERROR("request of irq%d failed\n",
53519 +                          platform_get_irq(_dev, 0));
53520 +               free_wrapper(gadget_wrapper);
53521 +               return -EBUSY;
53522 +       }
53523 +#else
53524 +       DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
53525 +                    _dev->irq);
53526 +       retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
53527 +                            IRQF_SHARED | IRQF_DISABLED,
53528 +                            gadget_wrapper->gadget.name, otg_dev->pcd);
53529 +       if (retval != 0) {
53530 +               DWC_ERROR("request of irq%d failed\n", _dev->irq);
53531 +               free_wrapper(gadget_wrapper);
53532 +               return -EBUSY;
53533 +       }
53534 +#endif
53535 +
53536 +       dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
53537 +
53538 +       return retval;
53539 +}
53540 +
53541 +/**
53542 + * Cleanup the PCD.
53543 + */
53544 +void pcd_remove(dwc_bus_dev_t *_dev)
53545 +{
53546 +       dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
53547 +       dwc_otg_pcd_t *pcd = otg_dev->pcd;
53548 +
53549 +       DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
53550 +
53551 +       /*
53552 +        * Free the IRQ
53553 +        */
53554 +#ifdef PLATFORM_INTERFACE
53555 +       free_irq(platform_get_irq(_dev, 0), pcd);
53556 +#else
53557 +       free_irq(_dev->irq, pcd);
53558 +#endif
53559 +       dwc_otg_pcd_remove(otg_dev->pcd);
53560 +       free_wrapper(gadget_wrapper);
53561 +       otg_dev->pcd = 0;
53562 +}
53563 +
53564 +/**
53565 + * This function registers a gadget driver with the PCD.
53566 + *
53567 + * When a driver is successfully registered, it will receive control
53568 + * requests including set_configuration(), which enables non-control
53569 + * requests.  then usb traffic follows until a disconnect is reported.
53570 + * then a host may connect again, or the driver might get unbound.
53571 + *
53572 + * @param driver The driver being registered
53573 + * @param bind The bind function of gadget driver
53574 + */
53575 +
53576 +int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
53577 +{
53578 +       int retval;
53579 +
53580 +       DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
53581 +                   driver->driver.name);
53582 +
53583 +       if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
53584 +           !driver->bind ||
53585 +           !driver->unbind || !driver->disconnect || !driver->setup) {
53586 +               DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
53587 +               return -EINVAL;
53588 +       }
53589 +       if (gadget_wrapper == 0) {
53590 +               DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
53591 +               return -ENODEV;
53592 +       }
53593 +       if (gadget_wrapper->driver != 0) {
53594 +               DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
53595 +               return -EBUSY;
53596 +       }
53597 +
53598 +       /* hook up the driver */
53599 +       gadget_wrapper->driver = driver;
53600 +       gadget_wrapper->gadget.dev.driver = &driver->driver;
53601 +
53602 +       DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
53603 +       retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);
53604 +       if (retval) {
53605 +               DWC_ERROR("bind to driver %s --> error %d\n",
53606 +                         driver->driver.name, retval);
53607 +               gadget_wrapper->driver = 0;
53608 +               gadget_wrapper->gadget.dev.driver = 0;
53609 +               return retval;
53610 +       }
53611 +       DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
53612 +                   driver->driver.name);
53613 +       return 0;
53614 +}
53615 +EXPORT_SYMBOL(usb_gadget_probe_driver);
53616 +
53617 +/**
53618 + * This function unregisters a gadget driver
53619 + *
53620 + * @param driver The driver being unregistered
53621 + */
53622 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
53623 +{
53624 +       //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
53625 +
53626 +       if (gadget_wrapper == 0) {
53627 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
53628 +                           -ENODEV);
53629 +               return -ENODEV;
53630 +       }
53631 +       if (driver == 0 || driver != gadget_wrapper->driver) {
53632 +               DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
53633 +                           -EINVAL);
53634 +               return -EINVAL;
53635 +       }
53636 +
53637 +       driver->unbind(&gadget_wrapper->gadget);
53638 +       gadget_wrapper->driver = 0;
53639 +
53640 +       DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
53641 +       return 0;
53642 +}
53643 +
53644 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
53645 +
53646 +#endif /* DWC_HOST_ONLY */
53647 --- /dev/null
53648 +++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
53649 @@ -0,0 +1,2550 @@
53650 +/* ==========================================================================
53651 + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
53652 + * $Revision: #98 $
53653 + * $Date: 2012/08/10 $
53654 + * $Change: 2047372 $
53655 + *
53656 + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
53657 + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
53658 + * otherwise expressly agreed to in writing between Synopsys and you.
53659 + *
53660 + * The Software IS NOT an item of Licensed Software or Licensed Product under
53661 + * any End User Software License Agreement or Agreement for Licensed Product
53662 + * with Synopsys or any supplement thereto. You are permitted to use and
53663 + * redistribute this Software in source and binary forms, with or without
53664 + * modification, provided that redistributions of source code must retain this
53665 + * notice. You may not view, use, disclose, copy or distribute this file or
53666 + * any information contained herein except pursuant to this license grant from
53667 + * Synopsys. If you do not agree with this notice, including the disclaimer
53668 + * below, then you are not authorized to use the Software.
53669 + *
53670 + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
53671 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53672 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53673 + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
53674 + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53675 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53676 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
53677 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53678 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53679 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
53680 + * DAMAGE.
53681 + * ========================================================================== */
53682 +
53683 +#ifndef __DWC_OTG_REGS_H__
53684 +#define __DWC_OTG_REGS_H__
53685 +
53686 +#include "dwc_otg_core_if.h"
53687 +
53688 +/**
53689 + * @file
53690 + *
53691 + * This file contains the data structures for accessing the DWC_otg core registers.
53692 + *
53693 + * The application interfaces with the HS OTG core by reading from and
53694 + * writing to the Control and Status Register (CSR) space through the
53695 + * AHB Slave interface. These registers are 32 bits wide, and the
53696 + * addresses are 32-bit-block aligned.
53697 + * CSRs are classified as follows:
53698 + * - Core Global Registers
53699 + * - Device Mode Registers
53700 + * - Device Global Registers
53701 + * - Device Endpoint Specific Registers
53702 + * - Host Mode Registers
53703 + * - Host Global Registers
53704 + * - Host Port CSRs
53705 + * - Host Channel Specific Registers
53706 + *
53707 + * Only the Core Global registers can be accessed in both Device and
53708 + * Host modes. When the HS OTG core is operating in one mode, either
53709 + * Device or Host, the application must not access registers from the
53710 + * other mode. When the core switches from one mode to another, the
53711 + * registers in the new mode of operation must be reprogrammed as they
53712 + * would be after a power-on reset.
53713 + */
53714 +
53715 +/****************************************************************************/
53716 +/** DWC_otg Core registers .
53717 + * The dwc_otg_core_global_regs structure defines the size
53718 + * and relative field offsets for the Core Global registers.
53719 + */
53720 +typedef struct dwc_otg_core_global_regs {
53721 +       /** OTG Control and Status Register.  <i>Offset: 000h</i> */
53722 +       volatile uint32_t gotgctl;
53723 +       /** OTG Interrupt Register.      <i>Offset: 004h</i> */
53724 +       volatile uint32_t gotgint;
53725 +       /**Core AHB Configuration Register.      <i>Offset: 008h</i> */
53726 +       volatile uint32_t gahbcfg;
53727 +
53728 +#define DWC_GLBINTRMASK                0x0001
53729 +#define DWC_DMAENABLE          0x0020
53730 +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
53731 +#define DWC_NPTXEMPTYLVL_HALFEMPTY     0x0000
53732 +#define DWC_PTXEMPTYLVL_EMPTY  0x0100
53733 +#define DWC_PTXEMPTYLVL_HALFEMPTY      0x0000
53734 +
53735 +       /**Core USB Configuration Register.      <i>Offset: 00Ch</i> */
53736 +       volatile uint32_t gusbcfg;
53737 +       /**Core Reset Register.  <i>Offset: 010h</i> */
53738 +       volatile uint32_t grstctl;
53739 +       /**Core Interrupt Register.      <i>Offset: 014h</i> */
53740 +       volatile uint32_t gintsts;
53741 +       /**Core Interrupt Mask Register.  <i>Offset: 018h</i> */
53742 +       volatile uint32_t gintmsk;
53743 +       /**Receive Status Queue Read Register (Read Only).      <i>Offset: 01Ch</i> */
53744 +       volatile uint32_t grxstsr;
53745 +       /**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/
53746 +       volatile uint32_t grxstsp;
53747 +       /**Receive FIFO Size Register.  <i>Offset: 024h</i> */
53748 +       volatile uint32_t grxfsiz;
53749 +       /**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */
53750 +       volatile uint32_t gnptxfsiz;
53751 +       /**Non Periodic Transmit FIFO/Queue Status Register (Read
53752 +        * Only). <i>Offset: 02Ch</i> */
53753 +       volatile uint32_t gnptxsts;
53754 +       /**I2C Access Register.  <i>Offset: 030h</i> */
53755 +       volatile uint32_t gi2cctl;
53756 +       /**PHY Vendor Control Register.  <i>Offset: 034h</i> */
53757 +       volatile uint32_t gpvndctl;
53758 +       /**General Purpose Input/Output Register.  <i>Offset: 038h</i> */
53759 +       volatile uint32_t ggpio;
53760 +       /**User ID Register.  <i>Offset: 03Ch</i> */
53761 +       volatile uint32_t guid;
53762 +       /**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */
53763 +       volatile uint32_t gsnpsid;
53764 +       /**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */
53765 +       volatile uint32_t ghwcfg1;
53766 +       /**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */
53767 +       volatile uint32_t ghwcfg2;
53768 +#define DWC_SLAVE_ONLY_ARCH 0
53769 +#define DWC_EXT_DMA_ARCH 1
53770 +#define DWC_INT_DMA_ARCH 2
53771 +
53772 +#define DWC_MODE_HNP_SRP_CAPABLE       0
53773 +#define DWC_MODE_SRP_ONLY_CAPABLE      1
53774 +#define DWC_MODE_NO_HNP_SRP_CAPABLE            2
53775 +#define DWC_MODE_SRP_CAPABLE_DEVICE            3
53776 +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
53777 +#define DWC_MODE_SRP_CAPABLE_HOST      5
53778 +#define DWC_MODE_NO_SRP_CAPABLE_HOST   6
53779 +
53780 +       /**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */
53781 +       volatile uint32_t ghwcfg3;
53782 +       /**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/
53783 +       volatile uint32_t ghwcfg4;
53784 +       /** Core LPM Configuration register <i>Offset: 054h</i>*/
53785 +       volatile uint32_t glpmcfg;
53786 +       /** Global PowerDn Register <i>Offset: 058h</i> */
53787 +       volatile uint32_t gpwrdn;
53788 +       /** Global DFIFO SW Config Register  <i>Offset: 05Ch</i> */
53789 +       volatile uint32_t gdfifocfg;
53790 +       /** ADP Control Register  <i>Offset: 060h</i> */
53791 +       volatile uint32_t adpctl;
53792 +       /** Reserved  <i>Offset: 064h-0FFh</i> */
53793 +       volatile uint32_t reserved39[39];
53794 +       /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
53795 +       volatile uint32_t hptxfsiz;
53796 +       /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
53797 +               otherwise Device Transmit FIFO#n Register.
53798 +        * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
53799 +       volatile uint32_t dtxfsiz[15];
53800 +} dwc_otg_core_global_regs_t;
53801 +
53802 +/**
53803 + * This union represents the bit fields of the Core OTG Control
53804 + * and Status Register (GOTGCTL).  Set the bits using the bit
53805 + * fields then write the <i>d32</i> value to the register.
53806 + */
53807 +typedef union gotgctl_data {
53808 +       /** raw register data */
53809 +       uint32_t d32;
53810 +       /** register bits */
53811 +       struct {
53812 +               unsigned sesreqscs:1;
53813 +               unsigned sesreq:1;
53814 +               unsigned vbvalidoven:1;
53815 +               unsigned vbvalidovval:1;
53816 +               unsigned avalidoven:1;
53817 +               unsigned avalidovval:1;
53818 +               unsigned bvalidoven:1;
53819 +               unsigned bvalidovval:1;
53820 +               unsigned hstnegscs:1;
53821 +               unsigned hnpreq:1;
53822 +               unsigned hstsethnpen:1;
53823 +               unsigned devhnpen:1;
53824 +               unsigned reserved12_15:4;
53825 +               unsigned conidsts:1;
53826 +               unsigned dbnctime:1;
53827 +               unsigned asesvld:1;
53828 +               unsigned bsesvld:1;
53829 +               unsigned otgver:1;
53830 +               unsigned reserved1:1;
53831 +               unsigned multvalidbc:5;
53832 +               unsigned chirpen:1;
53833 +               unsigned reserved28_31:4;
53834 +       } b;
53835 +} gotgctl_data_t;
53836 +
53837 +/**
53838 + * This union represents the bit fields of the Core OTG Interrupt Register
53839 + * (GOTGINT).  Set/clear the bits using the bit fields then write the <i>d32</i>
53840 + * value to the register.
53841 + */
53842 +typedef union gotgint_data {
53843 +       /** raw register data */
53844 +       uint32_t d32;
53845 +       /** register bits */
53846 +       struct {
53847 +               /** Current Mode */
53848 +               unsigned reserved0_1:2;
53849 +
53850 +               /** Session End Detected */
53851 +               unsigned sesenddet:1;
53852 +
53853 +               unsigned reserved3_7:5;
53854 +
53855 +               /** Session Request Success Status Change */
53856 +               unsigned sesreqsucstschng:1;
53857 +               /** Host Negotiation Success Status Change */
53858 +               unsigned hstnegsucstschng:1;
53859 +
53860 +               unsigned reserved10_16:7;
53861 +
53862 +               /** Host Negotiation Detected */
53863 +               unsigned hstnegdet:1;
53864 +               /** A-Device Timeout Change */
53865 +               unsigned adevtoutchng:1;
53866 +               /** Debounce Done */
53867 +               unsigned debdone:1;
53868 +               /** Multi-Valued input changed */
53869 +               unsigned mvic:1;
53870 +
53871 +               unsigned reserved31_21:11;
53872 +
53873 +       } b;
53874 +} gotgint_data_t;
53875 +
53876 +/**
53877 + * This union represents the bit fields of the Core AHB Configuration
53878 + * Register (GAHBCFG). Set/clear the bits using the bit fields then
53879 + * write the <i>d32</i> value to the register.
53880 + */
53881 +typedef union gahbcfg_data {
53882 +       /** raw register data */
53883 +       uint32_t d32;
53884 +       /** register bits */
53885 +       struct {
53886 +               unsigned glblintrmsk:1;
53887 +#define DWC_GAHBCFG_GLBINT_ENABLE              1
53888 +
53889 +               unsigned hburstlen:4;
53890 +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE       0
53891 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR         1
53892 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4                3
53893 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8                5
53894 +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16       7
53895 +
53896 +               unsigned dmaenable:1;
53897 +#define DWC_GAHBCFG_DMAENABLE                  1
53898 +               unsigned reserved:1;
53899 +               unsigned nptxfemplvl_txfemplvl:1;
53900 +               unsigned ptxfemplvl:1;
53901 +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY          1
53902 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY      0
53903 +               unsigned reserved9_20:12;
53904 +               unsigned remmemsupp:1;
53905 +               unsigned notialldmawrit:1;
53906 +               unsigned ahbsingle:1;
53907 +               unsigned reserved24_31:8;
53908 +       } b;
53909 +} gahbcfg_data_t;
53910 +
53911 +/**
53912 + * This union represents the bit fields of the Core USB Configuration
53913 + * Register (GUSBCFG). Set the bits using the bit fields then write
53914 + * the <i>d32</i> value to the register.
53915 + */
53916 +typedef union gusbcfg_data {
53917 +       /** raw register data */
53918 +       uint32_t d32;
53919 +       /** register bits */
53920 +       struct {
53921 +               unsigned toutcal:3;
53922 +               unsigned phyif:1;
53923 +               unsigned ulpi_utmi_sel:1;
53924 +               unsigned fsintf:1;
53925 +               unsigned physel:1;
53926 +               unsigned ddrsel:1;
53927 +               unsigned srpcap:1;
53928 +               unsigned hnpcap:1;
53929 +               unsigned usbtrdtim:4;
53930 +               unsigned reserved1:1;
53931 +               unsigned phylpwrclksel:1;
53932 +               unsigned otgutmifssel:1;
53933 +               unsigned ulpi_fsls:1;
53934 +               unsigned ulpi_auto_res:1;
53935 +               unsigned ulpi_clk_sus_m:1;
53936 +               unsigned ulpi_ext_vbus_drv:1;
53937 +               unsigned ulpi_int_vbus_indicator:1;
53938 +               unsigned term_sel_dl_pulse:1;
53939 +               unsigned indicator_complement:1;
53940 +               unsigned indicator_pass_through:1;
53941 +               unsigned ulpi_int_prot_dis:1;
53942 +               unsigned ic_usb_cap:1;
53943 +               unsigned ic_traffic_pull_remove:1;
53944 +               unsigned tx_end_delay:1;
53945 +               unsigned force_host_mode:1;
53946 +               unsigned force_dev_mode:1;
53947 +               unsigned reserved31:1;
53948 +       } b;
53949 +} gusbcfg_data_t;
53950 +
53951 +/**
53952 + * This union represents the bit fields of the Core Reset Register
53953 + * (GRSTCTL).  Set/clear the bits using the bit fields then write the
53954 + * <i>d32</i> value to the register.
53955 + */
53956 +typedef union grstctl_data {
53957 +       /** raw register data */
53958 +       uint32_t d32;
53959 +       /** register bits */
53960 +       struct {
53961 +               /** Core Soft Reset (CSftRst) (Device and Host)
53962 +                *
53963 +                * The application can flush the control logic in the
53964 +                * entire core using this bit. This bit resets the
53965 +                * pipelines in the AHB Clock domain as well as the
53966 +                * PHY Clock domain.
53967 +                *
53968 +                * The state machines are reset to an IDLE state, the
53969 +                * control bits in the CSRs are cleared, all the
53970 +                * transmit FIFOs and the receive FIFO are flushed.
53971 +                *
53972 +                * The status mask bits that control the generation of
53973 +                * the interrupt, are cleared, to clear the
53974 +                * interrupt. The interrupt status bits are not
53975 +                * cleared, so the application can get the status of
53976 +                * any events that occurred in the core after it has
53977 +                * set this bit.
53978 +                *
53979 +                * Any transactions on the AHB are terminated as soon
53980 +                * as possible following the protocol. Any
53981 +                * transactions on the USB are terminated immediately.
53982 +                *
53983 +                * The configuration settings in the CSRs are
53984 +                * unchanged, so the software doesn't have to
53985 +                * reprogram these registers (Device
53986 +                * Configuration/Host Configuration/Core System
53987 +                * Configuration/Core PHY Configuration).
53988 +                *
53989 +                * The application can write to this bit, any time it
53990 +                * wants to reset the core. This is a self clearing
53991 +                * bit and the core clears this bit after all the
53992 +                * necessary logic is reset in the core, which may
53993 +                * take several clocks, depending on the current state
53994 +                * of the core.
53995 +                */
53996 +               unsigned csftrst:1;
53997 +               /** Hclk Soft Reset
53998 +                *
53999 +                * The application uses this bit to reset the control logic in
54000 +                * the AHB clock domain. Only AHB clock domain pipelines are
54001 +                * reset.
54002 +                */
54003 +               unsigned hsftrst:1;
54004 +               /** Host Frame Counter Reset (Host Only)<br>
54005 +                *
54006 +                * The application can reset the (micro)frame number
54007 +                * counter inside the core, using this bit. When the
54008 +                * (micro)frame counter is reset, the subsequent SOF
54009 +                * sent out by the core, will have a (micro)frame
54010 +                * number of 0.
54011 +                */
54012 +               unsigned hstfrm:1;
54013 +               /** In Token Sequence Learning Queue Flush
54014 +                * (INTknQFlsh) (Device Only)
54015 +                */
54016 +               unsigned intknqflsh:1;
54017 +               /** RxFIFO Flush (RxFFlsh) (Device and Host)
54018 +                *
54019 +                * The application can flush the entire Receive FIFO
54020 +                * using this bit. The application must first
54021 +                * ensure that the core is not in the middle of a
54022 +                * transaction. The application should write into
54023 +                * this bit, only after making sure that neither the
54024 +                * DMA engine is reading from the RxFIFO nor the MAC
54025 +                * is writing the data in to the FIFO. The
54026 +                * application should wait until the bit is cleared
54027 +                * before performing any other operations. This bit
54028 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54029 +                * to clear.
54030 +                */
54031 +               unsigned rxfflsh:1;
54032 +               /** TxFIFO Flush (TxFFlsh) (Device and Host).
54033 +                *
54034 +                * This bit is used to selectively flush a single or
54035 +                * all transmit FIFOs. The application must first
54036 +                * ensure that the core is not in the middle of a
54037 +                * transaction. The application should write into
54038 +                * this bit, only after making sure that neither the
54039 +                * DMA engine is writing into the TxFIFO nor the MAC
54040 +                * is reading the data out of the FIFO. The
54041 +                * application should wait until the core clears this
54042 +                * bit, before performing any operations. This bit
54043 +                * will takes 8 clocks (slowest of PHY or AHB clock)
54044 +                * to clear.
54045 +                */
54046 +               unsigned txfflsh:1;
54047 +
54048 +               /** TxFIFO Number (TxFNum) (Device and Host).
54049 +                *
54050 +                * This is the FIFO number which needs to be flushed,
54051 +                * using the TxFIFO Flush bit. This field should not
54052 +                * be changed until the TxFIFO Flush bit is cleared by
54053 +                * the core.
54054 +                *       - 0x0 : Non Periodic TxFIFO Flush
54055 +                *       - 0x1 : Periodic TxFIFO #1 Flush in device mode
54056 +                *         or Periodic TxFIFO in host mode
54057 +                *       - 0x2 : Periodic TxFIFO #2 Flush in device mode.
54058 +                *       - ...
54059 +                *       - 0xF : Periodic TxFIFO #15 Flush in device mode
54060 +                *       - 0x10: Flush all the Transmit NonPeriodic and
54061 +                *         Transmit Periodic FIFOs in the core
54062 +                */
54063 +               unsigned txfnum:5;
54064 +               /** Reserved */
54065 +               unsigned reserved11_29:19;
54066 +               /** DMA Request Signal.  Indicated DMA request is in
54067 +                * probress. Used for debug purpose. */
54068 +               unsigned dmareq:1;
54069 +               /** AHB Master Idle.  Indicates the AHB Master State
54070 +                * Machine is in IDLE condition. */
54071 +               unsigned ahbidle:1;
54072 +       } b;
54073 +} grstctl_t;
54074 +
54075 +/**
54076 + * This union represents the bit fields of the Core Interrupt Mask
54077 + * Register (GINTMSK). Set/clear the bits using the bit fields then
54078 + * write the <i>d32</i> value to the register.
54079 + */
54080 +typedef union gintmsk_data {
54081 +       /** raw register data */
54082 +       uint32_t d32;
54083 +       /** register bits */
54084 +       struct {
54085 +               unsigned reserved0:1;
54086 +               unsigned modemismatch:1;
54087 +               unsigned otgintr:1;
54088 +               unsigned sofintr:1;
54089 +               unsigned rxstsqlvl:1;
54090 +               unsigned nptxfempty:1;
54091 +               unsigned ginnakeff:1;
54092 +               unsigned goutnakeff:1;
54093 +               unsigned ulpickint:1;
54094 +               unsigned i2cintr:1;
54095 +               unsigned erlysuspend:1;
54096 +               unsigned usbsuspend:1;
54097 +               unsigned usbreset:1;
54098 +               unsigned enumdone:1;
54099 +               unsigned isooutdrop:1;
54100 +               unsigned eopframe:1;
54101 +               unsigned restoredone:1;
54102 +               unsigned epmismatch:1;
54103 +               unsigned inepintr:1;
54104 +               unsigned outepintr:1;
54105 +               unsigned incomplisoin:1;
54106 +               unsigned incomplisoout:1;
54107 +               unsigned fetsusp:1;
54108 +               unsigned resetdet:1;
54109 +               unsigned portintr:1;
54110 +               unsigned hcintr:1;
54111 +               unsigned ptxfempty:1;
54112 +               unsigned lpmtranrcvd:1;
54113 +               unsigned conidstschng:1;
54114 +               unsigned disconnect:1;
54115 +               unsigned sessreqintr:1;
54116 +               unsigned wkupintr:1;
54117 +       } b;
54118 +} gintmsk_data_t;
54119 +/**
54120 + * This union represents the bit fields of the Core Interrupt Register
54121 + * (GINTSTS).  Set/clear the bits using the bit fields then write the
54122 + * <i>d32</i> value to the register.
54123 + */
54124 +typedef union gintsts_data {
54125 +       /** raw register data */
54126 +       uint32_t d32;
54127 +#define DWC_SOF_INTR_MASK 0x0008
54128 +       /** register bits */
54129 +       struct {
54130 +#define DWC_HOST_MODE 1
54131 +               unsigned curmode:1;
54132 +               unsigned modemismatch:1;
54133 +               unsigned otgintr:1;
54134 +               unsigned sofintr:1;
54135 +               unsigned rxstsqlvl:1;
54136 +               unsigned nptxfempty:1;
54137 +               unsigned ginnakeff:1;
54138 +               unsigned goutnakeff:1;
54139 +               unsigned ulpickint:1;
54140 +               unsigned i2cintr:1;
54141 +               unsigned erlysuspend:1;
54142 +               unsigned usbsuspend:1;
54143 +               unsigned usbreset:1;
54144 +               unsigned enumdone:1;
54145 +               unsigned isooutdrop:1;
54146 +               unsigned eopframe:1;
54147 +               unsigned restoredone:1;
54148 +               unsigned epmismatch:1;
54149 +               unsigned inepint:1;
54150 +               unsigned outepintr:1;
54151 +               unsigned incomplisoin:1;
54152 +               unsigned incomplisoout:1;
54153 +               unsigned fetsusp:1;
54154 +               unsigned resetdet:1;
54155 +               unsigned portintr:1;
54156 +               unsigned hcintr:1;
54157 +               unsigned ptxfempty:1;
54158 +               unsigned lpmtranrcvd:1;
54159 +               unsigned conidstschng:1;
54160 +               unsigned disconnect:1;
54161 +               unsigned sessreqintr:1;
54162 +               unsigned wkupintr:1;
54163 +       } b;
54164 +} gintsts_data_t;
54165 +
54166 +/**
54167 + * This union represents the bit fields in the Device Receive Status Read and
54168 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54169 + * element then read out the bits using the <i>b</i>it elements.
54170 + */
54171 +typedef union device_grxsts_data {
54172 +       /** raw register data */
54173 +       uint32_t d32;
54174 +       /** register bits */
54175 +       struct {
54176 +               unsigned epnum:4;
54177 +               unsigned bcnt:11;
54178 +               unsigned dpid:2;
54179 +
54180 +#define DWC_STS_DATA_UPDT              0x2     // OUT Data Packet
54181 +#define DWC_STS_XFER_COMP              0x3     // OUT Data Transfer Complete
54182 +
54183 +#define DWC_DSTS_GOUT_NAK              0x1     // Global OUT NAK
54184 +#define DWC_DSTS_SETUP_COMP            0x4     // Setup Phase Complete
54185 +#define DWC_DSTS_SETUP_UPDT 0x6        // SETUP Packet
54186 +               unsigned pktsts:4;
54187 +               unsigned fn:4;
54188 +               unsigned reserved25_31:7;
54189 +       } b;
54190 +} device_grxsts_data_t;
54191 +
54192 +/**
54193 + * This union represents the bit fields in the Host Receive Status Read and
54194 + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
54195 + * element then read out the bits using the <i>b</i>it elements.
54196 + */
54197 +typedef union host_grxsts_data {
54198 +       /** raw register data */
54199 +       uint32_t d32;
54200 +       /** register bits */
54201 +       struct {
54202 +               unsigned chnum:4;
54203 +               unsigned bcnt:11;
54204 +               unsigned dpid:2;
54205 +
54206 +               unsigned pktsts:4;
54207 +#define DWC_GRXSTS_PKTSTS_IN                     0x2
54208 +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP   0x3
54209 +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
54210 +#define DWC_GRXSTS_PKTSTS_CH_HALTED              0x7
54211 +
54212 +               unsigned reserved21_31:11;
54213 +       } b;
54214 +} host_grxsts_data_t;
54215 +
54216 +/**
54217 + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
54218 + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element
54219 + * then read out the bits using the <i>b</i>it elements.
54220 + */
54221 +typedef union fifosize_data {
54222 +       /** raw register data */
54223 +       uint32_t d32;
54224 +       /** register bits */
54225 +       struct {
54226 +               unsigned startaddr:16;
54227 +               unsigned depth:16;
54228 +       } b;
54229 +} fifosize_data_t;
54230 +
54231 +/**
54232 + * This union represents the bit fields in the Non-Periodic Transmit
54233 + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
54234 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54235 + * elements.
54236 + */
54237 +typedef union gnptxsts_data {
54238 +       /** raw register data */
54239 +       uint32_t d32;
54240 +       /** register bits */
54241 +       struct {
54242 +               unsigned nptxfspcavail:16;
54243 +               unsigned nptxqspcavail:8;
54244 +               /** Top of the Non-Periodic Transmit Request Queue
54245 +                *      - bit 24 - Terminate (Last entry for the selected
54246 +                *        channel/EP)
54247 +                *      - bits 26:25 - Token Type
54248 +                *        - 2'b00 - IN/OUT
54249 +                *        - 2'b01 - Zero Length OUT
54250 +                *        - 2'b10 - PING/Complete Split
54251 +                *        - 2'b11 - Channel Halt
54252 +                *      - bits 30:27 - Channel/EP Number
54253 +                */
54254 +               unsigned nptxqtop_terminate:1;
54255 +               unsigned nptxqtop_token:2;
54256 +               unsigned nptxqtop_chnep:4;
54257 +               unsigned reserved:1;
54258 +       } b;
54259 +} gnptxsts_data_t;
54260 +
54261 +/**
54262 + * This union represents the bit fields in the Transmit
54263 + * FIFO Status Register (DTXFSTS). Read the register into the
54264 + * <i>d32</i> element then read out the bits using the <i>b</i>it
54265 + * elements.
54266 + */
54267 +typedef union dtxfsts_data {
54268 +       /** raw register data */
54269 +       uint32_t d32;
54270 +       /** register bits */
54271 +       struct {
54272 +               unsigned txfspcavail:16;
54273 +               unsigned reserved:16;
54274 +       } b;
54275 +} dtxfsts_data_t;
54276 +
54277 +/**
54278 + * This union represents the bit fields in the I2C Control Register
54279 + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
54280 + * bits using the <i>b</i>it elements.
54281 + */
54282 +typedef union gi2cctl_data {
54283 +       /** raw register data */
54284 +       uint32_t d32;
54285 +       /** register bits */
54286 +       struct {
54287 +               unsigned rwdata:8;
54288 +               unsigned regaddr:8;
54289 +               unsigned addr:7;
54290 +               unsigned i2cen:1;
54291 +               unsigned ack:1;
54292 +               unsigned i2csuspctl:1;
54293 +               unsigned i2cdevaddr:2;
54294 +               unsigned i2cdatse0:1;
54295 +               unsigned reserved:1;
54296 +               unsigned rw:1;
54297 +               unsigned bsydne:1;
54298 +       } b;
54299 +} gi2cctl_data_t;
54300 +
54301 +/**
54302 + * This union represents the bit fields in the PHY Vendor Control Register
54303 + * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the
54304 + * bits using the <i>b</i>it elements.
54305 + */
54306 +typedef union gpvndctl_data {
54307 +       /** raw register data */
54308 +       uint32_t d32;
54309 +       /** register bits */
54310 +       struct {
54311 +               unsigned regdata:8;
54312 +               unsigned vctrl:8;
54313 +               unsigned regaddr16_21:6;
54314 +               unsigned regwr:1;
54315 +               unsigned reserved23_24:2;
54316 +               unsigned newregreq:1;
54317 +               unsigned vstsbsy:1;
54318 +               unsigned vstsdone:1;
54319 +               unsigned reserved28_30:3;
54320 +               unsigned disulpidrvr:1;
54321 +       } b;
54322 +} gpvndctl_data_t;
54323 +
54324 +/**
54325 + * This union represents the bit fields in the General Purpose
54326 + * Input/Output Register (GGPIO).
54327 + * Read the register into the <i>d32</i> element then read out the
54328 + * bits using the <i>b</i>it elements.
54329 + */
54330 +typedef union ggpio_data {
54331 +       /** raw register data */
54332 +       uint32_t d32;
54333 +       /** register bits */
54334 +       struct {
54335 +               unsigned gpi:16;
54336 +               unsigned gpo:16;
54337 +       } b;
54338 +} ggpio_data_t;
54339 +
54340 +/**
54341 + * This union represents the bit fields in the User ID Register
54342 + * (GUID). Read the register into the <i>d32</i> element then read out the
54343 + * bits using the <i>b</i>it elements.
54344 + */
54345 +typedef union guid_data {
54346 +       /** raw register data */
54347 +       uint32_t d32;
54348 +       /** register bits */
54349 +       struct {
54350 +               unsigned rwdata:32;
54351 +       } b;
54352 +} guid_data_t;
54353 +
54354 +/**
54355 + * This union represents the bit fields in the Synopsys ID Register
54356 + * (GSNPSID). Read the register into the <i>d32</i> element then read out the
54357 + * bits using the <i>b</i>it elements.
54358 + */
54359 +typedef union gsnpsid_data {
54360 +       /** raw register data */
54361 +       uint32_t d32;
54362 +       /** register bits */
54363 +       struct {
54364 +               unsigned rwdata:32;
54365 +       } b;
54366 +} gsnpsid_data_t;
54367 +
54368 +/**
54369 + * This union represents the bit fields in the User HW Config1
54370 + * Register.  Read the register into the <i>d32</i> element then read
54371 + * out the bits using the <i>b</i>it elements.
54372 + */
54373 +typedef union hwcfg1_data {
54374 +       /** raw register data */
54375 +       uint32_t d32;
54376 +       /** register bits */
54377 +       struct {
54378 +               unsigned ep_dir0:2;
54379 +               unsigned ep_dir1:2;
54380 +               unsigned ep_dir2:2;
54381 +               unsigned ep_dir3:2;
54382 +               unsigned ep_dir4:2;
54383 +               unsigned ep_dir5:2;
54384 +               unsigned ep_dir6:2;
54385 +               unsigned ep_dir7:2;
54386 +               unsigned ep_dir8:2;
54387 +               unsigned ep_dir9:2;
54388 +               unsigned ep_dir10:2;
54389 +               unsigned ep_dir11:2;
54390 +               unsigned ep_dir12:2;
54391 +               unsigned ep_dir13:2;
54392 +               unsigned ep_dir14:2;
54393 +               unsigned ep_dir15:2;
54394 +       } b;
54395 +} hwcfg1_data_t;
54396 +
54397 +/**
54398 + * This union represents the bit fields in the User HW Config2
54399 + * Register.  Read the register into the <i>d32</i> element then read
54400 + * out the bits using the <i>b</i>it elements.
54401 + */
54402 +typedef union hwcfg2_data {
54403 +       /** raw register data */
54404 +       uint32_t d32;
54405 +       /** register bits */
54406 +       struct {
54407 +               /* GHWCFG2 */
54408 +               unsigned op_mode:3;
54409 +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
54410 +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
54411 +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
54412 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
54413 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
54414 +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
54415 +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
54416 +
54417 +               unsigned architecture:2;
54418 +               unsigned point2point:1;
54419 +               unsigned hs_phy_type:2;
54420 +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
54421 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
54422 +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
54423 +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
54424 +
54425 +               unsigned fs_phy_type:2;
54426 +               unsigned num_dev_ep:4;
54427 +               unsigned num_host_chan:4;
54428 +               unsigned perio_ep_supported:1;
54429 +               unsigned dynamic_fifo:1;
54430 +               unsigned multi_proc_int:1;
54431 +               unsigned reserved21:1;
54432 +               unsigned nonperio_tx_q_depth:2;
54433 +               unsigned host_perio_tx_q_depth:2;
54434 +               unsigned dev_token_q_depth:5;
54435 +               unsigned otg_enable_ic_usb:1;
54436 +       } b;
54437 +} hwcfg2_data_t;
54438 +
54439 +/**
54440 + * This union represents the bit fields in the User HW Config3
54441 + * Register.  Read the register into the <i>d32</i> element then read
54442 + * out the bits using the <i>b</i>it elements.
54443 + */
54444 +typedef union hwcfg3_data {
54445 +       /** raw register data */
54446 +       uint32_t d32;
54447 +       /** register bits */
54448 +       struct {
54449 +               /* GHWCFG3 */
54450 +               unsigned xfer_size_cntr_width:4;
54451 +               unsigned packet_size_cntr_width:3;
54452 +               unsigned otg_func:1;
54453 +               unsigned i2c:1;
54454 +               unsigned vendor_ctrl_if:1;
54455 +               unsigned optional_features:1;
54456 +               unsigned synch_reset_type:1;
54457 +               unsigned adp_supp:1;
54458 +               unsigned otg_enable_hsic:1;
54459 +               unsigned bc_support:1;
54460 +               unsigned otg_lpm_en:1;
54461 +               unsigned dfifo_depth:16;
54462 +       } b;
54463 +} hwcfg3_data_t;
54464 +
54465 +/**
54466 + * This union represents the bit fields in the User HW Config4
54467 + * Register.  Read the register into the <i>d32</i> element then read
54468 + * out the bits using the <i>b</i>it elements.
54469 + */
54470 +typedef union hwcfg4_data {
54471 +       /** raw register data */
54472 +       uint32_t d32;
54473 +       /** register bits */
54474 +       struct {
54475 +               unsigned num_dev_perio_in_ep:4;
54476 +               unsigned power_optimiz:1;
54477 +               unsigned min_ahb_freq:1;
54478 +               unsigned hiber:1;
54479 +               unsigned xhiber:1;
54480 +               unsigned reserved:6;
54481 +               unsigned utmi_phy_data_width:2;
54482 +               unsigned num_dev_mode_ctrl_ep:4;
54483 +               unsigned iddig_filt_en:1;
54484 +               unsigned vbus_valid_filt_en:1;
54485 +               unsigned a_valid_filt_en:1;
54486 +               unsigned b_valid_filt_en:1;
54487 +               unsigned session_end_filt_en:1;
54488 +               unsigned ded_fifo_en:1;
54489 +               unsigned num_in_eps:4;
54490 +               unsigned desc_dma:1;
54491 +               unsigned desc_dma_dyn:1;
54492 +       } b;
54493 +} hwcfg4_data_t;
54494 +
54495 +/**
54496 + * This union represents the bit fields of the Core LPM Configuration
54497 + * Register (GLPMCFG). Set the bits using bit fields then write
54498 + * the <i>d32</i> value to the register.
54499 + */
54500 +typedef union glpmctl_data {
54501 +       /** raw register data */
54502 +       uint32_t d32;
54503 +       /** register bits */
54504 +       struct {
54505 +               /** LPM-Capable (LPMCap) (Device and Host)
54506 +                * The application uses this bit to control
54507 +                * the DWC_otg core LPM capabilities.
54508 +                */
54509 +               unsigned lpm_cap_en:1;
54510 +               /** LPM response programmed by application (AppL1Res) (Device)
54511 +                * Handshake response to LPM token pre-programmed
54512 +                * by device application software.
54513 +                */
54514 +               unsigned appl_resp:1;
54515 +               /** Host Initiated Resume Duration (HIRD) (Device and Host)
54516 +                * In Host mode this field indicates the value of HIRD
54517 +                * to be sent in an LPM transaction.
54518 +                * In Device mode this field is updated with the
54519 +                * Received LPM Token HIRD bmAttribute
54520 +                * when an ACK/NYET/STALL response is sent
54521 +                * to an LPM transaction.
54522 +                */
54523 +               unsigned hird:4;
54524 +               /** RemoteWakeEnable (bRemoteWake) (Device and Host)
54525 +                * In Host mode this bit indicates the value of remote
54526 +                * wake up to be sent in wIndex field of LPM transaction.
54527 +                * In Device mode this field is updated with the
54528 +                * Received LPM Token bRemoteWake bmAttribute
54529 +                * when an ACK/NYET/STALL response is sent
54530 +                * to an LPM transaction.
54531 +                */
54532 +               unsigned rem_wkup_en:1;
54533 +               /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
54534 +                * The application uses this bit to control
54535 +                * the utmi_sleep_n assertion to the PHY when in L1 state.
54536 +                */
54537 +               unsigned en_utmi_sleep:1;
54538 +               /** HIRD Threshold (HIRD_Thres) (Device and Host)
54539 +                */
54540 +               unsigned hird_thres:5;
54541 +               /** LPM Response (CoreL1Res) (Device and Host)
54542 +                * In Host mode this bit contains handsake response to
54543 +                * LPM transaction.
54544 +                * In Device mode the response of the core to
54545 +                * LPM transaction received is reflected in these two bits.
54546 +                       - 0x0 : ERROR (No handshake response)
54547 +                       - 0x1 : STALL
54548 +                       - 0x2 : NYET
54549 +                       - 0x3 : ACK
54550 +                */
54551 +               unsigned lpm_resp:2;
54552 +               /** Port Sleep Status (SlpSts) (Device and Host)
54553 +                * This bit is set as long as a Sleep condition
54554 +                * is present on the USB bus.
54555 +                */
54556 +               unsigned prt_sleep_sts:1;
54557 +               /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
54558 +                * Indicates that the application or host
54559 +                * can start resume from Sleep state.
54560 +                */
54561 +               unsigned sleep_state_resumeok:1;
54562 +               /** LPM channel Index (LPM_Chnl_Indx) (Host)
54563 +                * The channel number on which the LPM transaction
54564 +                * has to be applied while sending
54565 +                * an LPM transaction to the local device.
54566 +                */
54567 +               unsigned lpm_chan_index:4;
54568 +               /** LPM Retry Count (LPM_Retry_Cnt) (Host)
54569 +                * Number host retries that would be performed
54570 +                * if the device response was not valid response.
54571 +                */
54572 +               unsigned retry_count:3;
54573 +               /** Send LPM Transaction (SndLPM) (Host)
54574 +                * When set by application software,
54575 +                * an LPM transaction containing two tokens
54576 +                * is sent.
54577 +                */
54578 +               unsigned send_lpm:1;
54579 +               /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
54580 +                * Number of LPM Host Retries still remaining
54581 +                * to be transmitted for the current LPM sequence
54582 +                */
54583 +               unsigned retry_count_sts:3;
54584 +               unsigned reserved28_29:2;
54585 +               /** In host mode once this bit is set, the host
54586 +                * configures to drive the HSIC Idle state on the bus.
54587 +                * It then waits for the  device to initiate the Connect sequence.
54588 +                * In device mode once this bit is set, the device waits for
54589 +                * the HSIC Idle line state on the bus. Upon receving the Idle
54590 +                * line state, it initiates the HSIC Connect sequence.
54591 +                */
54592 +               unsigned hsic_connect:1;
54593 +               /** This bit overrides and functionally inverts
54594 +                * the if_select_hsic input port signal.
54595 +                */
54596 +               unsigned inv_sel_hsic:1;
54597 +       } b;
54598 +} glpmcfg_data_t;
54599 +
54600 +/**
54601 + * This union represents the bit fields of the Core ADP Timer, Control and
54602 + * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write
54603 + * the <i>d32</i> value to the register.
54604 + */
54605 +typedef union adpctl_data {
54606 +       /** raw register data */
54607 +       uint32_t d32;
54608 +       /** register bits */
54609 +       struct {
54610 +               /** Probe Discharge (PRB_DSCHG)
54611 +                *  These bits set the times for TADP_DSCHG.
54612 +                *  These bits are defined as follows:
54613 +                *  2'b00 - 4 msec
54614 +                *  2'b01 - 8 msec
54615 +                *  2'b10 - 16 msec
54616 +                *  2'b11 - 32 msec
54617 +                */
54618 +               unsigned prb_dschg:2;
54619 +               /** Probe Delta (PRB_DELTA)
54620 +                *  These bits set the resolution for RTIM   value.
54621 +                *  The bits are defined in units of 32 kHz clock cycles as follows:
54622 +                *  2'b00  -  1 cycles
54623 +                *  2'b01  -  2 cycles
54624 +                *  2'b10 -  3 cycles
54625 +                *  2'b11 - 4 cycles
54626 +                *  For example if this value is chosen to 2'b01, it means that RTIM
54627 +                *  increments for every 3(three) 32Khz clock cycles.
54628 +                */
54629 +               unsigned prb_delta:2;
54630 +               /** Probe Period (PRB_PER)
54631 +                *  These bits sets the TADP_PRD as shown in Figure 4 as follows:
54632 +                *  2'b00  -  0.625 to 0.925 sec (typical 0.775 sec)
54633 +                *  2'b01  -  1.25 to 1.85 sec (typical 1.55 sec)
54634 +                *  2'b10  -  1.9 to 2.6 sec (typical 2.275 sec)
54635 +                *  2'b11  -  Reserved
54636 +                */
54637 +               unsigned prb_per:2;
54638 +               /** These bits capture the latest time it took for VBUS to ramp from
54639 +                *  VADP_SINK to VADP_PRB.
54640 +                *  0x000  -  1 cycles
54641 +                *  0x001  -  2 cycles
54642 +                *  0x002  -  3 cycles
54643 +                *  etc
54644 +                *  0x7FF  -  2048 cycles
54645 +                *  A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.
54646 +               */
54647 +               unsigned rtim:11;
54648 +               /** Enable Probe (EnaPrb)
54649 +                *  When programmed to 1'b1, the core performs a probe operation.
54650 +                *  This bit is valid only if OTG_Ver = 1'b1.
54651 +                */
54652 +               unsigned enaprb:1;
54653 +               /** Enable Sense (EnaSns)
54654 +                *  When programmed to 1'b1, the core performs a Sense operation.
54655 +                *  This bit is valid only if OTG_Ver = 1'b1.
54656 +                */
54657 +               unsigned enasns:1;
54658 +               /** ADP Reset (ADPRes)
54659 +                *  When set, ADP controller is reset.
54660 +                *  This bit is valid only if OTG_Ver = 1'b1.
54661 +                */
54662 +               unsigned adpres:1;
54663 +               /** ADP Enable (ADPEn)
54664 +                *  When set, the core performs either ADP probing or sensing
54665 +                *  based on EnaPrb or EnaSns.
54666 +                *  This bit is valid only if OTG_Ver = 1'b1.
54667 +                */
54668 +               unsigned adpen:1;
54669 +               /** ADP Probe Interrupt (ADP_PRB_INT)
54670 +                *  When this bit is set, it means that the VBUS
54671 +                *  voltage is greater than VADP_PRB or VADP_PRB is reached.
54672 +                *  This bit is valid only if OTG_Ver = 1'b1.
54673 +                */
54674 +               unsigned adp_prb_int:1;
54675 +               /**
54676 +                *  ADP Sense Interrupt (ADP_SNS_INT)
54677 +                *  When this bit is set, it means that the VBUS voltage is greater than
54678 +                *  VADP_SNS value or VADP_SNS is reached.
54679 +                *  This bit is valid only if OTG_Ver = 1'b1.
54680 +                */
54681 +               unsigned adp_sns_int:1;
54682 +               /** ADP Tomeout Interrupt (ADP_TMOUT_INT)
54683 +                *  This bit is relevant only for an ADP probe.
54684 +                *  When this bit is set, it means that the ramp time has
54685 +                *  completed ie ADPCTL.RTIM has reached its terminal value
54686 +                *  of 0x7FF.  This is a debug feature that allows software
54687 +                *  to read the ramp time after each cycle.
54688 +                *  This bit is valid only if OTG_Ver = 1'b1.
54689 +                */
54690 +               unsigned adp_tmout_int:1;
54691 +               /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)
54692 +                *  When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.
54693 +                *  This bit is valid only if OTG_Ver = 1'b1.
54694 +                */
54695 +               unsigned adp_prb_int_msk:1;
54696 +               /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)
54697 +                *  When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.
54698 +                *  This bit is valid only if OTG_Ver = 1'b1.
54699 +                */
54700 +               unsigned adp_sns_int_msk:1;
54701 +               /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)
54702 +                *  When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.
54703 +                *  This bit is valid only if OTG_Ver = 1'b1.
54704 +                */
54705 +               unsigned adp_tmout_int_msk:1;
54706 +               /** Access Request
54707 +                * 2'b00 - Read/Write Valid (updated by the core)
54708 +                * 2'b01 - Read
54709 +                * 2'b00 - Write
54710 +                * 2'b00 - Reserved
54711 +                */
54712 +               unsigned ar:2;
54713 +                /** Reserved */
54714 +               unsigned reserved29_31:3;
54715 +       } b;
54716 +} adpctl_data_t;
54717 +
54718 +////////////////////////////////////////////
54719 +// Device Registers
54720 +/**
54721 + * Device Global Registers. <i>Offsets 800h-BFFh</i>
54722 + *
54723 + * The following structures define the size and relative field offsets
54724 + * for the Device Mode Registers.
54725 + *
54726 + * <i>These registers are visible only in Device mode and must not be
54727 + * accessed in Host mode, as the results are unknown.</i>
54728 + */
54729 +typedef struct dwc_otg_dev_global_regs {
54730 +       /** Device Configuration Register. <i>Offset 800h</i> */
54731 +       volatile uint32_t dcfg;
54732 +       /** Device Control Register. <i>Offset: 804h</i> */
54733 +       volatile uint32_t dctl;
54734 +       /** Device Status Register (Read Only). <i>Offset: 808h</i> */
54735 +       volatile uint32_t dsts;
54736 +       /** Reserved. <i>Offset: 80Ch</i> */
54737 +       uint32_t unused;
54738 +       /** Device IN Endpoint Common Interrupt Mask
54739 +        * Register. <i>Offset: 810h</i> */
54740 +       volatile uint32_t diepmsk;
54741 +       /** Device OUT Endpoint Common Interrupt Mask
54742 +        * Register. <i>Offset: 814h</i> */
54743 +       volatile uint32_t doepmsk;
54744 +       /** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */
54745 +       volatile uint32_t daint;
54746 +       /** Device All Endpoints Interrupt Mask Register.  <i>Offset:
54747 +        * 81Ch</i> */
54748 +       volatile uint32_t daintmsk;
54749 +       /** Device IN Token Queue Read Register-1 (Read Only).
54750 +        * <i>Offset: 820h</i> */
54751 +       volatile uint32_t dtknqr1;
54752 +       /** Device IN Token Queue Read Register-2 (Read Only).
54753 +        * <i>Offset: 824h</i> */
54754 +       volatile uint32_t dtknqr2;
54755 +       /** Device VBUS  discharge Register.  <i>Offset: 828h</i> */
54756 +       volatile uint32_t dvbusdis;
54757 +       /** Device VBUS Pulse Register.  <i>Offset: 82Ch</i> */
54758 +       volatile uint32_t dvbuspulse;
54759 +       /** Device IN Token Queue Read Register-3 (Read Only). /
54760 +        *      Device Thresholding control register (Read/Write)
54761 +        * <i>Offset: 830h</i> */
54762 +       volatile uint32_t dtknqr3_dthrctl;
54763 +       /** Device IN Token Queue Read Register-4 (Read Only). /
54764 +        *      Device IN EPs empty Inr. Mask Register (Read/Write)
54765 +        * <i>Offset: 834h</i> */
54766 +       volatile uint32_t dtknqr4_fifoemptymsk;
54767 +       /** Device Each Endpoint Interrupt Register (Read Only). /
54768 +        * <i>Offset: 838h</i> */
54769 +       volatile uint32_t deachint;
54770 +       /** Device Each Endpoint Interrupt mask Register (Read/Write). /
54771 +        * <i>Offset: 83Ch</i> */
54772 +       volatile uint32_t deachintmsk;
54773 +       /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
54774 +        * <i>Offset: 840h</i> */
54775 +       volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
54776 +       /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
54777 +        * <i>Offset: 880h</i> */
54778 +       volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
54779 +} dwc_otg_device_global_regs_t;
54780 +
54781 +/**
54782 + * This union represents the bit fields in the Device Configuration
54783 + * Register.  Read the register into the <i>d32</i> member then
54784 + * set/clear the bits using the <i>b</i>it elements.  Write the
54785 + * <i>d32</i> member to the dcfg register.
54786 + */
54787 +typedef union dcfg_data {
54788 +       /** raw register data */
54789 +       uint32_t d32;
54790 +       /** register bits */
54791 +       struct {
54792 +               /** Device Speed */
54793 +               unsigned devspd:2;
54794 +               /** Non Zero Length Status OUT Handshake */
54795 +               unsigned nzstsouthshk:1;
54796 +#define DWC_DCFG_SEND_STALL 1
54797 +
54798 +               unsigned ena32khzs:1;
54799 +               /** Device Addresses */
54800 +               unsigned devaddr:7;
54801 +               /** Periodic Frame Interval */
54802 +               unsigned perfrint:2;
54803 +#define DWC_DCFG_FRAME_INTERVAL_80 0
54804 +#define DWC_DCFG_FRAME_INTERVAL_85 1
54805 +#define DWC_DCFG_FRAME_INTERVAL_90 2
54806 +#define DWC_DCFG_FRAME_INTERVAL_95 3
54807 +
54808 +               /** Enable Device OUT NAK for bulk in DDMA mode */
54809 +               unsigned endevoutnak:1;
54810 +
54811 +               unsigned reserved14_17:4;
54812 +               /** In Endpoint Mis-match count */
54813 +               unsigned epmscnt:5;
54814 +               /** Enable Descriptor DMA in Device mode */
54815 +               unsigned descdma:1;
54816 +               unsigned perschintvl:2;
54817 +               unsigned resvalid:6;
54818 +       } b;
54819 +} dcfg_data_t;
54820 +
54821 +/**
54822 + * This union represents the bit fields in the Device Control
54823 + * Register.  Read the register into the <i>d32</i> member then
54824 + * set/clear the bits using the <i>b</i>it elements.
54825 + */
54826 +typedef union dctl_data {
54827 +       /** raw register data */
54828 +       uint32_t d32;
54829 +       /** register bits */
54830 +       struct {
54831 +               /** Remote Wakeup */
54832 +               unsigned rmtwkupsig:1;
54833 +               /** Soft Disconnect */
54834 +               unsigned sftdiscon:1;
54835 +               /** Global Non-Periodic IN NAK Status */
54836 +               unsigned gnpinnaksts:1;
54837 +               /** Global OUT NAK Status */
54838 +               unsigned goutnaksts:1;
54839 +               /** Test Control */
54840 +               unsigned tstctl:3;
54841 +               /** Set Global Non-Periodic IN NAK */
54842 +               unsigned sgnpinnak:1;
54843 +               /** Clear Global Non-Periodic IN NAK */
54844 +               unsigned cgnpinnak:1;
54845 +               /** Set Global OUT NAK */
54846 +               unsigned sgoutnak:1;
54847 +               /** Clear Global OUT NAK */
54848 +               unsigned cgoutnak:1;
54849 +               /** Power-On Programming Done */
54850 +               unsigned pwronprgdone:1;
54851 +               /** Reserved */
54852 +               unsigned reserved:1;
54853 +               /** Global Multi Count */
54854 +               unsigned gmc:2;
54855 +               /** Ignore Frame Number for ISOC EPs */
54856 +               unsigned ifrmnum:1;
54857 +               /** NAK on Babble */
54858 +               unsigned nakonbble:1;
54859 +               /** Enable Continue on BNA */
54860 +               unsigned encontonbna:1;
54861 +
54862 +               unsigned reserved18_31:14;
54863 +       } b;
54864 +} dctl_data_t;
54865 +
54866 +/**
54867 + * This union represents the bit fields in the Device Status
54868 + * Register.  Read the register into the <i>d32</i> member then
54869 + * set/clear the bits using the <i>b</i>it elements.
54870 + */
54871 +typedef union dsts_data {
54872 +       /** raw register data */
54873 +       uint32_t d32;
54874 +       /** register bits */
54875 +       struct {
54876 +               /** Suspend Status */
54877 +               unsigned suspsts:1;
54878 +               /** Enumerated Speed */
54879 +               unsigned enumspd:2;
54880 +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
54881 +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
54882 +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ              2
54883 +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ             3
54884 +               /** Erratic Error */
54885 +               unsigned errticerr:1;
54886 +               unsigned reserved4_7:4;
54887 +               /** Frame or Microframe Number of the received SOF */
54888 +               unsigned soffn:14;
54889 +               unsigned reserved22_31:10;
54890 +       } b;
54891 +} dsts_data_t;
54892 +
54893 +/**
54894 + * This union represents the bit fields in the Device IN EP Interrupt
54895 + * Register and the Device IN EP Common Mask Register.
54896 + *
54897 + * - Read the register into the <i>d32</i> member then set/clear the
54898 + *      bits using the <i>b</i>it elements.
54899 + */
54900 +typedef union diepint_data {
54901 +       /** raw register data */
54902 +       uint32_t d32;
54903 +       /** register bits */
54904 +       struct {
54905 +               /** Transfer complete mask */
54906 +               unsigned xfercompl:1;
54907 +               /** Endpoint disable mask */
54908 +               unsigned epdisabled:1;
54909 +               /** AHB Error mask */
54910 +               unsigned ahberr:1;
54911 +               /** TimeOUT Handshake mask (non-ISOC EPs) */
54912 +               unsigned timeout:1;
54913 +               /** IN Token received with TxF Empty mask */
54914 +               unsigned intktxfemp:1;
54915 +               /** IN Token Received with EP mismatch mask */
54916 +               unsigned intknepmis:1;
54917 +               /** IN Endpoint NAK Effective mask */
54918 +               unsigned inepnakeff:1;
54919 +               /** Reserved */
54920 +               unsigned emptyintr:1;
54921 +
54922 +               unsigned txfifoundrn:1;
54923 +
54924 +               /** BNA Interrupt mask */
54925 +               unsigned bna:1;
54926 +
54927 +               unsigned reserved10_12:3;
54928 +               /** BNA Interrupt mask */
54929 +               unsigned nak:1;
54930 +
54931 +               unsigned reserved14_31:18;
54932 +       } b;
54933 +} diepint_data_t;
54934 +
54935 +/**
54936 + * This union represents the bit fields in the Device IN EP
54937 + * Common/Dedicated Interrupt Mask Register.
54938 + */
54939 +typedef union diepint_data diepmsk_data_t;
54940 +
54941 +/**
54942 + * This union represents the bit fields in the Device OUT EP Interrupt
54943 + * Registerand Device OUT EP Common Interrupt Mask Register.
54944 + *
54945 + * - Read the register into the <i>d32</i> member then set/clear the
54946 + *      bits using the <i>b</i>it elements.
54947 + */
54948 +typedef union doepint_data {
54949 +       /** raw register data */
54950 +       uint32_t d32;
54951 +       /** register bits */
54952 +       struct {
54953 +               /** Transfer complete */
54954 +               unsigned xfercompl:1;
54955 +               /** Endpoint disable  */
54956 +               unsigned epdisabled:1;
54957 +               /** AHB Error */
54958 +               unsigned ahberr:1;
54959 +               /** Setup Phase Done (contorl EPs) */
54960 +               unsigned setup:1;
54961 +               /** OUT Token Received when Endpoint Disabled */
54962 +               unsigned outtknepdis:1;
54963 +
54964 +               unsigned stsphsercvd:1;
54965 +               /** Back-to-Back SETUP Packets Received */
54966 +               unsigned back2backsetup:1;
54967 +
54968 +               unsigned reserved7:1;
54969 +               /** OUT packet Error */
54970 +               unsigned outpkterr:1;
54971 +               /** BNA Interrupt */
54972 +               unsigned bna:1;
54973 +
54974 +               unsigned reserved10:1;
54975 +               /** Packet Drop Status */
54976 +               unsigned pktdrpsts:1;
54977 +               /** Babble Interrupt */
54978 +               unsigned babble:1;
54979 +               /** NAK Interrupt */
54980 +               unsigned nak:1;
54981 +               /** NYET Interrupt */
54982 +               unsigned nyet:1;
54983 +               /** Bit indicating setup packet received */
54984 +               unsigned sr:1;
54985 +
54986 +               unsigned reserved16_31:16;
54987 +       } b;
54988 +} doepint_data_t;
54989 +
54990 +/**
54991 + * This union represents the bit fields in the Device OUT EP
54992 + * Common/Dedicated Interrupt Mask Register.
54993 + */
54994 +typedef union doepint_data doepmsk_data_t;
54995 +
54996 +/**
54997 + * This union represents the bit fields in the Device All EP Interrupt
54998 + * and Mask Registers.
54999 + * - Read the register into the <i>d32</i> member then set/clear the
55000 + *      bits using the <i>b</i>it elements.
55001 + */
55002 +typedef union daint_data {
55003 +       /** raw register data */
55004 +       uint32_t d32;
55005 +       /** register bits */
55006 +       struct {
55007 +               /** IN Endpoint bits */
55008 +               unsigned in:16;
55009 +               /** OUT Endpoint bits */
55010 +               unsigned out:16;
55011 +       } ep;
55012 +       struct {
55013 +               /** IN Endpoint bits */
55014 +               unsigned inep0:1;
55015 +               unsigned inep1:1;
55016 +               unsigned inep2:1;
55017 +               unsigned inep3:1;
55018 +               unsigned inep4:1;
55019 +               unsigned inep5:1;
55020 +               unsigned inep6:1;
55021 +               unsigned inep7:1;
55022 +               unsigned inep8:1;
55023 +               unsigned inep9:1;
55024 +               unsigned inep10:1;
55025 +               unsigned inep11:1;
55026 +               unsigned inep12:1;
55027 +               unsigned inep13:1;
55028 +               unsigned inep14:1;
55029 +               unsigned inep15:1;
55030 +               /** OUT Endpoint bits */
55031 +               unsigned outep0:1;
55032 +               unsigned outep1:1;
55033 +               unsigned outep2:1;
55034 +               unsigned outep3:1;
55035 +               unsigned outep4:1;
55036 +               unsigned outep5:1;
55037 +               unsigned outep6:1;
55038 +               unsigned outep7:1;
55039 +               unsigned outep8:1;
55040 +               unsigned outep9:1;
55041 +               unsigned outep10:1;
55042 +               unsigned outep11:1;
55043 +               unsigned outep12:1;
55044 +               unsigned outep13:1;
55045 +               unsigned outep14:1;
55046 +               unsigned outep15:1;
55047 +       } b;
55048 +} daint_data_t;
55049 +
55050 +/**
55051 + * This union represents the bit fields in the Device IN Token Queue
55052 + * Read Registers.
55053 + * - Read the register into the <i>d32</i> member.
55054 + * - READ-ONLY Register
55055 + */
55056 +typedef union dtknq1_data {
55057 +       /** raw register data */
55058 +       uint32_t d32;
55059 +       /** register bits */
55060 +       struct {
55061 +               /** In Token Queue Write Pointer */
55062 +               unsigned intknwptr:5;
55063 +               /** Reserved */
55064 +               unsigned reserved05_06:2;
55065 +               /** write pointer has wrapped. */
55066 +               unsigned wrap_bit:1;
55067 +               /** EP Numbers of IN Tokens 0 ... 4 */
55068 +               unsigned epnums0_5:24;
55069 +       } b;
55070 +} dtknq1_data_t;
55071 +
55072 +/**
55073 + * This union represents Threshold control Register
55074 + * - Read and write the register into the <i>d32</i> member.
55075 + * - READ-WRITABLE Register
55076 + */
55077 +typedef union dthrctl_data {
55078 +       /** raw register data */
55079 +       uint32_t d32;
55080 +       /** register bits */
55081 +       struct {
55082 +               /** non ISO Tx Thr. Enable */
55083 +               unsigned non_iso_thr_en:1;
55084 +               /** ISO Tx Thr. Enable */
55085 +               unsigned iso_thr_en:1;
55086 +               /** Tx Thr. Length */
55087 +               unsigned tx_thr_len:9;
55088 +               /** AHB Threshold ratio */
55089 +               unsigned ahb_thr_ratio:2;
55090 +               /** Reserved */
55091 +               unsigned reserved13_15:3;
55092 +               /** Rx Thr. Enable */
55093 +               unsigned rx_thr_en:1;
55094 +               /** Rx Thr. Length */
55095 +               unsigned rx_thr_len:9;
55096 +               unsigned reserved26:1;
55097 +               /** Arbiter Parking Enable*/
55098 +               unsigned arbprken:1;
55099 +               /** Reserved */
55100 +               unsigned reserved28_31:4;
55101 +       } b;
55102 +} dthrctl_data_t;
55103 +
55104 +/**
55105 + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
55106 + * 900h-AFCh</i>
55107 + *
55108 + * There will be one set of endpoint registers per logical endpoint
55109 + * implemented.
55110 + *
55111 + * <i>These registers are visible only in Device mode and must not be
55112 + * accessed in Host mode, as the results are unknown.</i>
55113 + */
55114 +typedef struct dwc_otg_dev_in_ep_regs {
55115 +       /** Device IN Endpoint Control Register. <i>Offset:900h +
55116 +        * (ep_num * 20h) + 00h</i> */
55117 +       volatile uint32_t diepctl;
55118 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
55119 +       uint32_t reserved04;
55120 +       /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
55121 +        * (ep_num * 20h) + 08h</i> */
55122 +       volatile uint32_t diepint;
55123 +       /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
55124 +       uint32_t reserved0C;
55125 +       /** Device IN Endpoint Transfer Size
55126 +        * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
55127 +       volatile uint32_t dieptsiz;
55128 +       /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
55129 +        * (ep_num * 20h) + 14h</i> */
55130 +       volatile uint32_t diepdma;
55131 +       /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
55132 +        * (ep_num * 20h) + 18h</i> */
55133 +       volatile uint32_t dtxfsts;
55134 +       /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
55135 +        * (ep_num * 20h) + 1Ch</i> */
55136 +       volatile uint32_t diepdmab;
55137 +} dwc_otg_dev_in_ep_regs_t;
55138 +
55139 +/**
55140 + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
55141 + * B00h-CFCh</i>
55142 + *
55143 + * There will be one set of endpoint registers per logical endpoint
55144 + * implemented.
55145 + *
55146 + * <i>These registers are visible only in Device mode and must not be
55147 + * accessed in Host mode, as the results are unknown.</i>
55148 + */
55149 +typedef struct dwc_otg_dev_out_ep_regs {
55150 +       /** Device OUT Endpoint Control Register. <i>Offset:B00h +
55151 +        * (ep_num * 20h) + 00h</i> */
55152 +       volatile uint32_t doepctl;
55153 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
55154 +       uint32_t reserved04;
55155 +       /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
55156 +        * (ep_num * 20h) + 08h</i> */
55157 +       volatile uint32_t doepint;
55158 +       /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
55159 +       uint32_t reserved0C;
55160 +       /** Device OUT Endpoint Transfer Size Register. <i>Offset:
55161 +        * B00h + (ep_num * 20h) + 10h</i> */
55162 +       volatile uint32_t doeptsiz;
55163 +       /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
55164 +        * + (ep_num * 20h) + 14h</i> */
55165 +       volatile uint32_t doepdma;
55166 +       /** Reserved. <i>Offset:B00h +   * (ep_num * 20h) + 18h</i> */
55167 +       uint32_t unused;
55168 +       /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
55169 +        * + (ep_num * 20h) + 1Ch</i> */
55170 +       uint32_t doepdmab;
55171 +} dwc_otg_dev_out_ep_regs_t;
55172 +
55173 +/**
55174 + * This union represents the bit fields in the Device EP Control
55175 + * Register.  Read the register into the <i>d32</i> member then
55176 + * set/clear the bits using the <i>b</i>it elements.
55177 + */
55178 +typedef union depctl_data {
55179 +       /** raw register data */
55180 +       uint32_t d32;
55181 +       /** register bits */
55182 +       struct {
55183 +               /** Maximum Packet Size
55184 +                * IN/OUT EPn
55185 +                * IN/OUT EP0 - 2 bits
55186 +                *       2'b00: 64 Bytes
55187 +                *       2'b01: 32
55188 +                *       2'b10: 16
55189 +                *       2'b11: 8 */
55190 +               unsigned mps:11;
55191 +#define DWC_DEP0CTL_MPS_64      0
55192 +#define DWC_DEP0CTL_MPS_32      1
55193 +#define DWC_DEP0CTL_MPS_16      2
55194 +#define DWC_DEP0CTL_MPS_8       3
55195 +
55196 +               /** Next Endpoint
55197 +                * IN EPn/IN EP0
55198 +                * OUT EPn/OUT EP0 - reserved */
55199 +               unsigned nextep:4;
55200 +
55201 +               /** USB Active Endpoint */
55202 +               unsigned usbactep:1;
55203 +
55204 +               /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
55205 +                * This field contains the PID of the packet going to
55206 +                * be received or transmitted on this endpoint. The
55207 +                * application should program the PID of the first
55208 +                * packet going to be received or transmitted on this
55209 +                * endpoint , after the endpoint is
55210 +                * activated. Application use the SetD1PID and
55211 +                * SetD0PID fields of this register to program either
55212 +                * D0 or D1 PID.
55213 +                *
55214 +                * The encoding for this field is
55215 +                *       - 0: D0
55216 +                *       - 1: D1
55217 +                */
55218 +               unsigned dpid:1;
55219 +
55220 +               /** NAK Status */
55221 +               unsigned naksts:1;
55222 +
55223 +               /** Endpoint Type
55224 +                *      2'b00: Control
55225 +                *      2'b01: Isochronous
55226 +                *      2'b10: Bulk
55227 +                *      2'b11: Interrupt */
55228 +               unsigned eptype:2;
55229 +
55230 +               /** Snoop Mode
55231 +                * OUT EPn/OUT EP0
55232 +                * IN EPn/IN EP0 - reserved */
55233 +               unsigned snp:1;
55234 +
55235 +               /** Stall Handshake */
55236 +               unsigned stall:1;
55237 +
55238 +               /** Tx Fifo Number
55239 +                * IN EPn/IN EP0
55240 +                * OUT EPn/OUT EP0 - reserved */
55241 +               unsigned txfnum:4;
55242 +
55243 +               /** Clear NAK */
55244 +               unsigned cnak:1;
55245 +               /** Set NAK */
55246 +               unsigned snak:1;
55247 +               /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
55248 +                * Writing to this field sets the Endpoint DPID (DPID)
55249 +                * field in this register to DATA0. Set Even
55250 +                * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
55251 +                * Writing to this field sets the Even/Odd
55252 +                * (micro)frame (EO_FrNum) field to even (micro)
55253 +                * frame.
55254 +                */
55255 +               unsigned setd0pid:1;
55256 +               /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
55257 +                * Writing to this field sets the Endpoint DPID (DPID)
55258 +                * field in this register to DATA1 Set Odd
55259 +                * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
55260 +                * Writing to this field sets the Even/Odd
55261 +                * (micro)frame (EO_FrNum) field to odd (micro) frame.
55262 +                */
55263 +               unsigned setd1pid:1;
55264 +
55265 +               /** Endpoint Disable */
55266 +               unsigned epdis:1;
55267 +               /** Endpoint Enable */
55268 +               unsigned epena:1;
55269 +       } b;
55270 +} depctl_data_t;
55271 +
55272 +/**
55273 + * This union represents the bit fields in the Device EP Transfer
55274 + * Size Register.  Read the register into the <i>d32</i> member then
55275 + * set/clear the bits using the <i>b</i>it elements.
55276 + */
55277 +typedef union deptsiz_data {
55278 +               /** raw register data */
55279 +       uint32_t d32;
55280 +               /** register bits */
55281 +       struct {
55282 +               /** Transfer size */
55283 +               unsigned xfersize:19;
55284 +/** Max packet count for EP (pow(2,10)-1) */
55285 +#define MAX_PKT_CNT 1023
55286 +               /** Packet Count */
55287 +               unsigned pktcnt:10;
55288 +               /** Multi Count - Periodic IN endpoints */
55289 +               unsigned mc:2;
55290 +               unsigned reserved:1;
55291 +       } b;
55292 +} deptsiz_data_t;
55293 +
55294 +/**
55295 + * This union represents the bit fields in the Device EP 0 Transfer
55296 + * Size Register.  Read the register into the <i>d32</i> member then
55297 + * set/clear the bits using the <i>b</i>it elements.
55298 + */
55299 +typedef union deptsiz0_data {
55300 +               /** raw register data */
55301 +       uint32_t d32;
55302 +               /** register bits */
55303 +       struct {
55304 +               /** Transfer size */
55305 +               unsigned xfersize:7;
55306 +                               /** Reserved */
55307 +               unsigned reserved7_18:12;
55308 +               /** Packet Count */
55309 +               unsigned pktcnt:2;
55310 +                               /** Reserved */
55311 +               unsigned reserved21_28:8;
55312 +                               /**Setup Packet Count (DOEPTSIZ0 Only) */
55313 +               unsigned supcnt:2;
55314 +               unsigned reserved31;
55315 +       } b;
55316 +} deptsiz0_data_t;
55317 +
55318 +/////////////////////////////////////////////////
55319 +// DMA Descriptor Specific Structures
55320 +//
55321 +
55322 +/** Buffer status definitions */
55323 +
55324 +#define BS_HOST_READY  0x0
55325 +#define BS_DMA_BUSY            0x1
55326 +#define BS_DMA_DONE            0x2
55327 +#define BS_HOST_BUSY   0x3
55328 +
55329 +/** Receive/Transmit status definitions */
55330 +
55331 +#define RTS_SUCCESS            0x0
55332 +#define RTS_BUFFLUSH   0x1
55333 +#define RTS_RESERVED   0x2
55334 +#define RTS_BUFERR             0x3
55335 +
55336 +/**
55337 + * This union represents the bit fields in the DMA Descriptor
55338 + * status quadlet. Read the quadlet into the <i>d32</i> member then
55339 + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
55340 + * <i>b_iso_in</i> elements.
55341 + */
55342 +typedef union dev_dma_desc_sts {
55343 +               /** raw register data */
55344 +       uint32_t d32;
55345 +               /** quadlet bits */
55346 +       struct {
55347 +               /** Received number of bytes */
55348 +               unsigned bytes:16;
55349 +               /** NAK bit - only for OUT EPs */
55350 +               unsigned nak:1;
55351 +               unsigned reserved17_22:6;
55352 +               /** Multiple Transfer - only for OUT EPs */
55353 +               unsigned mtrf:1;
55354 +               /** Setup Packet received - only for OUT EPs */
55355 +               unsigned sr:1;
55356 +               /** Interrupt On Complete */
55357 +               unsigned ioc:1;
55358 +               /** Short Packet */
55359 +               unsigned sp:1;
55360 +               /** Last */
55361 +               unsigned l:1;
55362 +               /** Receive Status */
55363 +               unsigned sts:2;
55364 +               /** Buffer Status */
55365 +               unsigned bs:2;
55366 +       } b;
55367 +
55368 +//#ifdef DWC_EN_ISOC
55369 +               /** iso out quadlet bits */
55370 +       struct {
55371 +               /** Received number of bytes */
55372 +               unsigned rxbytes:11;
55373 +
55374 +               unsigned reserved11:1;
55375 +               /** Frame Number */
55376 +               unsigned framenum:11;
55377 +               /** Received ISO Data PID */
55378 +               unsigned pid:2;
55379 +               /** Interrupt On Complete */
55380 +               unsigned ioc:1;
55381 +               /** Short Packet */
55382 +               unsigned sp:1;
55383 +               /** Last */
55384 +               unsigned l:1;
55385 +               /** Receive Status */
55386 +               unsigned rxsts:2;
55387 +               /** Buffer Status */
55388 +               unsigned bs:2;
55389 +       } b_iso_out;
55390 +
55391 +               /** iso in quadlet bits */
55392 +       struct {
55393 +               /** Transmited number of bytes */
55394 +               unsigned txbytes:12;
55395 +               /** Frame Number */
55396 +               unsigned framenum:11;
55397 +               /** Transmited ISO Data PID */
55398 +               unsigned pid:2;
55399 +               /** Interrupt On Complete */
55400 +               unsigned ioc:1;
55401 +               /** Short Packet */
55402 +               unsigned sp:1;
55403 +               /** Last */
55404 +               unsigned l:1;
55405 +               /** Transmit Status */
55406 +               unsigned txsts:2;
55407 +               /** Buffer Status */
55408 +               unsigned bs:2;
55409 +       } b_iso_in;
55410 +//#endif                                /* DWC_EN_ISOC */
55411 +} dev_dma_desc_sts_t;
55412 +
55413 +/**
55414 + * DMA Descriptor structure
55415 + *
55416 + * DMA Descriptor structure contains two quadlets:
55417 + * Status quadlet and Data buffer pointer.
55418 + */
55419 +typedef struct dwc_otg_dev_dma_desc {
55420 +       /** DMA Descriptor status quadlet */
55421 +       dev_dma_desc_sts_t status;
55422 +       /** DMA Descriptor data buffer pointer */
55423 +       uint32_t buf;
55424 +} dwc_otg_dev_dma_desc_t;
55425 +
55426 +/**
55427 + * The dwc_otg_dev_if structure contains information needed to manage
55428 + * the DWC_otg controller acting in device mode. It represents the
55429 + * programming view of the device-specific aspects of the controller.
55430 + */
55431 +typedef struct dwc_otg_dev_if {
55432 +       /** Pointer to device Global registers.
55433 +        * Device Global Registers starting at offset 800h
55434 +        */
55435 +       dwc_otg_device_global_regs_t *dev_global_regs;
55436 +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
55437 +
55438 +       /**
55439 +        * Device Logical IN Endpoint-Specific Registers 900h-AFCh
55440 +        */
55441 +       dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
55442 +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
55443 +#define DWC_EP_REG_OFFSET 0x20
55444 +
55445 +       /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
55446 +       dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
55447 +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
55448 +
55449 +       /* Device configuration information */
55450 +       uint8_t speed;                           /**< Device Speed      0: Unknown, 1: LS, 2:FS, 3: HS */
55451 +       uint8_t num_in_eps;              /**< Number # of Tx EP range: 0-15 exept ep0 */
55452 +       uint8_t num_out_eps;             /**< Number # of Rx EP range: 0-15 exept ep 0*/
55453 +
55454 +       /** Size of periodic FIFOs (Bytes) */
55455 +       uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
55456 +
55457 +       /** Size of Tx FIFOs (Bytes) */
55458 +       uint16_t tx_fifo_size[MAX_TX_FIFOS];
55459 +
55460 +       /** Thresholding enable flags and length varaiables **/
55461 +       uint16_t rx_thr_en;
55462 +       uint16_t iso_tx_thr_en;
55463 +       uint16_t non_iso_tx_thr_en;
55464 +
55465 +       uint16_t rx_thr_length;
55466 +       uint16_t tx_thr_length;
55467 +
55468 +       /**
55469 +        * Pointers to the DMA Descriptors for EP0 Control
55470 +        * transfers (virtual and physical)
55471 +        */
55472 +
55473 +       /** 2 descriptors for SETUP packets */
55474 +       dwc_dma_t dma_setup_desc_addr[2];
55475 +       dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
55476 +
55477 +       /** Pointer to Descriptor with latest SETUP packet */
55478 +       dwc_otg_dev_dma_desc_t *psetup;
55479 +
55480 +       /** Index of current SETUP handler descriptor */
55481 +       uint32_t setup_desc_index;
55482 +
55483 +       /** Descriptor for Data In or Status In phases */
55484 +       dwc_dma_t dma_in_desc_addr;
55485 +       dwc_otg_dev_dma_desc_t *in_desc_addr;
55486 +
55487 +       /** Descriptor for Data Out or Status Out phases */
55488 +       dwc_dma_t dma_out_desc_addr;
55489 +       dwc_otg_dev_dma_desc_t *out_desc_addr;
55490 +
55491 +       /** Setup Packet Detected - if set clear NAK when queueing */
55492 +       uint32_t spd;
55493 +       /** Isoc ep pointer on which incomplete happens */
55494 +       void *isoc_ep;
55495 +
55496 +} dwc_otg_dev_if_t;
55497 +
55498 +/////////////////////////////////////////////////
55499 +// Host Mode Register Structures
55500 +//
55501 +/**
55502 + * The Host Global Registers structure defines the size and relative
55503 + * field offsets for the Host Mode Global Registers.  Host Global
55504 + * Registers offsets 400h-7FFh.
55505 +*/
55506 +typedef struct dwc_otg_host_global_regs {
55507 +       /** Host Configuration Register.   <i>Offset: 400h</i> */
55508 +       volatile uint32_t hcfg;
55509 +       /** Host Frame Interval Register.       <i>Offset: 404h</i> */
55510 +       volatile uint32_t hfir;
55511 +       /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
55512 +       volatile uint32_t hfnum;
55513 +       /** Reserved.   <i>Offset: 40Ch</i> */
55514 +       uint32_t reserved40C;
55515 +       /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
55516 +       volatile uint32_t hptxsts;
55517 +       /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
55518 +       volatile uint32_t haint;
55519 +       /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
55520 +       volatile uint32_t haintmsk;
55521 +       /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
55522 +       volatile uint32_t hflbaddr;
55523 +} dwc_otg_host_global_regs_t;
55524 +
55525 +/**
55526 + * This union represents the bit fields in the Host Configuration Register.
55527 + * Read the register into the <i>d32</i> member then set/clear the bits using
55528 + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
55529 + */
55530 +typedef union hcfg_data {
55531 +       /** raw register data */
55532 +       uint32_t d32;
55533 +
55534 +       /** register bits */
55535 +       struct {
55536 +               /** FS/LS Phy Clock Select */
55537 +               unsigned fslspclksel:2;
55538 +#define DWC_HCFG_30_60_MHZ 0
55539 +#define DWC_HCFG_48_MHZ           1
55540 +#define DWC_HCFG_6_MHZ    2
55541 +
55542 +               /** FS/LS Only Support */
55543 +               unsigned fslssupp:1;
55544 +               unsigned reserved3_6:4;
55545 +               /** Enable 32-KHz Suspend Mode */
55546 +               unsigned ena32khzs:1;
55547 +               /** Resume Validation Periiod */
55548 +               unsigned resvalid:8;
55549 +               unsigned reserved16_22:7;
55550 +               /** Enable Scatter/gather DMA in Host mode */
55551 +               unsigned descdma:1;
55552 +               /** Frame List Entries */
55553 +               unsigned frlisten:2;
55554 +               /** Enable Periodic Scheduling */
55555 +               unsigned perschedena:1;
55556 +               unsigned reserved27_30:4;
55557 +               unsigned modechtimen:1;
55558 +       } b;
55559 +} hcfg_data_t;
55560 +
55561 +/**
55562 + * This union represents the bit fields in the Host Frame Remaing/Number
55563 + * Register.
55564 + */
55565 +typedef union hfir_data {
55566 +       /** raw register data */
55567 +       uint32_t d32;
55568 +
55569 +       /** register bits */
55570 +       struct {
55571 +               unsigned frint:16;
55572 +               unsigned hfirrldctrl:1;
55573 +               unsigned reserved:15;
55574 +       } b;
55575 +} hfir_data_t;
55576 +
55577 +/**
55578 + * This union represents the bit fields in the Host Frame Remaing/Number
55579 + * Register.
55580 + */
55581 +typedef union hfnum_data {
55582 +       /** raw register data */
55583 +       uint32_t d32;
55584 +
55585 +       /** register bits */
55586 +       struct {
55587 +               unsigned frnum:16;
55588 +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
55589 +               unsigned frrem:16;
55590 +       } b;
55591 +} hfnum_data_t;
55592 +
55593 +typedef union hptxsts_data {
55594 +       /** raw register data */
55595 +       uint32_t d32;
55596 +
55597 +       /** register bits */
55598 +       struct {
55599 +               unsigned ptxfspcavail:16;
55600 +               unsigned ptxqspcavail:8;
55601 +               /** Top of the Periodic Transmit Request Queue
55602 +                *      - bit 24 - Terminate (last entry for the selected channel)
55603 +                *      - bits 26:25 - Token Type
55604 +                *        - 2'b00 - Zero length
55605 +                *        - 2'b01 - Ping
55606 +                *        - 2'b10 - Disable
55607 +                *      - bits 30:27 - Channel Number
55608 +                *      - bit 31 - Odd/even microframe
55609 +                */
55610 +               unsigned ptxqtop_terminate:1;
55611 +               unsigned ptxqtop_token:2;
55612 +               unsigned ptxqtop_chnum:4;
55613 +               unsigned ptxqtop_odd:1;
55614 +       } b;
55615 +} hptxsts_data_t;
55616 +
55617 +/**
55618 + * This union represents the bit fields in the Host Port Control and Status
55619 + * Register. Read the register into the <i>d32</i> member then set/clear the
55620 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55621 + * hprt0 register.
55622 + */
55623 +typedef union hprt0_data {
55624 +       /** raw register data */
55625 +       uint32_t d32;
55626 +       /** register bits */
55627 +       struct {
55628 +               unsigned prtconnsts:1;
55629 +               unsigned prtconndet:1;
55630 +               unsigned prtena:1;
55631 +               unsigned prtenchng:1;
55632 +               unsigned prtovrcurract:1;
55633 +               unsigned prtovrcurrchng:1;
55634 +               unsigned prtres:1;
55635 +               unsigned prtsusp:1;
55636 +               unsigned prtrst:1;
55637 +               unsigned reserved9:1;
55638 +               unsigned prtlnsts:2;
55639 +               unsigned prtpwr:1;
55640 +               unsigned prttstctl:4;
55641 +               unsigned prtspd:2;
55642 +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
55643 +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
55644 +#define DWC_HPRT0_PRTSPD_LOW_SPEED     2
55645 +               unsigned reserved19_31:13;
55646 +       } b;
55647 +} hprt0_data_t;
55648 +
55649 +/**
55650 + * This union represents the bit fields in the Host All Interrupt
55651 + * Register.
55652 + */
55653 +typedef union haint_data {
55654 +       /** raw register data */
55655 +       uint32_t d32;
55656 +       /** register bits */
55657 +       struct {
55658 +               unsigned ch0:1;
55659 +               unsigned ch1:1;
55660 +               unsigned ch2:1;
55661 +               unsigned ch3:1;
55662 +               unsigned ch4:1;
55663 +               unsigned ch5:1;
55664 +               unsigned ch6:1;
55665 +               unsigned ch7:1;
55666 +               unsigned ch8:1;
55667 +               unsigned ch9:1;
55668 +               unsigned ch10:1;
55669 +               unsigned ch11:1;
55670 +               unsigned ch12:1;
55671 +               unsigned ch13:1;
55672 +               unsigned ch14:1;
55673 +               unsigned ch15:1;
55674 +               unsigned reserved:16;
55675 +       } b;
55676 +
55677 +       struct {
55678 +               unsigned chint:16;
55679 +               unsigned reserved:16;
55680 +       } b2;
55681 +} haint_data_t;
55682 +
55683 +/**
55684 + * This union represents the bit fields in the Host All Interrupt
55685 + * Register.
55686 + */
55687 +typedef union haintmsk_data {
55688 +       /** raw register data */
55689 +       uint32_t d32;
55690 +       /** register bits */
55691 +       struct {
55692 +               unsigned ch0:1;
55693 +               unsigned ch1:1;
55694 +               unsigned ch2:1;
55695 +               unsigned ch3:1;
55696 +               unsigned ch4:1;
55697 +               unsigned ch5:1;
55698 +               unsigned ch6:1;
55699 +               unsigned ch7:1;
55700 +               unsigned ch8:1;
55701 +               unsigned ch9:1;
55702 +               unsigned ch10:1;
55703 +               unsigned ch11:1;
55704 +               unsigned ch12:1;
55705 +               unsigned ch13:1;
55706 +               unsigned ch14:1;
55707 +               unsigned ch15:1;
55708 +               unsigned reserved:16;
55709 +       } b;
55710 +
55711 +       struct {
55712 +               unsigned chint:16;
55713 +               unsigned reserved:16;
55714 +       } b2;
55715 +} haintmsk_data_t;
55716 +
55717 +/**
55718 + * Host Channel Specific Registers. <i>500h-5FCh</i>
55719 + */
55720 +typedef struct dwc_otg_hc_regs {
55721 +       /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
55722 +       volatile uint32_t hcchar;
55723 +       /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
55724 +       volatile uint32_t hcsplt;
55725 +       /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
55726 +       volatile uint32_t hcint;
55727 +       /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
55728 +       volatile uint32_t hcintmsk;
55729 +       /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
55730 +       volatile uint32_t hctsiz;
55731 +       /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
55732 +       volatile uint32_t hcdma;
55733 +       volatile uint32_t reserved;
55734 +       /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
55735 +       volatile uint32_t hcdmab;
55736 +} dwc_otg_hc_regs_t;
55737 +
55738 +/**
55739 + * This union represents the bit fields in the Host Channel Characteristics
55740 + * Register. Read the register into the <i>d32</i> member then set/clear the
55741 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55742 + * hcchar register.
55743 + */
55744 +typedef union hcchar_data {
55745 +       /** raw register data */
55746 +       uint32_t d32;
55747 +
55748 +       /** register bits */
55749 +       struct {
55750 +               /** Maximum packet size in bytes */
55751 +               unsigned mps:11;
55752 +
55753 +               /** Endpoint number */
55754 +               unsigned epnum:4;
55755 +
55756 +               /** 0: OUT, 1: IN */
55757 +               unsigned epdir:1;
55758 +
55759 +               unsigned reserved:1;
55760 +
55761 +               /** 0: Full/high speed device, 1: Low speed device */
55762 +               unsigned lspddev:1;
55763 +
55764 +               /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
55765 +               unsigned eptype:2;
55766 +
55767 +               /** Packets per frame for periodic transfers. 0 is reserved. */
55768 +               unsigned multicnt:2;
55769 +
55770 +               /** Device address */
55771 +               unsigned devaddr:7;
55772 +
55773 +               /**
55774 +                * Frame to transmit periodic transaction.
55775 +                * 0: even, 1: odd
55776 +                */
55777 +               unsigned oddfrm:1;
55778 +
55779 +               /** Channel disable */
55780 +               unsigned chdis:1;
55781 +
55782 +               /** Channel enable */
55783 +               unsigned chen:1;
55784 +       } b;
55785 +} hcchar_data_t;
55786 +
55787 +typedef union hcsplt_data {
55788 +       /** raw register data */
55789 +       uint32_t d32;
55790 +
55791 +       /** register bits */
55792 +       struct {
55793 +               /** Port Address */
55794 +               unsigned prtaddr:7;
55795 +
55796 +               /** Hub Address */
55797 +               unsigned hubaddr:7;
55798 +
55799 +               /** Transaction Position */
55800 +               unsigned xactpos:2;
55801 +#define DWC_HCSPLIT_XACTPOS_MID 0
55802 +#define DWC_HCSPLIT_XACTPOS_END 1
55803 +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
55804 +#define DWC_HCSPLIT_XACTPOS_ALL 3
55805 +
55806 +               /** Do Complete Split */
55807 +               unsigned compsplt:1;
55808 +
55809 +               /** Reserved */
55810 +               unsigned reserved:14;
55811 +
55812 +               /** Split Enble */
55813 +               unsigned spltena:1;
55814 +       } b;
55815 +} hcsplt_data_t;
55816 +
55817 +/**
55818 + * This union represents the bit fields in the Host All Interrupt
55819 + * Register.
55820 + */
55821 +typedef union hcint_data {
55822 +       /** raw register data */
55823 +       uint32_t d32;
55824 +       /** register bits */
55825 +       struct {
55826 +               /** Transfer Complete */
55827 +               unsigned xfercomp:1;
55828 +               /** Channel Halted */
55829 +               unsigned chhltd:1;
55830 +               /** AHB Error */
55831 +               unsigned ahberr:1;
55832 +               /** STALL Response Received */
55833 +               unsigned stall:1;
55834 +               /** NAK Response Received */
55835 +               unsigned nak:1;
55836 +               /** ACK Response Received */
55837 +               unsigned ack:1;
55838 +               /** NYET Response Received */
55839 +               unsigned nyet:1;
55840 +               /** Transaction Err */
55841 +               unsigned xacterr:1;
55842 +               /** Babble Error */
55843 +               unsigned bblerr:1;
55844 +               /** Frame Overrun */
55845 +               unsigned frmovrun:1;
55846 +               /** Data Toggle Error */
55847 +               unsigned datatglerr:1;
55848 +               /** Buffer Not Available (only for DDMA mode) */
55849 +               unsigned bna:1;
55850 +               /** Exessive transaction error (only for DDMA mode) */
55851 +               unsigned xcs_xact:1;
55852 +               /** Frame List Rollover interrupt */
55853 +               unsigned frm_list_roll:1;
55854 +               /** Reserved */
55855 +               unsigned reserved14_31:18;
55856 +       } b;
55857 +} hcint_data_t;
55858 +
55859 +/**
55860 + * This union represents the bit fields in the Host Channel Interrupt Mask
55861 + * Register. Read the register into the <i>d32</i> member then set/clear the
55862 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55863 + * hcintmsk register.
55864 + */
55865 +typedef union hcintmsk_data {
55866 +       /** raw register data */
55867 +       uint32_t d32;
55868 +
55869 +       /** register bits */
55870 +       struct {
55871 +               unsigned xfercompl:1;
55872 +               unsigned chhltd:1;
55873 +               unsigned ahberr:1;
55874 +               unsigned stall:1;
55875 +               unsigned nak:1;
55876 +               unsigned ack:1;
55877 +               unsigned nyet:1;
55878 +               unsigned xacterr:1;
55879 +               unsigned bblerr:1;
55880 +               unsigned frmovrun:1;
55881 +               unsigned datatglerr:1;
55882 +               unsigned bna:1;
55883 +               unsigned xcs_xact:1;
55884 +               unsigned frm_list_roll:1;
55885 +               unsigned reserved14_31:18;
55886 +       } b;
55887 +} hcintmsk_data_t;
55888 +
55889 +/**
55890 + * This union represents the bit fields in the Host Channel Transfer Size
55891 + * Register. Read the register into the <i>d32</i> member then set/clear the
55892 + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
55893 + * hcchar register.
55894 + */
55895 +
55896 +typedef union hctsiz_data {
55897 +       /** raw register data */
55898 +       uint32_t d32;
55899 +
55900 +       /** register bits */
55901 +       struct {
55902 +               /** Total transfer size in bytes */
55903 +               unsigned xfersize:19;
55904 +
55905 +               /** Data packets to transfer */
55906 +               unsigned pktcnt:10;
55907 +
55908 +               /**
55909 +                * Packet ID for next data packet
55910 +                * 0: DATA0
55911 +                * 1: DATA2
55912 +                * 2: DATA1
55913 +                * 3: MDATA (non-Control), SETUP (Control)
55914 +                */
55915 +               unsigned pid:2;
55916 +#define DWC_HCTSIZ_DATA0 0
55917 +#define DWC_HCTSIZ_DATA1 2
55918 +#define DWC_HCTSIZ_DATA2 1
55919 +#define DWC_HCTSIZ_MDATA 3
55920 +#define DWC_HCTSIZ_SETUP 3
55921 +
55922 +               /** Do PING protocol when 1 */
55923 +               unsigned dopng:1;
55924 +       } b;
55925 +
55926 +       /** register bits */
55927 +       struct {
55928 +               /** Scheduling information */
55929 +               unsigned schinfo:8;
55930 +
55931 +               /** Number of transfer descriptors.
55932 +                * Max value:
55933 +                * 64 in general,
55934 +                * 256 only for HS isochronous endpoint.
55935 +                */
55936 +               unsigned ntd:8;
55937 +
55938 +               /** Data packets to transfer */
55939 +               unsigned reserved16_28:13;
55940 +
55941 +               /**
55942 +                * Packet ID for next data packet
55943 +                * 0: DATA0
55944 +                * 1: DATA2
55945 +                * 2: DATA1
55946 +                * 3: MDATA (non-Control)
55947 +                */
55948 +               unsigned pid:2;
55949 +
55950 +               /** Do PING protocol when 1 */
55951 +               unsigned dopng:1;
55952 +       } b_ddma;
55953 +} hctsiz_data_t;
55954 +
55955 +/**
55956 + * This union represents the bit fields in the Host DMA Address
55957 + * Register used in Descriptor DMA mode.
55958 + */
55959 +typedef union hcdma_data {
55960 +       /** raw register data */
55961 +       uint32_t d32;
55962 +       /** register bits */
55963 +       struct {
55964 +               unsigned reserved0_2:3;
55965 +               /** Current Transfer Descriptor. Not used for ISOC */
55966 +               unsigned ctd:8;
55967 +               /** Start Address of Descriptor List */
55968 +               unsigned dma_addr:21;
55969 +       } b;
55970 +} hcdma_data_t;
55971 +
55972 +/**
55973 + * This union represents the bit fields in the DMA Descriptor
55974 + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
55975 + * set/clear the bits using the <i>b</i>it elements.
55976 + */
55977 +typedef union host_dma_desc_sts {
55978 +       /** raw register data */
55979 +       uint32_t d32;
55980 +       /** quadlet bits */
55981 +
55982 +       /* for non-isochronous  */
55983 +       struct {
55984 +               /** Number of bytes */
55985 +               unsigned n_bytes:17;
55986 +               /** QTD offset to jump when Short Packet received - only for IN EPs */
55987 +               unsigned qtd_offset:6;
55988 +               /**
55989 +                * Set to request the core to jump to alternate QTD if
55990 +                * Short Packet received - only for IN EPs
55991 +                */
55992 +               unsigned a_qtd:1;
55993 +                /**
55994 +                 * Setup Packet bit. When set indicates that buffer contains
55995 +                 * setup packet.
55996 +                 */
55997 +               unsigned sup:1;
55998 +               /** Interrupt On Complete */
55999 +               unsigned ioc:1;
56000 +               /** End of List */
56001 +               unsigned eol:1;
56002 +               unsigned reserved27:1;
56003 +               /** Rx/Tx Status */
56004 +               unsigned sts:2;
56005 +#define DMA_DESC_STS_PKTERR    1
56006 +               unsigned reserved30:1;
56007 +               /** Active Bit */
56008 +               unsigned a:1;
56009 +       } b;
56010 +       /* for isochronous */
56011 +       struct {
56012 +               /** Number of bytes */
56013 +               unsigned n_bytes:12;
56014 +               unsigned reserved12_24:13;
56015 +               /** Interrupt On Complete */
56016 +               unsigned ioc:1;
56017 +               unsigned reserved26_27:2;
56018 +               /** Rx/Tx Status */
56019 +               unsigned sts:2;
56020 +               unsigned reserved30:1;
56021 +               /** Active Bit */
56022 +               unsigned a:1;
56023 +       } b_isoc;
56024 +} host_dma_desc_sts_t;
56025 +
56026 +#define        MAX_DMA_DESC_SIZE               131071
56027 +#define MAX_DMA_DESC_NUM_GENERIC       64
56028 +#define MAX_DMA_DESC_NUM_HS_ISOC       256
56029 +#define MAX_FRLIST_EN_NUM              64
56030 +/**
56031 + * Host-mode DMA Descriptor structure
56032 + *
56033 + * DMA Descriptor structure contains two quadlets:
56034 + * Status quadlet and Data buffer pointer.
56035 + */
56036 +typedef struct dwc_otg_host_dma_desc {
56037 +       /** DMA Descriptor status quadlet */
56038 +       host_dma_desc_sts_t status;
56039 +       /** DMA Descriptor data buffer pointer */
56040 +       uint32_t buf;
56041 +} dwc_otg_host_dma_desc_t;
56042 +
56043 +/** OTG Host Interface Structure.
56044 + *
56045 + * The OTG Host Interface Structure structure contains information
56046 + * needed to manage the DWC_otg controller acting in host mode. It
56047 + * represents the programming view of the host-specific aspects of the
56048 + * controller.
56049 + */
56050 +typedef struct dwc_otg_host_if {
56051 +       /** Host Global Registers starting at offset 400h.*/
56052 +       dwc_otg_host_global_regs_t *host_global_regs;
56053 +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
56054 +
56055 +       /** Host Port 0 Control and Status Register */
56056 +       volatile uint32_t *hprt0;
56057 +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
56058 +
56059 +       /** Host Channel Specific Registers at offsets 500h-5FCh. */
56060 +       dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
56061 +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
56062 +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
56063 +
56064 +       /* Host configuration information */
56065 +       /** Number of Host Channels (range: 1-16) */
56066 +       uint8_t num_host_channels;
56067 +       /** Periodic EPs supported (0: no, 1: yes) */
56068 +       uint8_t perio_eps_supported;
56069 +       /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
56070 +       uint16_t perio_tx_fifo_size;
56071 +
56072 +} dwc_otg_host_if_t;
56073 +
56074 +/**
56075 + * This union represents the bit fields in the Power and Clock Gating Control
56076 + * Register. Read the register into the <i>d32</i> member then set/clear the
56077 + * bits using the <i>b</i>it elements.
56078 + */
56079 +typedef union pcgcctl_data {
56080 +       /** raw register data */
56081 +       uint32_t d32;
56082 +
56083 +       /** register bits */
56084 +       struct {
56085 +               /** Stop Pclk */
56086 +               unsigned stoppclk:1;
56087 +               /** Gate Hclk */
56088 +               unsigned gatehclk:1;
56089 +               /** Power Clamp */
56090 +               unsigned pwrclmp:1;
56091 +               /** Reset Power Down Modules */
56092 +               unsigned rstpdwnmodule:1;
56093 +               /** Reserved */
56094 +               unsigned reserved:1;
56095 +               /** Enable Sleep Clock Gating (Enbl_L1Gating) */
56096 +               unsigned enbl_sleep_gating:1;
56097 +               /** PHY In Sleep (PhySleep) */
56098 +               unsigned phy_in_sleep:1;
56099 +               /** Deep Sleep*/
56100 +               unsigned deep_sleep:1;
56101 +               unsigned resetaftsusp:1;
56102 +               unsigned restoremode:1;
56103 +               unsigned enbl_extnd_hiber:1;
56104 +               unsigned extnd_hiber_pwrclmp:1;
56105 +               unsigned extnd_hiber_switch:1;
56106 +               unsigned ess_reg_restored:1;
56107 +               unsigned prt_clk_sel:2;
56108 +               unsigned port_power:1;
56109 +               unsigned max_xcvrselect:2;
56110 +               unsigned max_termsel:1;
56111 +               unsigned mac_dev_addr:7;
56112 +               unsigned p2hd_dev_enum_spd:2;
56113 +               unsigned p2hd_prt_spd:2;
56114 +               unsigned if_dev_mode:1;
56115 +       } b;
56116 +} pcgcctl_data_t;
56117 +
56118 +/**
56119 + * This union represents the bit fields in the Global Data FIFO Software
56120 + * Configuration Register. Read the register into the <i>d32</i> member then
56121 + * set/clear the bits using the <i>b</i>it elements.
56122 + */
56123 +typedef union gdfifocfg_data {
56124 +       /* raw register data */
56125 +       uint32_t d32;
56126 +       /** register bits */
56127 +       struct {
56128 +               /** OTG Data FIFO depth */
56129 +               unsigned gdfifocfg:16;
56130 +               /** Start address of EP info controller */
56131 +               unsigned epinfobase:16;
56132 +       } b;
56133 +} gdfifocfg_data_t;
56134 +
56135 +/**
56136 + * This union represents the bit fields in the Global Power Down Register
56137 + * Register. Read the register into the <i>d32</i> member then set/clear the
56138 + * bits using the <i>b</i>it elements.
56139 + */
56140 +typedef union gpwrdn_data {
56141 +       /* raw register data */
56142 +       uint32_t d32;
56143 +
56144 +       /** register bits */
56145 +       struct {
56146 +               /** PMU Interrupt Select */
56147 +               unsigned pmuintsel:1;
56148 +               /** PMU Active */
56149 +               unsigned pmuactv:1;
56150 +               /** Restore */
56151 +               unsigned restore:1;
56152 +               /** Power Down Clamp */
56153 +               unsigned pwrdnclmp:1;
56154 +               /** Power Down Reset */
56155 +               unsigned pwrdnrstn:1;
56156 +               /** Power Down Switch */
56157 +               unsigned pwrdnswtch:1;
56158 +               /** Disable VBUS */
56159 +               unsigned dis_vbus:1;
56160 +               /** Line State Change */
56161 +               unsigned lnstschng:1;
56162 +               /** Line state change mask */
56163 +               unsigned lnstchng_msk:1;
56164 +               /** Reset Detected */
56165 +               unsigned rst_det:1;
56166 +               /** Reset Detect mask */
56167 +               unsigned rst_det_msk:1;
56168 +               /** Disconnect Detected */
56169 +               unsigned disconn_det:1;
56170 +               /** Disconnect Detect mask */
56171 +               unsigned disconn_det_msk:1;
56172 +               /** Connect Detected*/
56173 +               unsigned connect_det:1;
56174 +               /** Connect Detected Mask*/
56175 +               unsigned connect_det_msk:1;
56176 +               /** SRP Detected */
56177 +               unsigned srp_det:1;
56178 +               /** SRP Detect mask */
56179 +               unsigned srp_det_msk:1;
56180 +               /** Status Change Interrupt */
56181 +               unsigned sts_chngint:1;
56182 +               /** Status Change Interrupt Mask */
56183 +               unsigned sts_chngint_msk:1;
56184 +               /** Line State */
56185 +               unsigned linestate:2;
56186 +               /** Indicates current mode(status of IDDIG signal) */
56187 +               unsigned idsts:1;
56188 +               /** B Session Valid signal status*/
56189 +               unsigned bsessvld:1;
56190 +               /** ADP Event Detected */
56191 +               unsigned adp_int:1;
56192 +               /** Multi Valued ID pin */
56193 +               unsigned mult_val_id_bc:5;
56194 +               /** Reserved 24_31 */
56195 +               unsigned reserved29_31:3;
56196 +       } b;
56197 +} gpwrdn_data_t;
56198 +
56199 +#endif
56200 --- /dev/null
56201 +++ b/drivers/usb/host/dwc_otg/test/Makefile
56202 @@ -0,0 +1,16 @@
56203 +
56204 +PERL=/usr/bin/perl
56205 +PL_TESTS=test_sysfs.pl test_mod_param.pl
56206 +
56207 +.PHONY : test
56208 +test : perl_tests
56209 +
56210 +perl_tests :
56211 +       @echo
56212 +       @echo Running perl tests
56213 +       @for test in $(PL_TESTS); do \
56214 +         if $(PERL) ./$$test ; then \
56215 +           echo "=======> $$test, PASSED" ; \
56216 +         else echo "=======> $$test, FAILED" ; \
56217 +         fi \
56218 +       done
56219 --- /dev/null
56220 +++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
56221 @@ -0,0 +1,337 @@
56222 +package dwc_otg_test;
56223 +
56224 +use strict;
56225 +use Exporter ();
56226 +
56227 +use vars qw(@ISA @EXPORT
56228 +$sysfsdir $paramdir $errors $params
56229 +);
56230 +
56231 +@ISA = qw(Exporter);
56232 +
56233 +#
56234 +# Globals
56235 +#
56236 +$sysfsdir = "/sys/devices/lm0";
56237 +$paramdir = "/sys/module/dwc_otg";
56238 +$errors = 0;
56239 +
56240 +$params = [
56241 +          {
56242 +           NAME => "otg_cap",
56243 +           DEFAULT => 0,
56244 +           ENUM => [],
56245 +           LOW => 0,
56246 +           HIGH => 2
56247 +          },
56248 +          {
56249 +           NAME => "dma_enable",
56250 +           DEFAULT => 0,
56251 +           ENUM => [],
56252 +           LOW => 0,
56253 +           HIGH => 1
56254 +          },
56255 +          {
56256 +           NAME => "dma_burst_size",
56257 +           DEFAULT => 32,
56258 +           ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
56259 +           LOW => 1,
56260 +           HIGH => 256
56261 +          },
56262 +          {
56263 +           NAME => "host_speed",
56264 +           DEFAULT => 0,
56265 +           ENUM => [],
56266 +           LOW => 0,
56267 +           HIGH => 1
56268 +          },
56269 +          {
56270 +           NAME => "host_support_fs_ls_low_power",
56271 +           DEFAULT => 0,
56272 +           ENUM => [],
56273 +           LOW => 0,
56274 +           HIGH => 1
56275 +          },
56276 +          {
56277 +           NAME => "host_ls_low_power_phy_clk",
56278 +           DEFAULT => 0,
56279 +           ENUM => [],
56280 +           LOW => 0,
56281 +           HIGH => 1
56282 +          },
56283 +          {
56284 +           NAME => "dev_speed",
56285 +           DEFAULT => 0,
56286 +           ENUM => [],
56287 +           LOW => 0,
56288 +           HIGH => 1
56289 +          },
56290 +          {
56291 +           NAME => "enable_dynamic_fifo",
56292 +           DEFAULT => 1,
56293 +           ENUM => [],
56294 +           LOW => 0,
56295 +           HIGH => 1
56296 +          },
56297 +          {
56298 +           NAME => "data_fifo_size",
56299 +           DEFAULT => 8192,
56300 +           ENUM => [],
56301 +           LOW => 32,
56302 +           HIGH => 32768
56303 +          },
56304 +          {
56305 +           NAME => "dev_rx_fifo_size",
56306 +           DEFAULT => 1064,
56307 +           ENUM => [],
56308 +           LOW => 16,
56309 +           HIGH => 32768
56310 +          },
56311 +          {
56312 +           NAME => "dev_nperio_tx_fifo_size",
56313 +           DEFAULT => 1024,
56314 +           ENUM => [],
56315 +           LOW => 16,
56316 +           HIGH => 32768
56317 +          },
56318 +          {
56319 +           NAME => "dev_perio_tx_fifo_size_1",
56320 +           DEFAULT => 256,
56321 +           ENUM => [],
56322 +           LOW => 4,
56323 +           HIGH => 768
56324 +          },
56325 +          {
56326 +           NAME => "dev_perio_tx_fifo_size_2",
56327 +           DEFAULT => 256,
56328 +           ENUM => [],
56329 +           LOW => 4,
56330 +           HIGH => 768
56331 +          },
56332 +          {
56333 +           NAME => "dev_perio_tx_fifo_size_3",
56334 +           DEFAULT => 256,
56335 +           ENUM => [],
56336 +           LOW => 4,
56337 +           HIGH => 768
56338 +          },
56339 +          {
56340 +           NAME => "dev_perio_tx_fifo_size_4",
56341 +           DEFAULT => 256,
56342 +           ENUM => [],
56343 +           LOW => 4,
56344 +           HIGH => 768
56345 +          },
56346 +          {
56347 +           NAME => "dev_perio_tx_fifo_size_5",
56348 +           DEFAULT => 256,
56349 +           ENUM => [],
56350 +           LOW => 4,
56351 +           HIGH => 768
56352 +          },
56353 +          {
56354 +           NAME => "dev_perio_tx_fifo_size_6",
56355 +           DEFAULT => 256,
56356 +           ENUM => [],
56357 +           LOW => 4,
56358 +           HIGH => 768
56359 +          },
56360 +          {
56361 +           NAME => "dev_perio_tx_fifo_size_7",
56362 +           DEFAULT => 256,
56363 +           ENUM => [],
56364 +           LOW => 4,
56365 +           HIGH => 768
56366 +          },
56367 +          {
56368 +           NAME => "dev_perio_tx_fifo_size_8",
56369 +           DEFAULT => 256,
56370 +           ENUM => [],
56371 +           LOW => 4,
56372 +           HIGH => 768
56373 +          },
56374 +          {
56375 +           NAME => "dev_perio_tx_fifo_size_9",
56376 +           DEFAULT => 256,
56377 +           ENUM => [],
56378 +           LOW => 4,
56379 +           HIGH => 768
56380 +          },
56381 +          {
56382 +           NAME => "dev_perio_tx_fifo_size_10",
56383 +           DEFAULT => 256,
56384 +           ENUM => [],
56385 +           LOW => 4,
56386 +           HIGH => 768
56387 +          },
56388 +          {
56389 +           NAME => "dev_perio_tx_fifo_size_11",
56390 +           DEFAULT => 256,
56391 +           ENUM => [],
56392 +           LOW => 4,
56393 +           HIGH => 768
56394 +          },
56395 +          {
56396 +           NAME => "dev_perio_tx_fifo_size_12",
56397 +           DEFAULT => 256,
56398 +           ENUM => [],
56399 +           LOW => 4,
56400 +           HIGH => 768
56401 +          },
56402 +          {
56403 +           NAME => "dev_perio_tx_fifo_size_13",
56404 +           DEFAULT => 256,
56405 +           ENUM => [],
56406 +           LOW => 4,
56407 +           HIGH => 768
56408 +          },
56409 +          {
56410 +           NAME => "dev_perio_tx_fifo_size_14",
56411 +           DEFAULT => 256,
56412 +           ENUM => [],
56413 +           LOW => 4,
56414 +           HIGH => 768
56415 +          },
56416 +          {
56417 +           NAME => "dev_perio_tx_fifo_size_15",
56418 +           DEFAULT => 256,
56419 +           ENUM => [],
56420 +           LOW => 4,
56421 +           HIGH => 768
56422 +          },
56423 +          {
56424 +           NAME => "host_rx_fifo_size",
56425 +           DEFAULT => 1024,
56426 +           ENUM => [],
56427 +           LOW => 16,
56428 +           HIGH => 32768
56429 +          },
56430 +          {
56431 +           NAME => "host_nperio_tx_fifo_size",
56432 +           DEFAULT => 1024,
56433 +           ENUM => [],
56434 +           LOW => 16,
56435 +           HIGH => 32768
56436 +          },
56437 +          {
56438 +           NAME => "host_perio_tx_fifo_size",
56439 +           DEFAULT => 1024,
56440 +           ENUM => [],
56441 +           LOW => 16,
56442 +           HIGH => 32768
56443 +          },
56444 +          {
56445 +           NAME => "max_transfer_size",
56446 +           DEFAULT => 65535,
56447 +           ENUM => [],
56448 +           LOW => 2047,
56449 +           HIGH => 65535
56450 +          },
56451 +          {
56452 +           NAME => "max_packet_count",
56453 +           DEFAULT => 511,
56454 +           ENUM => [],
56455 +           LOW => 15,
56456 +           HIGH => 511
56457 +          },
56458 +          {
56459 +           NAME => "host_channels",
56460 +           DEFAULT => 12,
56461 +           ENUM => [],
56462 +           LOW => 1,
56463 +           HIGH => 16
56464 +          },
56465 +          {
56466 +           NAME => "dev_endpoints",
56467 +           DEFAULT => 6,
56468 +           ENUM => [],
56469 +           LOW => 1,
56470 +           HIGH => 15
56471 +          },
56472 +          {
56473 +           NAME => "phy_type",
56474 +           DEFAULT => 1,
56475 +           ENUM => [],
56476 +           LOW => 0,
56477 +           HIGH => 2
56478 +          },
56479 +          {
56480 +           NAME => "phy_utmi_width",
56481 +           DEFAULT => 16,
56482 +           ENUM => [8, 16],
56483 +           LOW => 8,
56484 +           HIGH => 16
56485 +          },
56486 +          {
56487 +           NAME => "phy_ulpi_ddr",
56488 +           DEFAULT => 0,
56489 +           ENUM => [],
56490 +           LOW => 0,
56491 +           HIGH => 1
56492 +          },
56493 +         ];
56494 +
56495 +
56496 +#
56497 +#
56498 +sub check_arch {
56499 +  $_ = `uname -m`;
56500 +  chomp;
56501 +  unless (m/armv4tl/) {
56502 +    warn "# \n# Can't execute on $_.  Run on integrator platform.\n# \n";
56503 +    return 0;
56504 +  }
56505 +  return 1;
56506 +}
56507 +
56508 +#
56509 +#
56510 +sub load_module {
56511 +  my $params = shift;
56512 +  print "\nRemoving Module\n";
56513 +  system "rmmod dwc_otg";
56514 +  print "Loading Module\n";
56515 +  if ($params ne "") {
56516 +    print "Module Parameters: $params\n";
56517 +  }
56518 +  if (system("modprobe dwc_otg $params")) {
56519 +    warn "Unable to load module\n";
56520 +    return 0;
56521 +  }
56522 +  return 1;
56523 +}
56524 +
56525 +#
56526 +#
56527 +sub test_status {
56528 +  my $arg = shift;
56529 +
56530 +  print "\n";
56531 +
56532 +  if (defined $arg) {
56533 +    warn "WARNING: $arg\n";
56534 +  }
56535 +
56536 +  if ($errors > 0) {
56537 +    warn "TEST FAILED with $errors errors\n";
56538 +    return 0;
56539 +  } else {
56540 +    print "TEST PASSED\n";
56541 +    return 0 if (defined $arg);
56542 +  }
56543 +  return 1;
56544 +}
56545 +
56546 +#
56547 +#
56548 +@EXPORT = qw(
56549 +$sysfsdir
56550 +$paramdir
56551 +$params
56552 +$errors
56553 +check_arch
56554 +load_module
56555 +test_status
56556 +);
56557 +
56558 +1;
56559 --- /dev/null
56560 +++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
56561 @@ -0,0 +1,133 @@
56562 +#!/usr/bin/perl -w
56563 +#
56564 +# Run this program on the integrator.
56565 +#
56566 +# - Tests module parameter default values.
56567 +# - Tests setting of valid module parameter values via modprobe.
56568 +# - Tests invalid module parameter values.
56569 +# -----------------------------------------------------------------------------
56570 +use strict;
56571 +use dwc_otg_test;
56572 +
56573 +check_arch() or die;
56574 +
56575 +#
56576 +#
56577 +sub test {
56578 +  my ($param,$expected) = @_;
56579 +  my $value = get($param);
56580 +
56581 +  if ($value == $expected) {
56582 +    print "$param = $value, okay\n";
56583 +  }
56584 +
56585 +  else {
56586 +    warn "ERROR: value of $param != $expected, $value\n";
56587 +    $errors ++;
56588 +  }
56589 +}
56590 +
56591 +#
56592 +#
56593 +sub get {
56594 +  my $param = shift;
56595 +  my $tmp = `cat $paramdir/$param`;
56596 +  chomp $tmp;
56597 +  return $tmp;
56598 +}
56599 +
56600 +#
56601 +#
56602 +sub test_main {
56603 +
56604 +  print "\nTesting Module Parameters\n";
56605 +
56606 +  load_module("") or die;
56607 +
56608 +  # Test initial values
56609 +  print "\nTesting Default Values\n";
56610 +  foreach (@{$params}) {
56611 +    test ($_->{NAME}, $_->{DEFAULT});
56612 +  }
56613 +
56614 +  # Test low value
56615 +  print "\nTesting Low Value\n";
56616 +  my $cmd_params = "";
56617 +  foreach (@{$params}) {
56618 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
56619 +  }
56620 +  load_module($cmd_params) or die;
56621 +
56622 +  foreach (@{$params}) {
56623 +    test ($_->{NAME}, $_->{LOW});
56624 +  }
56625 +
56626 +  # Test high value
56627 +  print "\nTesting High Value\n";
56628 +  $cmd_params = "";
56629 +  foreach (@{$params}) {
56630 +    $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
56631 +  }
56632 +  load_module($cmd_params) or die;
56633 +
56634 +  foreach (@{$params}) {
56635 +    test ($_->{NAME}, $_->{HIGH});
56636 +  }
56637 +
56638 +  # Test Enum
56639 +  print "\nTesting Enumerated\n";
56640 +  foreach (@{$params}) {
56641 +    if (defined $_->{ENUM}) {
56642 +      my $value;
56643 +      foreach $value (@{$_->{ENUM}}) {
56644 +       $cmd_params = "$_->{NAME}=$value";
56645 +       load_module($cmd_params) or die;
56646 +       test ($_->{NAME}, $value);
56647 +      }
56648 +    }
56649 +  }
56650 +
56651 +  # Test Invalid Values
56652 +  print "\nTesting Invalid Values\n";
56653 +  $cmd_params = "";
56654 +  foreach (@{$params}) {
56655 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
56656 +  }
56657 +  load_module($cmd_params) or die;
56658 +
56659 +  foreach (@{$params}) {
56660 +    test ($_->{NAME}, $_->{DEFAULT});
56661 +  }
56662 +
56663 +  $cmd_params = "";
56664 +  foreach (@{$params}) {
56665 +    $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
56666 +  }
56667 +  load_module($cmd_params) or die;
56668 +
56669 +  foreach (@{$params}) {
56670 +    test ($_->{NAME}, $_->{DEFAULT});
56671 +  }
56672 +
56673 +  print "\nTesting Enumerated\n";
56674 +  foreach (@{$params}) {
56675 +    if (defined $_->{ENUM}) {
56676 +      my $value;
56677 +      foreach $value (@{$_->{ENUM}}) {
56678 +       $value = $value + 1;
56679 +       $cmd_params = "$_->{NAME}=$value";
56680 +       load_module($cmd_params) or die;
56681 +       test ($_->{NAME}, $_->{DEFAULT});
56682 +       $value = $value - 2;
56683 +       $cmd_params = "$_->{NAME}=$value";
56684 +       load_module($cmd_params) or die;
56685 +       test ($_->{NAME}, $_->{DEFAULT});
56686 +      }
56687 +    }
56688 +  }
56689 +
56690 +  test_status() or die;
56691 +}
56692 +
56693 +test_main();
56694 +0;
56695 --- /dev/null
56696 +++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
56697 @@ -0,0 +1,193 @@
56698 +#!/usr/bin/perl -w
56699 +#
56700 +# Run this program on the integrator
56701 +# - Tests select sysfs attributes.
56702 +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
56703 +# -----------------------------------------------------------------------------
56704 +use strict;
56705 +use dwc_otg_test;
56706 +
56707 +check_arch() or die;
56708 +
56709 +#
56710 +#
56711 +sub test {
56712 +  my ($attr,$expected) = @_;
56713 +  my $string = get($attr);
56714 +
56715 +  if ($string eq $expected) {
56716 +    printf("$attr = $string, okay\n");
56717 +  }
56718 +  else {
56719 +    warn "ERROR: value of $attr != $expected, $string\n";
56720 +    $errors ++;
56721 +  }
56722 +}
56723 +
56724 +#
56725 +#
56726 +sub set {
56727 +  my ($reg, $value) = @_;
56728 +  system "echo $value > $sysfsdir/$reg";
56729 +}
56730 +
56731 +#
56732 +#
56733 +sub get {
56734 +  my $attr = shift;
56735 +  my $string = `cat $sysfsdir/$attr`;
56736 +  chomp $string;
56737 +  if ($string =~ m/\s\=\s/) {
56738 +    my $tmp;
56739 +    ($tmp, $string) = split /\s=\s/, $string;
56740 +  }
56741 +  return $string;
56742 +}
56743 +
56744 +#
56745 +#
56746 +sub test_main {
56747 +  print("\nTesting Sysfs Attributes\n");
56748 +
56749 +  load_module("") or die;
56750 +
56751 +  # Test initial values of regoffset/regvalue/guid/gsnpsid
56752 +  print("\nTesting Default Values\n");
56753 +
56754 +  test("regoffset", "0xffffffff");
56755 +  test("regvalue", "invalid offset");
56756 +  test("guid", "0x12345678");  # this will fail if it has been changed
56757 +  test("gsnpsid", "0x4f54200a");
56758 +
56759 +  # Test operation of regoffset/regvalue
56760 +  print("\nTesting regoffset\n");
56761 +  set('regoffset', '5a5a5a5a');
56762 +  test("regoffset", "0xffffffff");
56763 +
56764 +  set('regoffset', '0');
56765 +  test("regoffset", "0x00000000");
56766 +
56767 +  set('regoffset', '40000');
56768 +  test("regoffset", "0x00000000");
56769 +
56770 +  set('regoffset', '3ffff');
56771 +  test("regoffset", "0x0003ffff");
56772 +
56773 +  set('regoffset', '1');
56774 +  test("regoffset", "0x00000001");
56775 +
56776 +  print("\nTesting regvalue\n");
56777 +  set('regoffset', '3c');
56778 +  test("regvalue", "0x12345678");
56779 +  set('regvalue', '5a5a5a5a');
56780 +  test("regvalue", "0x5a5a5a5a");
56781 +  set('regvalue','a5a5a5a5');
56782 +  test("regvalue", "0xa5a5a5a5");
56783 +  set('guid','12345678');
56784 +
56785 +  # Test HNP Capable
56786 +  print("\nTesting HNP Capable bit\n");
56787 +  set('hnpcapable', '1');
56788 +  test("hnpcapable", "0x1");
56789 +  set('hnpcapable','0');
56790 +  test("hnpcapable", "0x0");
56791 +
56792 +  set('regoffset','0c');
56793 +
56794 +  my $old = get('gusbcfg');
56795 +  print("setting hnpcapable\n");
56796 +  set('hnpcapable', '1');
56797 +  test("hnpcapable", "0x1");
56798 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
56799 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
56800 +
56801 +  $old = get('gusbcfg');
56802 +  print("clearing hnpcapable\n");
56803 +  set('hnpcapable', '0');
56804 +  test("hnpcapable", "0x0");
56805 +  test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56806 +  test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
56807 +
56808 +  # Test SRP Capable
56809 +  print("\nTesting SRP Capable bit\n");
56810 +  set('srpcapable', '1');
56811 +  test("srpcapable", "0x1");
56812 +  set('srpcapable','0');
56813 +  test("srpcapable", "0x0");
56814 +
56815 +  set('regoffset','0c');
56816 +
56817 +  $old = get('gusbcfg');
56818 +  print("setting srpcapable\n");
56819 +  set('srpcapable', '1');
56820 +  test("srpcapable", "0x1");
56821 +  test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
56822 +  test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
56823 +
56824 +  $old = get('gusbcfg');
56825 +  print("clearing srpcapable\n");
56826 +  set('srpcapable', '0');
56827 +  test("srpcapable", "0x0");
56828 +  test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
56829 +  test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
56830 +
56831 +  # Test GGPIO
56832 +  print("\nTesting GGPIO\n");
56833 +  set('ggpio','5a5a5a5a');
56834 +  test('ggpio','0x5a5a0000');
56835 +  set('ggpio','a5a5a5a5');
56836 +  test('ggpio','0xa5a50000');
56837 +  set('ggpio','11110000');
56838 +  test('ggpio','0x11110000');
56839 +  set('ggpio','00001111');
56840 +  test('ggpio','0x00000000');
56841 +
56842 +  # Test DEVSPEED
56843 +  print("\nTesting DEVSPEED\n");
56844 +  set('regoffset','800');
56845 +  $old = get('regvalue');
56846 +  set('devspeed','0');
56847 +  test('devspeed','0x0');
56848 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
56849 +  set('devspeed','1');
56850 +  test('devspeed','0x1');
56851 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
56852 +  set('devspeed','2');
56853 +  test('devspeed','0x2');
56854 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
56855 +  set('devspeed','3');
56856 +  test('devspeed','0x3');
56857 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
56858 +  set('devspeed','4');
56859 +  test('devspeed','0x0');
56860 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
56861 +  set('devspeed','5');
56862 +  test('devspeed','0x1');
56863 +  test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
56864 +
56865 +
56866 +  #  mode      Returns the current mode:0 for device mode1 for host mode       Read
56867 +  #  hnp       Initiate the Host Negotiation Protocol.  Read returns the status.       Read/Write
56868 +  #  srp       Initiate the Session Request Protocol.  Read returns the status.        Read/Write
56869 +  #  buspower  Get or Set the Power State of the bus (0 - Off or 1 - On)       Read/Write
56870 +  #  bussuspend        Suspend the USB bus.    Read/Write
56871 +  #  busconnected      Get the connection status of the bus    Read
56872 +
56873 +  #  gotgctl   Get or set the Core Control Status Register.    Read/Write
56874 +  ##  gusbcfg  Get or set the Core USB Configuration Register  Read/Write
56875 +  #  grxfsiz   Get or set the Receive FIFO Size Register       Read/Write
56876 +  #  gnptxfsiz Get or set the non-periodic Transmit Size Register      Read/Write
56877 +  #  gpvndctl  Get or set the PHY Vendor Control Register      Read/Write
56878 +  ##  ggpio    Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
56879 +  ##  guid     Get or set the value of the User ID Register    Read/Write
56880 +  ##  gsnpsid  Get the value of the Synopsys ID Regester       Read
56881 +  ##  devspeed Get or set the device speed setting in the DCFG register        Read/Write
56882 +  #  enumspeed Gets the device enumeration Speed.      Read
56883 +  #  hptxfsiz  Get the value of the Host Periodic Transmit FIFO        Read
56884 +  #  hprt0     Get or Set the value in the Host Port Control and Status Register       Read/Write
56885 +
56886 +  test_status("TEST NYI") or die;
56887 +}
56888 +
56889 +test_main();
56890 +0;